1
fseek(fPtr, 0, SEEK_END);
    fflush(stdin);
    printf("\n\t\t\t ENTERID : ");
    fgets(user.id, ID_SIZE, stdin);
    fflush(stdin);

    printf("tENTER FIRST NAME: ");
    fgets(user.fname, MAX_FNAME_SIZE, stdin); //automatic added newline
    

    printf("ENTER LAST NAME: ");
    fgets(user.lname, MAX_LNAME_SIZE, stdin); //automatic added newline
 

I was using fgets() for reading the input of the string and store into the text file using the fwrite. But why does fgets() automatically enter a newline for each input of string.

ryyker
  • 22,849
  • 3
  • 43
  • 87
Lucas Jack
  • 13
  • 6
  • 3
    It is not automatic. You enter newline and `fgets()` saves it to the buffers. – MikeCAT Jan 12 '21 at 13:27
  • 3
    Do not use `fflush(stdin);`, it's undefined behaviour. – Sourav Ghosh Jan 12 '21 at 13:27
  • How to remove it automatically? @MikeCAT – Lucas Jack Jan 12 '21 at 13:29
  • 1
    The `fgets` stores the read newline character, while the `gets` discards the read newline character. It is by design. – Ron Jan 12 '21 at 13:29
  • 1
    [c - Removing trailing newline character from fgets() input - Stack Overflow](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input) – MikeCAT Jan 12 '21 at 13:29
  • @MikeCAT that mean we need to do another process to remove the newline \0? Like that link given using `strcspn` – Lucas Jack Jan 12 '21 at 13:36
  • 1
    @LucasJack - (From the comments under that link.) _"This [method] handles the rare buffer than begins with `'\0'`, something that causes grief for the `buffer[strlen(buffer) - 1] = '\0';`"_ – ryyker Jan 12 '21 at 14:01

2 Answers2

1

"...but gets() no issue about newline"
Note, that although your observation about gets() being preferable in this case over fgets() for handling newline, the unfavorable behaviors that come with gets() make it dangerous to use, with the result that "it was officially removed by the 2011 standard." (credit) Even without the \n mitigations mentioned below, fgets() is highly preferred over gets().

"fgets() goes newline when storing string..." and "...why does fgets() automatically enter a newline for each input of string"
fgets() does not enter the newline upon reading the line, rather if one exists, the newline is picked up as part of the line when fgets() called. For example in this case, when using stdin as the input method, the user clicks the <return> to finish inputting text. Upon hitting the <return> key, a \n is entered just like any other character, and becomes the last character entered. When the line is read using fgets(), if the \n is seen before any of its other stop reading criteria, fgets() stops reading, and stores all characters, including \n, terminates line with \0 and stores into the buffer. (If sizeof(buffer) - 1 or EOF is seen first, fgets() will never see the newline.)

To easily eliminate the \n, (or other typical unwanted line endings), use the following single line statements after each of your calls to fgets():

fgets(user.id, ID_SIZE, stdin);
user.id[strcspn(user.id, "\n")] = 0;
//fflush(stdin);//UB, should not be called 
...
fgets(user.fname, MAX_FNAME_SIZE, stdin);
user.fname[strcspn(user.fname, "\n")] = 0;
...
fgets(user.lname, MAX_LNAME_SIZE, stdin);
user.lname[strcspn(user.lname, "\n")] = 0;
...

This technique works for truncating any string by searching for the unwanted char, whether it be "\n", "\n\r", "\r\n", etc. When using more than one search character, eg "\r\n", it searches until it reaches either the \r or the \n and terminates at that position.

"This [method] handles the rare buffer than begins with '\0', something that causes grief for the buffer[strlen(buffer) - 1] = '\0'; [method]." (@Chux - comment section of link below.)

Credit here

ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Why this have added \r ? – Lucas Jack Jan 12 '21 at 13:41
  • 1
    @LucasJack - It does not need it, but does not hurt. I will remove it for your code. Some environments tack on the `\r` in addition to the `\n`. See edit for more detailed explanation. – ryyker Jan 12 '21 at 13:50
0

Quoting from the man page,

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.

So, after providing the input from the terminal, you press the ENTER key which adds a newline to the input buffer. That same newline is scanned and stored in the destination provided to fgets().

If you want to remove the trailing newline, use the solution mentioned in the answer: Removing trailing newline character from fgets() input

That said, read:

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • `strcspn` so everytime i using fgets() i need to do this process to make sure no newline store? – Lucas Jack Jan 12 '21 at 13:38
  • 1
    @LucasJack - There are other methods, as seen in the link, but this one is elegant in that it is a simple and surprisingly versatile one line method. – ryyker Jan 12 '21 at 13:57