odin19
odin19

Reputation: 159

fgets() not scanning the number of strings I want

I have an array of sentences and I want to scan them first with fgets() and then print them one by one. Here is the program:

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





int main(int argc,char *argv[]) {

    char sentence[100][100]; /* 100 sentences with at most 100 characters*/
    int n,i,j;

    scanf("%d",&n); /* number of sentences*/

    for (i=0;i<n;i++) {
        fgets(sentence[i],100,stdin);
    }
    printf("****************************");
    for (i=0;i<n;i++) {
        for(j=0;j<strlen(sentence[i]);j++) {
            putchar(sentence[i][j]);
        }

    }


    return 0;
}

The problem is that this only scans n-1 sentences. Why is that?

And the other weird thing is that after printing the asterisks, it starts printing at a new line without me telling it to do so.

Upvotes: 1

Views: 292

Answers (3)

Sourav Ghosh
Sourav Ghosh

Reputation: 134326

Both the cases will be solved by one concept, fgets() considers a newline as a part of the input.

Issue 1:

You have a newline left in the input buffer (due to the ENTER key press after the first input) which is picked up by the immediate next fgets().

Resolve issue 1:

Use

  scanf("%d%*c",&n);   //simple solution

or

 scanf("%d",&n);
 while (getchar() != '\n');  //eat up anything upto newline

to clear the trailing newline.

Issue 2:

fgets() scans and stores the newline as a per of the input. If you don't want the newline as a part of the input, you've to check and remove that manually.

Related quote from the man page:

[...] If a newline is read, it is stored into the buffer. [...]

Resolve issue 2:

  sentence[strcspn(sentence, "\r\n")] = 0;

Thanks to @chux, more about this here

Upvotes: 1

Claudio Cortese
Claudio Cortese

Reputation: 1380

Did you read the man page for 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 ('\0') is stored after the last character in the buffer.

So your code should be, as pointed out by chux :

fgets(sentence[i],sizeof sentence[i],stdin);

Upvotes: 0

microtony
microtony

Reputation: 192

Assume the input is

3
abc
def
ghi

The cursor stays after the number 3 on the first line after n is scanned.

You can add a space after %d, like scanf("%d ", &n); to move the cursor to the next line. (This assumes that the first sentence does not start with spaces).

Depends on whether your environment is (Windows / Unix), and whether you want every string to keep the end of line character, you need to increase the buffer size to:

  • 101 - for Unix line ending and you are fine to discard the end of line character for sentences of 100 characters long
  • 102 - for Windows line ending and you are fine to discard the end of line character for sentences of 100 characters long
  • 102 - for Unix line ending and you want to keep the end of line character for all sentences
  • 103 - for Windows line ending and you want to keep the end of line character for all sentences

For example, if you incorrectly used 101 for Windows, for the following input

0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

The output would be:

0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789


0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789


0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

(there are some empty lines)

Upvotes: 1

Related Questions