0

I'm new here and this is my only coding class since I'm an engineering major. I've been developing a scientific calculator in C. I've been using functions for each operation and I'm using a while loop in order to either loop around and perform more calculations, or break the loop and end the code when the user inputs Q. The problem is, my code is looping regardless and is not giving me the option to input my characters. I have included all the necessary libraries so I won't be posting them in this code excerpt.

void remove_crlf(char *s){   char *t = s + strlen(s);   // t begins at the null sentinel at the end of s.   
t--;   
/* t is now at the last character of s - unless s didn't contain any characters,in        
which case, t is now *BEFORE* s.  We have to keep checking for that. */   
/* We repeat until EITHER t slides to the left of s, OR we find a character that is        
not a line feed (\n) or a carriage return (\r). */   
while ((t >= s) && (*t == '\n' || *t == '\r'))  
 {      
     *t = '\0'; // Clobber the character t is pointing at.      
     t--;       // Decrement t.   
     }
}

double addition(double x, double y)
{
    return (x + y);
}

int main(void)
{
    int n;
    double x, y;
    double answer;
    char s[64];
    FILE *ofp;
    ofp = fopen("project.txt", "a");

    while (1)
    {
        printf("Enter the correct number in order to pursue your desired operation.\n");
        printf(" 1.Addition\n");
        scanf("%d", &n);

        if (n == 1)
        {
            printf("Enter your first value: ");
            scanf("%lf", &x);
            fprintf(ofp, " %lf", x);
            fprintf(ofp, " +");
            printf("Enter your second value: ");
            scanf("%lf", &y);
            fprintf(ofp, " %lf", y);
            answer = addition(x, y);
            printf("%lf\n", answer);
            fprintf(ofp, " = %lf\n", answer);
        }
        printf("Would you like to perform more calculations?\n Press Q to quit.\n Press any other character to perform more calculations.\n");
        fgets(s, 63, stdin);
        remove_crlf(s);

        if (strcasecmp(s, "Q") == 0)
        {
            break;
        }
        
        else{
        }

So this is just an example of how my code is formatted. I have many functions but all work the same way that the addition function works and I have about 16 different operations. Remove_crlf is a function I used in a previous code, and was provided by my professor although I'm not really sure what it does. I am also printing to a txt file but that shouldn't matter much. Any feedback is helpful and sorry if I did not ask my question correctly. Thank you!

  • 1
    Your fscanf is telling it to read a number, but then you enter a number and press enter. The enter key is now in the keyboard buffer and hasn't been read yet. Then your fgets reads a bunch of characters up to and including an enter key - and because there is an enter key in the keyboard buffer it reads that text. So you never have the chance to press Q because an empty string ending with an enter key was already read. So, you could do an fgets after each fscanf to gobble up the enter key that is left behind. Then the fgets that asks for a Q will have an empty keyboard buffer to read from. – Jerry Jeremiah Dec 08 '20 at 01:54
  • I see. Rather than using an fgets after the scanf, can I include something in the scanf to gobble up this enter key or would only fgets do that? EDIT: I did that and it worked!! Thank you so much. I might just add that after every scanf in each of my functions, lot of work but it will do the trick. Thanks so much. – machinekillx Dec 08 '20 at 01:55
  • 1
    Because your code is not removing the enter key from the keyboard buffer, your code would work if you typed `1 2 3 Q` all on one line and pressing enter when you are asked for the operation. – Jerry Jeremiah Dec 08 '20 at 01:56
  • No worries. Already added fgets after each scanf in each function. Wasn't much of a hassle. Thanks for your help, I appreciate it. – machinekillx Dec 08 '20 at 02:01
  • Technically you don't need it after every scanf because scanf("%d",...) and scanf("%f",...) will ignore whitespace so the previous enter key will be ignored. You only need it between the last scanf and the fgets. So you could just put one before your `printf("Would you like to perform more calculations?...` as long as you are sure that the last thing before that was a scanf("%d",...) or scanf("%f",...). I think that is rather fragile because inserting a fgets earlier can then break your program unexpectedly. That's why I suggested doing it after each scanf instead of before the fgets. – Jerry Jeremiah Dec 08 '20 at 02:16
  • In-Depth [How can I stop taking inputs from user when I press the key 'q'?](https://stackoverflow.com/a/65164824/3422102) -- more than you ever wanted to know... – David C. Rankin Dec 08 '20 at 03:28
  • Consider only using `fgets()` and not `scanf()`. – chux - Reinstate Monica Dec 08 '20 at 03:28
  • 1
    Minor: off by 1: `char s[64]; fgets(s, 63, stdin);` --> `fgets(s, 64, stdin);` or even better `fgets(s, sizeof s, stdin);` – chux - Reinstate Monica Dec 08 '20 at 03:30
  • (at least that off-by-one was in the right direction `:)` – David C. Rankin Dec 08 '20 at 03:32

0 Answers0