11

I'm pretty new to C, and I have a problem with inputing data to the program.

My code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
   int a;
   char b[20];

   printf("Input your ID: ");
   scanf("%d", &a);

   printf("Input your name: ");
   gets(b);   

   printf("---------");

   printf("Name: %s", b);   

   system("pause");
   return 0;
}

It allows to input ID, but it just skips the rest of the input. If I change the order like this:

printf("Input your name: ");
   gets(b);   

   printf("Input your ID: ");
   scanf("%d", &a);

It will work. Although, I CANNOT change order and I need it just as-is. Can someone help me ? Maybe I need to use some other functions. Thanks!

Dmitri
  • 2,451
  • 6
  • 35
  • 55
  • 1
    gets(3): "The gets() function cannot be used securely. Because of its lack of bounds checking, and the inability for the calling program to reliably determine the length of the next incoming line, the use of this function enables malicious users to arbitrarily change a running program's func- tionality through a buffer overflow attack. It is strongly suggested that the fgets() function be used in all cases. (See the FSA.)" Don't use it. – Bertrand Marron Mar 02 '10 at 20:39
  • 3
    More briefly: If you use `gets`, flying rabid attack ocelots will rip out your eyesockets. So don't. – Tyler McHenry Mar 02 '10 at 20:45
  • 2
    `scanf` is **evil** - http://c-faq.com/stdio/scanfprobs.html – jschmier Mar 02 '10 at 22:07
  • 2
    `gets(b);` change to `scanf(" %19[^\n]", b);` – BLUEPIXY Mar 15 '15 at 06:01
  • 2
    Apparently OP is new to C, why keep talking about security stuff. He just wants to implement something in a beginner way. – Timothy Leung Oct 18 '15 at 07:42
  • Don't use gets as create security holes.use fgets. –  Aug 04 '17 at 16:56

8 Answers8

12

Try:

scanf("%d\n", &a);

gets only reads the '\n' that scanf leaves in. Also, you should use fgets not gets: http://www.cplusplus.com/reference/clibrary/cstdio/fgets/ to avoid possible buffer overflows.

Edit:

if the above doesn't work, try:

...
scanf("%d", &a);
getc(stdin);
...
IVlad
  • 43,099
  • 13
  • 111
  • 179
  • Hm. I've tried scanf("%d\n", &a); but it doesn't seems to be working. After I input ID, I just dont see program doing anything else. – Dmitri Mar 02 '10 at 20:37
  • Wow! Thanks! That worked flawlessly! Thanks for advice about fgets. Will surely use it!! Thank you! – Dmitri Mar 02 '10 at 20:47
  • `scanf("\n")` doesn't do what you think - it consumes *all consecutive whitespace characters*, so doesn't return until there's a non-space character buffered. – Toby Speight Jun 24 '19 at 15:42
8

scanf doesn't consume the newline and is thus a natural enemy of fgets. Don't put them together without a good hack. Both of these options will work:

// Option 1 - eat the newline
scanf("%d", &a);
getchar(); // reads the newline character

// Option 2 - use fgets, then scan what was read
char tmp[50];
fgets(tmp, 50, stdin);
sscanf(tmp, "%d", &a);
// note that you might have read too many characters at this point and
// must interprete them, too
AndiDog
  • 68,631
  • 21
  • 159
  • 205
  • Also, using `scanf("%d%*c", &a)` should work. The `%*c` term causes `scanf` to read in one character (the newline) but the asterisk causes the value to be discarded. This will make `scanf` eat the newline without requiring a separate function call. – bta Mar 02 '10 at 20:57
  • You present both options as if they had equal footing, but `scanf` is just so hard to use properly that it's much better to avoid using it entirely (see the comp.lang.c FAQ link). Just go with option 2. – jamesdlin Mar 03 '10 at 03:23
3

scanf will not consume \n so it will be taken by the gets which follows the scanf. flush the input stream after scanf like this.

#include <stdlib.h>
#include <string.h>

int main(void) {
   int a;
   char b[20];

   printf("Input your ID: ");
   scanf("%d", &a);
   fflush(stdin);
   printf("Input your name: ");
   gets(b);   

   printf("---------");

   printf("Name: %s", b);   

   system("pause");
   return 0;
}
pmg
  • 106,608
  • 13
  • 126
  • 198
vinayak
  • 31
  • 1
1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
        int a;
        char b[20];
        printf("Input your ID: ");
        scanf("%d", &a);
        getchar();
        printf("Input your name: ");
        gets(b);
        printf("---------");
        printf("Name: %s", b);
        return 0;
}



Note: 
  If you use the scanf first and the fgets second, it will give problem only. It will not read the second character for the gets function. 

  If you press enter, after give the input for scanf, that enter character will be consider as a input f or fgets.
muruga
  • 2,092
  • 2
  • 20
  • 28
0

you should do this way.

    fgetc(stdin);
    scanf("%c",&c);
    if(c!='y')
    {
        break;
    }
    fgetc(stdin);

to read input from scanf after reading through gets.

Madan Ram
  • 880
  • 1
  • 11
  • 18
0

Just use 2 gets() functions

When you want to use gets() after a scanf(), you make sure that you use 2 of the gets() functions and for the above case write your code like:

int main(void) {
   int a;
   char b[20];

   printf("Input your ID: ");
   scanf("%d", &a);

//the change is here*********************
   printf("Input your name: ");
   gets(b);
   gets(b);   
//the change is here*********************

   printf("---------");

   printf("Name: %s", b);   

   system("pause");
   return 0;
}
Leonardo Alves Machado
  • 2,747
  • 10
  • 38
  • 53
  • welcome to SO! Please remember that English is not the first language of everybody here, so try to post answers that are grammatically correct, rather than using 'u' for 'you' - which won't work with Google Translate! – Dave Mulligan Jan 09 '16 at 09:59
0

scanf("%d", &a); can't read the return, because %d accepts only decimal integer. So you add a \n at the beginning of the next scanf to ignore the last \n inside the buffer.

Then, scanf("\n%s", b); now can reads the string without problem, but scanf stops to read when find a white space. So, change the %s to %[^\n]. It means: "read everthing but \n"

scanf("\n%[^\n]", b);

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    int a;
    char b[20];

    printf("Input your ID: ");
    scanf("%d", &a);

    printf("Input your name: ");
    scanf("\n%[^\n]", b);
    //first \n says to ignore last 'return'
    //%[^\n] read until find a 'return'  
    printf("---------\n");
    printf("Name: %s\n\n", b);   

    system("pause");
    return 0;
}
0

The scanf function removes whitespace automatically before trying to parse things other than characters. %c, %n, %[] are exceptions that do not remove leading whitespace.

gets is reading the newline left by previous scanf. Catch the newline usinggetchar();

scanf("%d", &a);
getchar(); // catches the newline character omitted by scanf("%d")
gets(b);

https://wpollock.com/CPlus/PrintfRef.htm

Duy Đặng
  • 409
  • 1
  • 7
  • 15