3

Using fgets to input a string, I have doubts related to length of string read.

For example, consider the following program.

char str[50];
int i;
int len;
printf("Enter name:\n");
fgets(str,11,stdin);
len = strlen(str);
printf("len :  %d\n",len);
  1. If I enter 123456789, strlen gives 10.

  2. If I enter 1234567890, strlen given is 10 again ??

I think strlen is considering newline also for string length. Am I correct? (I understand fgets using newline as part of string)

What's wrong with (2) where I enter exactly 10 characters, Here string length should be 11 right? 10 + 1 (for newline) = 11

pb2q
  • 58,613
  • 19
  • 146
  • 147
kumar
  • 2,530
  • 6
  • 33
  • 57
  • printf("len : %d",len); printf("str : %s",str); printf("hi");return 0; } Adding few prints helps to clarify the answers given below. Notice how "hi" is printed. – kumar Nov 20 '12 at 11:19

3 Answers3

4

fgets reads at most 1 fewer characters than the length argument given, and does retain the newline as part of the input - so long as the newline is part of the first (length - 1) characters.

So in your first case, assuming that 123456789 is followed by a newline, fgets has read 9 characters including the newline, yielding a string length of 10; in your second case, fgets will stop after reading the 10 characters 1234567890, yielding a string length of 10.

pb2q
  • 58,613
  • 19
  • 146
  • 147
  • 1
    Minor correction: it will *not* retain the newline if #/characters >= max length. As illustrated in the example below. – paulsm4 Jun 24 '12 at 21:01
  • 1
    @paulsm4 I believe that's already clear from my first line: _reads at most 1 fewer characters than the length argument given_. – pb2q Jun 24 '12 at 21:07
3

Here is an example:

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

#define MAX_DIGITS 5

int
main ()
{
  char buf[80];
  char *s = NULL;
  printf ("\n>>Enter string, %d digits or less: ", MAX_DIGITS);
  s = fgets (buf, MAX_DIGITS+1, stdin);
  printf ("strlen(buf)=%d, buf=%s, strlen(s)=%d, s=%s\n",
    strlen(buf), buf, strlen(s), s);
  return 0;
}

Sample output, with "MAX_DIGITS" and "MAX_DIGITS + 1":

>>Enter string, 5 digits or less: 1
strlen(buf)=2, buf=1
, strlen(s)=2, s=1
.

>>Enter string, 5 digits or less: 12
strlen(buf)=3, buf=12
, strlen(s)=3, s=12
.

>>Enter string, 5 digits or less: 123
strlen(buf)=4, buf=123
, strlen(s)=4, s=123
.

>>Enter string, 5 digits or less: 1234
strlen(buf)=5, buf=1234
, strlen(s)=5, s=1234
.

>>Enter string, 5 digits or less: 12345
strlen(buf)=5, buf=12345, strlen(s)=5, s=12345.

>>Enter string, 5 digits or less: 123456
strlen(buf)=5, buf=12345, strlen(s)=5, s=12345.

You'll notice:

  1. The return buffer retains the "\n" as long as the #/digits are < MAX_DIGITS.

  2. The "\n" is REMOVED when #/digits >= MAX_DIGITS.

  3. Your buffer must accomodate MAX_DIGITS+1

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • @kumar To store newline is should be + 2 as fgets is already taking away one for storing a null terminator value -> '\0'; That is, if you pass it 6 it will read at most 5 things (4 digits + CR or 5 digits). If you pass it 7 it will read 5 digits plus a carriage return. – Scooter Aug 21 '12 at 23:09
-1

Actually fgets requires a size specification (in your case 11) account for the \0 at the end of a string. From the fgets 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 we know that reading stops at \n, when you enter 123456789\n. However when you enter 1234567890\n, fgets() processes the input but it only takes the 10 characters and ignores everything else afterwards.

Any extra input of your string and your string will at size-1 of fget() with last character as \0 so the output remains the same.

Ahmed Masud
  • 21,655
  • 3
  • 33
  • 58