2

Greetings , to cut it short , below is the code

The Code

// This program would sum up all the integer provided by user

#include <stdio.h>

int main(void)
{
 int sum = 0;                  // initialize and declare variable
 int num;
 char check;
 int status;

 printf("Please enter an integer to be summed :"); // prompt user for an integer
 status = scanf("%d" , &num);                                

  while(status == 1)                              //If user enter an integer , while loop test condition is true
  {
    sum = sum + num;                           //sum the input integer
    printf("Do you wanna add more integer?(y/n) :");   //Asking for user next action
    scanf("%c" , &check);

          if(check == 'y')                   //Check user's answer

        status = scanf("%d" , &num);

    else

        status = 0;

  }


 return 0;
}

The problem

The first thing I do when I run the program is to provide an integer , after that it would just print out the control-string Do you wanna add more integer?(y/n) :.Then the problem arouse , instead of waiting for me to type y or n , the program would just end itself , which mean in Windows command prompt it would give me the line Press any key to continue.....

I keep read through the code line by line to find any semantic error (assume there's no syntax error since compiler would've complained if there's one) or any logical error that I made , but to no avail.So I suspect is it there's any rules of C that mention We shouldn't prompt use if() with character as test value when it is enclosed in while() loop or any other thing that I've neglected??

Thanks for keeping yourself tied up to read my problem , hope I would really learn from you guys, do point out any mistake I made as I'm a learner who ready to accept any comment or teaching that is correct.

caramel1995
  • 2,968
  • 10
  • 44
  • 57
  • 1
    please be more precise in the headline of the question. if you don't needed help, you wouldn't be asking, and hopefully also, you are asking because you can't figure out yourself. Your heading fits to all questions asked on SO. – Jens Gustedt Jun 04 '11 at 21:04
  • Please ignore everyone telling you to use fflush(stdin), they don't know what the are talking about. Check this [C FAQ](http://c-faq.com/stdio/stdinflush.html) and this [C FAQ](http://c-faq.com/stdio/stdinflush2.html). – Lundin Jun 05 '11 at 16:31

5 Answers5

4

You're using scanf(). My general rule is: don't.

The problem is that scanf() of pretty much anything will leave the characters after the value you read (usually a newline) in the buffer, except that %c reads the next character regardless of what it is. So you get the newline there, and then the y/n response is passed to the next scanf().

I prefer to read lines and then sscanf() out of them; that way I know exactly what I'm getting.

geekosaur
  • 59,309
  • 11
  • 123
  • 114
  • Hehe, the best advice here: just don't use `scanf()` :) Though, you should have also mentioned `fgets()` alongside of `sscanf()`. – zvrba Jun 05 '11 at 05:04
3

Put getchar() after each scanf to clear the stdin input buffer from the trailing line feed character '\n' that gets added to the buffer when the user presses enter.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

You are entering a number and then pressing enter key. The "%d" format string will read upto the the first integer and not read the newline character that you enter. That newline character would stay inside the buffer, which gets read on the first scanf in the loop with the "%c" specifier. Therefore the check == 'y' becomes false as check contains 0x0a , ie the newline ASCII equivalent, after it has read the new line.

Note that, if you want to make exactly your code snippet work then you need to enter the numbers and the y/n options one after another without any newline (0x0a) or blank space (0x20) or other separators. For example if you like to sumup the list 1,2,3,4,5 then you need to enter it as follows in your code: 1y2y3y4y5n . If you enter a printf statement printing the status value after the scanf asking for the yes/no, you can clearly see that the last unread character is being read by the "%c".

If you want to input the numbers and option separated What you need is to consume the extra character. Which you can do by using a getchar () or using the argument suppression operator in the format string: scanf ("%*c%c", &check) . This "%*c" will read one character from the stdin and then simply discard it, and then the "%c" will get your input into the check variable. But if you enter an extra new line or have , say, some trailing spaces before the options you enter, or after the number you have entered, then it will make only one of these be consumed by the above and discarded, and the same problem will arise.

You can also use the string scanf (" %c", &check); the " %c" (note the trailing blankspace) will skip any number of blankspace character you enter before entering the first character.

It actually depends how you want to interpret and handle the input, you need to adjust as per it. Probably make :

 char check[2];

 while (status == 1)
 {
    sum += num;

    printf("Do you wanna add more integer?(y/n) :");   //Asking for user next action
    scanf("%s" , check);

    if ((check[0] == 'y')&&(check[1] == '\0'))    //Check user's answer  
       status = scanf("%d" , &num);
    else
       status = 0;
 }

or simply use strcmp (check, "y") == 0 or other ways.

phoxis
  • 60,131
  • 14
  • 81
  • 117
-1

Here is the edited code working for me:

#include <stdio.h>
#include <conio.h>
int main(void)
{

   int sum = 0;                  
   int num;
   char check;
   int status=1;

   printf("Please enter an integer to be summed :");
   status = scanf("%d" , &num);      
   while(status == 1)
   {
      sum = sum + num;                          
      printf("Do you wanna add more integer?(y/n) :");   
      fflush(stdin);
      check = getche();

      if(check == 'y')                   

         status = scanf("%d" , &num);
      else

         status = 0;
   }
    printf("\nThe sum is: %d",sum);
    getch();
    return 0;
 }
knurdy
  • 496
  • 6
  • 18
  • what is `conio.h` ? is it from the TurboC++ 3.1 ? – phoxis Jun 05 '11 at 01:51
  • -1 fflush(stdin) is undefined behavior and not something you should teach beginners to use. Also, the code is needlessly using non-standard libraries. – Lundin Jun 05 '11 at 16:29
-1

status starts off as undefined. You want to make sure that the input/sum loop runs at least once, therefore you should set it to 1 initially. That way you know it will always run the first time.

What @geekosaur has said about scanf() is true - it will leave things in the input buffer which will cause strange behaviour for following input statements. But it's fine to use scanf(), as long you clear stdin every time you use it. If you are using Windows there is a ready-made function:

fflush(stdin);

If you are using another operating system (or you want your code to be portable) you can search for a similar function to include in your program. Input in C is just one of the awful things that the beginner programmer needs to work around (you get used to it). I believe it may help as well if you put spaces at the beginning of the scanf() format string each time you are using it - eg.

scanf(" %d");

This should tell the program to ignore any whitespace already in the input (including newlines).

One thing to note is that you really have 2 status inputs here - the int status and the char check. You could make things a bit simpler for yourself by setting the condition as the user input:

char check = 'y';

...

while(check == 'y')

This should create the same behaviour as what you have now. I used a do-while loop instead:

// This program would sum up all the integer provided by user

#include <stdio.h>

int main(void)
{
    int sum = 0;
    int num;
    char check;

    do // a do-while loop always runs at least once - perfect for input validation
    {
        printf("Please enter an integer to be summed :");
        fflush(stdin); //only in Windows - remove for other OS
        scanf(" %d" , &num);
        sum += num; //another way of writing sum = sum + num                                
        printf("Do you wanna add more integer?(y/n) :");
        fflush(stdin); //only in Windows - remove for other OS
        scanf(" %c" , &check);    
    }while(check == 'y');

    //if you want to print the sum...
    printf("The sum is %i\n", sum);
    getchar();

    return 0;
}

It did work for me on Windows with the fflush() calls removed.

thelionroars1337
  • 188
  • 1
  • 3
  • 10
  • -1 fflush(stdin) is undefined behavior and not something you should teach beginners to use. – Lundin Jun 05 '11 at 16:30
  • 1
    @Lundin that's your opinion and that's fine - but I am currently studying introductory C (have my exam in a couple of hours) and this is what I have been taught to use by the lecturer. So your views are not universal. Portability of code may or may not be one of your goals when writing a program and I did state quite clearly the conditions that you could use fflush() (at least as I have been taught it). But thank you for sharing the links above. I don't really see how calling getchar() is any more efficient than including whitespace in beginning of scanf() format string - care to enlighten. – thelionroars1337 Jun 05 '11 at 17:19
  • I'm sad to hear that you have a teacher who doesn't know C too well. Because this is not "believes", it is not even a portability issue. Standard C _explicitly_ states that fflush(stdin) is undefined behavior (ISO 9899:1999 7.19.5.2). And undefined behavior means that any random thing may happen. When undefined behavior occurs, the program is free to format your C: or shoot innocent bystanders. – Lundin Jun 06 '11 at 19:30
  • @Lundin, Not if it is explicitly defined for that implementation - whether you use it then is perhaps a portability issue. How many compilers fully comply with the 99 standard anyway? I'm sure there are better ways to handle characters left in stdin, but whether you want to introduce those methods to people who are just starting in both the language and programming is something a teacher might weigh up both sides of. Don't many writing production code create their own parsing functions for input - would you expect a beginner to do so? Maybe, maybe not. And my exam went well, thanks for asking. – thelionroars1337 Jun 07 '11 at 07:49
  • @thelionroars1337 What you are speaking of is an extension outside the C language, ie the compiler is inventing some own language that is not C. Sadly, this is very common, compilers implement their own crap even when there is no reason for it. As for fflush(stdin) it was undefined behavior in C90 as well, it has nothing to do with C99. – Lundin Jun 07 '11 at 13:28
  • As for the definition of undefined behavior, the C language means something that the compiler is not forced to implement in predictable ways. A good explanation can be found [here](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior). – Lundin Jun 07 '11 at 13:32
  • @Lundin yes I figured it was not present in the previous standard either - and it's not in current draft of future standard. TjatOf course everything in the standards are there for some reason, but I haven't seen any explanation yet of why it's undefined. – thelionroars1337 Jun 07 '11 at 15:10