0

I'm trying to understand how gets works if it's used after scanf.

int main()
{
    char c,d;
    char word[20];
    int n;

    printf("give a number:\n");
    scanf("%d ",&n);                           //     (input 1)

    // c=getchar();                                   (Solution 1)
    // while ((c = getchar()) != '\n' && c != EOF) ;  (Solution 2)
    // fflush(stdin);                                 (Solution 3)
    // gets(word);                                    (Solution 4)

    printf("Give a word:\n");
    gets(word);                                  //   (input 2)

    printf("word = %s ",word);                   //   (Output)
}

I know this question is asked a lot here, and that I shouldn't use gets at all (instead I should use fgets). However, I have to use it since it's the only thing we were taught in class. I've read plenty of posts about it. I've found multiple solutions to evade that problem. but I still don't understand some of these solutions.

If I start my program without any of the solutions, gets will read the new-line character \n and won't let me give any input.

I found that this can be bypassed if I use:

  • (Solution 1) however let's say the user in (input 1) typed:

    1   aaaaaaaaaaa \n 
    

    (Output) will be " aaaaaaaaaaa "

  • (Solution 2) will fix this problem and will let me give (input 2).

  • (Solution 3) works too; however, it's frowned upon as it doesn't have a good portability.

  • (Solution 4) is the same as (solution 2) I suppose. Please tell me if I'm wrong.

  • Another solution I found is to always use gets whenever I want to give input; and then format it with sscanf(...). Tried it! It fixed all my problems. This is what I started using.

I don't really understand Solution 2. I can see that it removes all characters besides \n and then removes the first \n it meets and stops the loop. But what if the user gave this as his input

\n \n \n               1    abc \n

Why are the first 3 '\n' ignored? I don't understand the buffer notion that well.

Please let me know if I got something wrong in those solutions!

EDIT: I already know about scanf(" %c",...); but my problem is with gets and not scanf.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • @jonathan leffler I know about using space before %c in scanf, this is not the same question. As this has to do with gets() and not scanf –  May 23 '17 at 23:37
  • 1
    You should worry about a class that teaches you to use `gets()` — it is teaching you bad practices from the start, which isn't going to help you in industry. Tell (well, maybe don't) your teacher that C11 abandoned `gets()` — announced in 2007, implemented in 2011 — because it is [Impossible to use `gets()` safely](http://stackoverflow.com/questions/1694036/). So, it has been at least 5 years, arguably 10, since the standards body dropped a hint. But the first (Morris) Internet Worm back in 1988 used `gets()` as one of its way around! – Jonathan Leffler May 23 '17 at 23:37
  • I know I shouldn't use gets at all due to its buffer problems and how it can use memory it shoudln't use. But, sadly I have to use it for this class. I'm trying to understand how it works and how can I play around its multiple problems. –  May 23 '17 at 23:41
  • 1
    You've got a `scanf()` and it leaves the newline in the buffer. There's also a trailing blank in the format string; you can have another relevant duplicate [What is the effect of a trailing blank in a `scanf()` format string?](http://stackoverflow.com/questions/19499060/) if you like. The problems are very much the same — mixing line-based input with `scanf()`-based input is hard to get right and most people don't. If you want line-based input, use `fgets()` et al to read and then `sscanf()` to parse. – Jonathan Leffler May 23 '17 at 23:41
  • so far i've been using solely this for anything other than strings gets(line); sscanf(line,"%f",&something); and gets($string_name) for strings Is this correct? –  May 23 '17 at 23:48
  • 1
    Your first three newlines are ignored because `scanf()` skips them as white space before the first number. The `scanf()` function doesn't care about newlines except to the extent they're 'white space' that gets skipped by every format specifier except `%c`, `%[…]` (scan sets) and `%n`. All the other formats skip leading white space. So, `scanf("%d ", &n)` first skips leading white space, then reads a number, and then waits to find a non-white-space character (which it ignores and puts back for the next input operation, but it has to read up to that character before it completes). – Jonathan Leffler May 23 '17 at 23:52
  • Solution 2 assumes that any characters after the number but before the newline are not relevant — there's no chance that the user typed 1M meaning `1000000` (or `1048576`), for example. It skips over any non-digits after the number, up to and including the newline (or EOF). If that's what you want (it often is), it's good; if it's not what you want, it's bad. But the controlling factor is what you want your program to do with the extra input. – Jonathan Leffler May 23 '17 at 23:55
  • 1
    Using `fgets()` with `sscanf()` when appropriate is usually the best way to go. It has major benefits when it comes to trying alternative formats and error reporting. – Jonathan Leffler May 23 '17 at 23:59
  • Thanks a lot sir you're awesome! That was really helpful. I hope I can give back to the community someday too –  May 24 '17 at 07:12

0 Answers0