0

This question might look stupid but I am not used to work with C and I'm losing my mind here not knowing what is wrong.

Basically what I want is to get a number from the user, then a string, the user may write whatever he feels like, I want to keep just the first caracter of that string.

My code is the following:

#include <stdio.h>

int main()
{
  int b, n;
  char frase [2];

  scanf("%d", &n);
    
  fgets(frase, 2, stdin);
  puts(frase);

  return 0;
}

My problem is, after the fgets the program stops, no matter what I have after it, it only stops, no error messages or anything. What is happening?

anastaciu
  • 23,467
  • 7
  • 28
  • 53
Fabricio_A
  • 58
  • 7
  • What exactly is your error? Does it close after you type something in the second input or does it let you type and produce no output? Never used gets myself, I just use scanf("%s", &charArr); – Turret Feb 16 '21 at 21:14
  • The answer starts with: don't use `scanf()` and `fgets()` together. – ad absurdum Feb 16 '21 at 21:35

2 Answers2

3

What is happening?

Your code will:

  • For an input 123 abc:

    • Store 123 in n, store the space in frase followed by a null byte. Then it will print that single space and end its execution with no errors.
  • For an input 123 Enter abc:

    • Store 123 in n and store in frase the newline character \n added to the buffer when you pressed Enter, followed by a null byte, next it will print that \n and end its execution with no errors.

So it doesn't just stop, it does what it's supposed to do.

What you shoud do, to make your code more robust, is to also parse the number with fgets, and convert it with sscanf or strtol:

int n = 0;
char buffer[20];
char frase[2];

fgets(buffer, sizeof buffer, stdin); 
if(sscanf(buffer, "%d", &n) != 1){
    //value not parsed
}

fgets(frase, sizeof frase, stdin);

puts(frase);

Using scanf to parse inputs is rarely, if ever, a good ideia.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
-1

The fgets is grabbing the newline character that is in the buffer after scanf reads the int. Putting a getchar() before your fgets should fix the problem.

jeremycurda
  • 1
  • 1
  • 1
  • 1
    Instead of `getchar()`, modifying the `scanf` might work better. If you use `scanf("%d\n", &n)`, it should also be able to handle `\r\n` on Windows. – Locke Feb 16 '21 at 21:23
  • @locke thanks for that, C sometimes can be a pain in the ass and the \n solved the damn thing – Fabricio_A Feb 16 '21 at 21:26
  • @Locke -- that is a very bad idea; [it is almost always a mistake to terminate a `scanf()` format string with a whitespace character](https://stackoverflow.com/questions/43032984/using-scanfd-with-a-space-after-the-d). It can cause havoc with user interactions. – ad absurdum Feb 16 '21 at 21:30
  • The answer says "use `getchar()`"; it doesn't suggest messing with `scanf` format-string. Neither is ideal, but either can seem to work OK. See [here](https://stackoverflow.com/q/5240789/509868) for more information. – anatolyg Feb 16 '21 at 21:39
  • @anatolyg -- "_either can seem to work OK_": _seem_ is the operative word. `"%d\n"` does _not_ work ok; it matches whitespace characters until a failing match, blocking input. In this case it appears to "work" because the following `fgets()` is unprompted and takes the input left behind after `scanf()` is finished. Printing an input prompt before the `fgets()` will show the problem, or removing the `fgets()` altogether will leave the `scanf()` hanging until some non-whitespace character is entered. Read my linked answer in my previous comment. – ad absurdum Feb 16 '21 at 21:50