1

There are two different spots where the check happens.

That is, where you enter a, s, m, d, or q and when you enter the first and second number.

At any of the checks, if the check is false, it should ask you to re-enter your input.

I'm guessing this can be done by putting a scanf statement for the numbers part inside a while loop check, but when I enter an invalid value (non-number) the loop runs infinitely.

So I must be doing something wrong. I have made the a, s, m, d, and q part work for the most part.

But the second part never seems to work. For this, I left my failed attempts at the while loops out, and instead in //comments.

Any help would be greatly appreciated! Here is my code so far:

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char ch;
    float num1,num2,answer;
    printf("Enter the operation of your choice:\n");
    printf("a. add      s. subtract\n");
    printf("m. multiply q. divide\n");
    printf("q. quit\n");
    while ((ch = getchar())!='q')
    {
        printf("Enter the operation of your choice:\n");
        printf("a. add      s. subtract\n");
        printf("m. multiply q. divide\n");
        printf("q. quit\n");
        ch=tolower(ch);
        if (ch=='\n')
            continue;
        else
        {
            switch(ch)
            {
                case 'a':
                //The code below is what I have tried to make work.
                //This code would also be copy pasted to the other cases,
                //of course with the correct operations respectively being used.
                //
                //printf("Enter first number: ")
                //while(scanf("%f",&num1)==0)
                //{
                //  printf("Invalid input. Please enter a number.");
                //  scanf("%f",&num1);
                //}
                //printf("Enter second number: ")
                //while(scanf("%f",&num2)==0)
                //{
                //  printf("Invalid input. Please enter a number.");
                //  scanf("%f",&num2);
                //}
                //answer = num1 + num2;
                //printf("%f + %f = %f\n",num1,num2,answer);
                //break;
                //
                //I have also tried to make this work using do-while loops
                printf("Enter first number: ");
                scanf("%f",&num1);
                printf("Enter second number: ");
                scanf("%f",&num2);
                answer = num1 + num2;
                printf("%f + %f = %f\n",num1,num2,answer);
                break;
            case 's':
                printf("Enter first number: ");
                scanf("%f",&num1);
                printf("Enter second number: ");
                scanf("%f",&num2);
                answer = num1 - num2;
                printf("%f - %f = %f\n",num1,num2,answer);
                break;
            case 'm':
                printf("Enter first number: ");
                scanf("%f",&num1);
                printf("Enter second number: ");
                scanf("%f",&num2);
                answer = num1 * num2;
                printf("%f * %f = %f\n",num1,num2,answer);
                break;
            case 'd':
                printf("Enter first number: ");
                scanf("%f",&num1);
                printf("Enter second number: ");
                scanf("%f",&num2);
                answer = num1 / num2;
                printf("%f / %f = %f\n",num1,num2,answer);
                break;
            default:
                printf("That is not a valid operation.\n");
                break;
        }
    }
}
return 0;
}

Again, thanks for any help! Ya'll would be a life saver! Cheers! -Will S.

EDIT: I got my code to work! Here is the final code...

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char ch;
    float num1,num2,answer;
    printf("Enter the operation of your choice:\n");
    printf("a. add      s. subtract\n");
    printf("m. multiply q. divide\n");
    printf("q. quit\n");
    while ((ch = getchar())!='q')
    {
        ch=tolower(ch);
        //Ignore whitespace
        if (ch=='\n')
            continue;
        else
        {
            switch(ch)
            {
                //Addition part
                case 'a':
                    //First number
                    printf("Enter first number: ");
                    //Check to see if input is a number
                while (scanf("%f",&num1)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                //Second number
                printf("Enter second number: ");
                while (scanf("%f",&num2)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                //Do math for respective operation
                answer = num1 + num2;
                //Print out result
                printf("%.3f + %.3f = %.3f\n", num1,num2,answer);
                break;
            //Subtraction part
            case 's':
                printf("Enter first number: ");
                while (scanf("%f",&num1)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                printf("Enter second number: ");
                while (scanf("%f",&num2)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                answer = num1 - num2;
                printf("%.3f - %.3f = %.3f\n", num1,num2,answer);
                break;
            //Multiplication part
            case 'm':
                printf("Enter first number: ");
                while (scanf("%f",&num1)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                printf("Enter second number: ");
                while (scanf("%f",&num2)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                answer = num1 * num2;
                printf("%.3f * %.3f = %.3f\n", num1,num2,answer);
                break;
            //Division part
            case 'd':
                printf("Enter first number: ");
                while (scanf("%f",&num1)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                printf("Enter second number: ");
                while (scanf("%f",&num2)==0)
                {
                    printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                    scanf("%*s");
                }
                //Check for if number is a zero
                while (num2==0)
                {
                    printf("Please enter a non-zero number, such as 2.5, -1.78E8, or 3: ");
                    while (scanf("%f",&num2)==0)
                    {
                        printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
                        scanf("%*s");
                    }
                }
                answer = num1 / num2;
                printf("%.3f / %.3f = %.3f\n", num1,num2,answer);
                break;
            //For if a non-valid operation is entered
            default:
                printf("That is not a valid operation.\n");
                break;
        }
    }
    printf("Enter the operation of your choice:\n");
    printf("a. add      s. subtract\n");
    printf("m. multiply q. divide\n");
    printf("q. quit\n");
}
printf("Bye.\n");
return 0;

}

Looking back at it, I probably could do without the if/else statement.

King Sutter
  • 61
  • 2
  • 4
  • 11
  • In every case of your switch(), if you detect a wrong input, you could simply ignore the input, print a "input ignored, start again", and `break`. The user will have to select again the operation. Otherwise, you must use a loop, or a function with a loop inside which gets a number. – linuxfan says Reinstate Monica Feb 26 '17 at 08:49
  • the function: `getchar()` returns a `int`, not a `char`. so the declartion of `ch` is not correct – user3629249 Feb 26 '17 at 22:28
  • the code will output the menu more than once because for the user to enter a char, they must also press the /enter/return/ key The next call to `getchar()` retrieves the '\n' key. To avoid this, empty the `stdin` stream, with something similar to: `while( (ch == getchar()) != EOF && '\n' != ch );` – user3629249 Feb 26 '17 at 22:32
  • when calling any of the `scanf()` family of functions, always check the returned value (not the parameter values) to assure the operation was successful – user3629249 Feb 26 '17 at 22:34
  • Note: the calls to `scanf()` also leave the '\n' in the `stdin` stream, so need to be consumed before calling `scanf()` to input the next action. – user3629249 Feb 26 '17 at 22:37
  • for ease of readability and understanding, please consistently indent the code. – user3629249 Feb 26 '17 at 22:39
  • @user3629249 It can be converted to char so it is ok. – Suraj Jain Feb 27 '17 at 07:56
  • @user3629249 Also That Would Be Needed Only When Scanning int. – Suraj Jain Feb 27 '17 at 07:56
  • @user3629249 Is My Answer below correct , i wanted to confirm or is there something i missed – Suraj Jain Feb 27 '17 at 12:55
  • There's a lot of repetition in the code — more in the code that detects and attempts to recover from faulty input. Time for a function — or several functions. Consider writing a function that is given a prompt, a pointer to a integer to receive the value that's read, and that loops, cleans, reprompts, etc, and returns an indication of success or failure. It might, amongst other things, count the number of attempts. If you don't get a number within some number of attempts (5, perhaps 10), it might report failure and return. Then use that, possibly inside a function that prompts for two values. – Jonathan Leffler Feb 27 '17 at 15:12
  • I think I figured it out. Thanks all for any and all suggestions and tips and overall help! I'll post my final code in just a second for anyone who happens to search this later. – King Sutter Feb 27 '17 at 15:18
  • @KingSutter Does My Answer Helped You ?? – Suraj Jain Feb 28 '17 at 07:16
  • @SurajJain, Suggest you learn about 1) signed/unsigned char, 2) sign extension, 3) why the returned value from `getchar()` should be assigned to an `int`, NOT a `char` variable, especially as that pertains to the EOF value. – user3629249 Feb 28 '17 at 08:31
  • @user3629249 Sir , getchar returns unsigned char converted to int. I later thought about that EOF , sorry. And i need to talk to you about something , can we chat ? – Suraj Jain Feb 28 '17 at 16:18
  • I don't know how to enter chat mode without the system already having initiated it. If you know, post as comment. Which I'll eventually see. – user3629249 Mar 01 '17 at 19:17
  • @SurajJain, per the man page, `getchar()` returns an `int`, not an `unsigned int`. here is the syntax for `getchar()` "int getchar(void);" – user3629249 Mar 01 '17 at 19:23
  • @user3629249 Sir, Please Come here http://chat.stackoverflow.com/rooms/137009/talk-for-c – Suraj Jain Mar 02 '17 at 02:29

2 Answers2

2
while(scanf("%f",&num1)==0)
{
     printf("Invalid input. Please enter a number.");
      scanf("%f",&num1);
 }

This loops scans two numbers per iteration. This is not what you want. Lose the second scanf.

You should also check for EOF and errors.

int result;
while((result = scanf("%f",&num1))==0)
{
     printf("Invalid input. Please enter a number.");
}

if (result == EOF) .... report an error and exit ...
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
2

There are multiple problems with your code. First of all in this loop

  1. You are taking input two times on failure

    while(scanf("%f",&num1)==0)   //Taking Input Here Once
    {
        printf("Invalid input. Please enter a number.");
        scanf("%f",&num1);             //Again Taking input.
    }
    

    Instead what you wanted was to check the return value of the scanf() and if it was 0 you would execute the loop again, so this would be the way to do that:

    int l = 0;
    
    while(l==0){  //Checking l, if it is zero or not, if zero running loop again.
        printf("Invalid input. Please enter a number.");
        l = scanf("%f",&num1);                   //Storing Return Value of scanf in l   
    }
    
  2. When the program will encounter any line with scanf("%f" , &num1) or scanf("%f" , &num2), it will skip all the white spaces and wait for next input. In the case where the input does not match the format specification, then the input isn't consumed and remains in the input buffer.

    int l = 0;
    
    while(l==0){  //Checking l 
    
         printf("Invalid input. Please enter a number.");
         l = scanf("%f",&num1);  //scanf will look at the buffer if the input
                                 //does not match, it will not be consumed 
                                 //and will remain in buffer.       
    }
    

    In other words, the character that doesn't match is never read. So when you type e.g. an a character, your code will loop indefinitely as scanf continues to fail on the same character.

  3. When the program executes its last scanf("%f",&num2) call then because of the enter there is a newline \n character present in buffer and so due to ch = getchar(), new line \n gets stored in ch and the following if condition satisfies and the loop execute again.

     if(ch =='\n')
         continue;
    
Suraj Jain
  • 4,463
  • 28
  • 39