4

I have a problem. I've tried to see the length of some string after using fgets function. If I enter string under the number of letter which can be in the string (like: the maximum letters in string is 9 and I enter 4 letters), I get length of the string+1. why?

Here's my code:

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

int main(void)
{
    char name[10]={0};
    printf("enter your name\n");
    fgets(name, 10, stdin);
    printf("your name is %s and it is %d letters\n", name, strlen(name)); // length problem 

    return 0;
} 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Raz Omry
  • 255
  • 1
  • 6
  • 18

4 Answers4

5

From fgets manual page (https://linux.die.net/man/3/fgets):

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 (aq\0aq) is stored after the last character in the buffer.

So it adds '\n' after your 4 letters, returning string_length+1.

From Removing trailing newline character from fgets() input you can add @Tim Čas solution to your code.

The line is still read with the fgets() function and after we remove the newline character.

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


int main(void)
{
    char name[10] = { 0 };
    printf("enter your name\n");
    fgets(name, 10, stdin);
    printf("your name is %s and it is %d letters\n", name, strlen(name)); // length problem 
    name[strcspn(name, "\n")] = 0;
    printf("NEW - your name is %s and it is %d letters\n", name, strlen(name));
    return 0;
}

That outputs:

enter your name
Andy
your name is Andy
 and it is 5 letters
NEW - your name is Andy and it is 4 letters
Press any key to continue . . .
Community
  • 1
  • 1
jgorostegui
  • 1,290
  • 1
  • 8
  • 13
3

If a character array has enough space then the standard function fgets also includes the new line character '\n' in the array that usually corresponds to the pressed key Enter.

You can remove this redundant new line character the following way

name[strcspn( name, "\n" )] = '\0';

after that you will get the expected result of applying the function strlen.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

Because the end of line character '\n' is included in the string copied into name by fgets() .

timrau
  • 22,578
  • 4
  • 51
  • 64
1

As is written in man fgets,

The fgets() function reads at most one less than the number of characters specified by size from the given stream and stores them in the string str. Reading stops when a newline character is found, at end-of-file or error. The newline, if any, is retained. If any characters are read and there is no error, a `\0' character is appended to end the string.

Since you are reading from stdin, fgets(name, 10, stdin) reads at most 9 characters from stdin buffer and appends \0 to the end. It just happens that the new line character \n produced when user hit enter is in the buffer too.

As a sidenote, it is customary (and a good practice) to use sizeof() when specifying size of the array passed to fgets.

fgets(name, (int) sizeof(name), stdin);
Pejman
  • 1,328
  • 1
  • 18
  • 26
  • 1
    "*It can never go wrong!*" sure, as its a machine, but it still can be *used* wrongly. Imaging using as pointer instead of an array: `char * readstr(char * p) { return fgets(p, sizeof p, stdin); }` would (on most systems) try to read 4 or 8 `char`s. – alk Jan 10 '17 at 16:38
  • "It can never go wrong!" --> note that `sizeof` returns type `size_t`, yet `fgets(char * s, int n, FILE * stream)` uses an `int` for the size. With huge arrays, this may convert unexpectantly. Certainly rare, but not _never_. – chux - Reinstate Monica Jan 10 '17 at 16:47
  • How do you know it can never go wrong if you don't check it's return value? `fgets` can return `NULL` from `stdin` if `EOF` is encountered. – RoadRunner Jan 10 '17 at 16:56
  • I am merely suggesting OP to pass sizeof(name) instead of 10 to `fgets`. It can always go wrong when things are taken out of context. Thanks for the comments. updated the answer. – Pejman Jan 10 '17 at 17:09
  • @PejmanGh I'm sorry if I sounded rude. Up vote from me :). – RoadRunner Jan 10 '17 at 17:44