0

This is a simple C program that explains do while loop.Before the loop ends there two scanf ./ I am really confused with the one " scanf("%d",&dummy); ". The program will not run as expected wihtout this line. So, I believe this line act as a some sort of placeholder to create a space to take input for chat. But I am not sure about this and how actually it works

#include<stdio.h>  
#include<stdlib.h>  
void main ()  
{  
    char c;  
    int choice,dummy;    
    do{  
    printf("\n1. Print Hello\n2. Print Javatpoint\n3. Exit\n");  
    scanf("%d",&choice);  
    switch(choice)  
    {  
        case 1 :   
        printf("Hello");   
        break;  
        case 2:    
        printf("Javatpoint");  
        break;  
        case 3:  
        exit(0);   
        break;  
        default:   
        printf("please enter valid choice");      
    }  
    printf("do you want to enter more?");   
    scanf("%d",&dummy);  //This part confuses me
    scanf("%c",&c);  
    }while(c=='y');  
}  
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
Paras
  • 23
  • 2
  • 1
    Note that `void main()` is not standard C. Use `int main(void)`. See [What are the valid signatures for C's main() function?](https://stackoverflow.com/q/2108192/10077). – Fred Larson Jul 31 '20 at 02:53
  • 2
    `"%c"` and `"%[..]"` are the two conversion specifiers that do not discard leading whitespace. You must include a space before either to consume leading whitespace --- and you cannot use any user-input function correctly, especially `scanf()`, if you fail to ***check the return***. `fgets()` followed by `sscanf()` is the recommended way to handle user-input. Otherwise, how will you handle the accidental entry of `"4r"` when reaching for `'4'`? – David C. Rankin Jul 31 '20 at 04:16
  • 1
    "I am really confused [by] scanf". This is a tautology. Why do beginners bother trying to learn scanf? You should not even touch scanf until you have at *least* 15 years experience with the language. – William Pursell Jul 31 '20 at 12:57

3 Answers3

2

Once the user has entered a choice and hit Enter key, the number is read up to, but not including, the end-of-line character. Without this scanf("%d", %dummy);, that end-of-line character is still there and is read into c. Since that is not equal to 'y', your loop terminates.

With the scanf("%d", dummy); call, the whitespace gets consumed looking for digits. Note that scanf documentation says, "All conversion specifiers other than [, c, and n consume and discard all leading whitespace characters (determined as if by calling isspace) before attempting to parse the input." When a non-whitespace, non-digit character is encountered (such as 'y' or 'n'), the reading of the integer fails. That's ok, you're ignoring it anyway. But now the 'y' or 'n' is there to read into c.

An easier way would be to change scanf("%c", &c); to scanf(" %c", &c); (note the space before %c). This tells scanf to consume any whitespace before reading a character into c. It's much more idiomatic.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
1

Because variable dummy is used to capture the return following choice number.

If we add one line to print dummy

    printf("[%c]\n", dummy); // We should change dummy's type to char, omit here

This is an explanation of the result:

1. Print Hello                
2. Print Javatpoint
3. Exit
1                                     # This is input: 1 and an invisible return
Hellodo you want to enter more?[      # return is captured by scanf and printed
]
y                                     # This is input: y and an invisible return, return is ignored by scanf("%d", &choice), because it need numbers

1. Print Hello
2. Print Javatpoint
3. Exit
2                                     # This is input: n and an invisible return
Javatpointdo you want to enter more?[
]
n
Martins3
  • 67
  • 1
  • 8
-1

This is happening as scanf leaves a '\n' character which is read by next scanf is %c is used.

Solution : replace %c by %1s in the reported program to solve the issue (to read the next non-white space character, use %1s instead of %c).

Kindly refer below program to see issue because of newline character.

[root@localhost Programs]# cat -n scan.c

 #include<stdio.h>  
 #include<stdlib.h>  
 int main ()  
 {  
     char c = 0;  
     int choice,dummy;    
     do{  
     printf("\n1. Print Hello\n2. Print Javatpoint\n3. Exit\n");  
     scanf("%d",&choice);  
     switch(choice)  
     {  
         case 1 :   
         printf("Hello\n");   
         break;  
         case 2:    
            printf("Javatpoint\n");  
            break;  
            case 3:  
            exit(0);   
       break;  
            default:   
            printf("please enter valid choice\n");      
        }  
        printf("say 'y' if you want to enter more\n");   
        scanf("%c",&c);
        printf("%d\n",c);
        scanf("%c",&c);
        printf("%d\n",c);
        }while(c=='y');  
        return 0;
    }  

you can see value 10 which is the value of character '\n' left by earlier scanf.

  • Issue is resolved by below program (%1s is used in place of %c ):

    #include<stdio.h>
    #include<stdlib.h>
    int main ()
    {
    char c = 0;
    int choice,dummy;
    do{
    printf("\n1. Print Hello\n2. Print Javatpoint\n3. Exit\n");
    scanf("%d",&choice);
    switch(choice)
    {
    case 1 :
    printf("Hello\n");
    break;
    case 2:
    printf("Javatpoint\n");
    break;
    case 3:
    exit(0);
    break;
    default:
    printf("please enter valid choice\n");
    }
    printf("say 'y' if you want to enter more\n");
    scanf("%1s",&c); }while(c=='y');
    return 0; }

inderjeet
  • 69
  • 2
  • 1
    You can't use `scanf("%1s",&c);` Why? `"%1s"` writes 2-bytes -- (1) the character and (2) the *nul-termianting* character to mark the end of the string. See [man 3 scanf](https://www.man7.org/linux/man-pages/man3/scanf.3.html) So you invoke *Undefined Behavior*. Use `" %c"` instead. – David C. Rankin Jul 31 '20 at 04:05
  • I don't think there is any problem of using %1s before return statement in above program. – inderjeet Aug 03 '20 at 00:37
  • Yes, yes there is. You declare `char c = 0;` The total storage available for `c` is 1-byte. When you use `scanf("%1s",&c);`, you write 2-bytes to `c`. That is writing beyond the bounds of the memory available to `c` and is *Undefined Behavior*. You will overwrite the first byte of whatever comes after `c` on the program stack with `'\0'`. (bad things will happen...) – David C. Rankin Aug 03 '20 at 00:46
  • Thanks David for the correction and I am really sorry for suggesting program with undefined behavior. I think I misinterpreted following description in BRIAN W KERNIGHAN DENNIS M. RITCHIE : characters; char *. The next input characters (default 1) are placed at the indicated spot. The normal skip over white space is suppressed; to read the next non-white space character, use "1s. – inderjeet Aug 03 '20 at 00:56
  • No worries. That is the double-edge of the C sword. Unlimited freedom to harness every byte of the computer -- but it comes with the unwavering responsibility to make sure you account for each byte you are using `:)` – David C. Rankin Aug 03 '20 at 00:59
  • [Consider This Code](https://paste.opensuse.org/63366776) – David C. Rankin Aug 03 '20 at 01:04