Hi,
I am required to first read a number, n and then n lines of string. The strings can contain leading spaces which has to be preserved:

2
" hello world"
...

using

scanf("%d", &n);
for (int i = 0;i < n;i++)
{
         scanf(" [^\n]", message);
         ....
         printf("Case #%d: %d\n",case_count, count);
}

ignores the leading space.

while doing

scanf("%d", &n);
for (int i = 0;i < n;i++)
{
         scanf("[^\n]", message);
         ....
         printf("Case #%d: %d\n",case_count, count);
         case_count++;
}

gives peculiar result. As soon as 2 is entered it shows the result:
Case #1: 0
Case #2: 0
without waiting to take " hello world"

ie bypasses the computation. As the computation excludes '\n' and '\r' characters hence I suppose it takes '\n' as string 1 and '\r' as string 2 and therefore the count is not updated.

Using gets and fgets does not help either. So now how can this problem be solved elegantly where I can take both the integer and back-to-back strings without any hassle. Is there any smart function which can take care of this (ie ignores new line and includes leading space characters)?

Thankse.

Dani AI

Generated

The root cause is mixing token-oriented input and line-oriented input. Reading the integer with a token read leaves the end-of-line in the stream, and certain scanf formats (or a leading space in a format) will either skip that newline or skip leading spaces on the next line — which is exactly why the examples in the thread behave oddly. is right to push a line-oriented approach: treat the whole input as lines and parse the integer from the first line, then read the next n lines verbatim so leading spaces are preserved.

A compact, robust approach (POSIX) is to use getline() to grab entire lines and strtol() to parse the count. This preserves every character the user typed (including leading spaces), and you only strip a trailing '\n' (and, on Windows, a trailing '\r') when you need to.

char *line = NULL;
size_t cap = 0;
ssize_t r = getline(&line, &cap, stdin);
if (r <= 0) /* handle EOF/error */;

char *end;
long n = strtol(line, &end, 10);
/* validate n and errors from strtol */

for (long i = 0; i < n; ++i) {
    r = getline(&line, &cap, stdin);
    if (r <= 0) break;          /* EOF or error */
    if (r > 0 && line[r-1] == '\n') line[--r] = '\0';
    if (r > 0 && line[r-1] == '\r') line[--r] = '\0'; /* handle CRLF */
    /* process 'line' — leading spaces are intact */
}
free(line);

If getline() is unavailable, the same idea applies with a fixed buffer: read the first full line into a buffer and use strtol() to parse n, then use fgets() for the subsequent lines. If you prefer to keep a token read for the integer, consume the rest of that line (read and discard characters until '\n') before doing fgets() loops — this matches ’s “read char at a time” idea but only as a tiny cleanup step.

Quick tips: always check return values, validate strtol()’s end pointer, only strip trailing newline/CR (don’t trim left), and choose a dynamic read (getline) if line length is unpredictable.

Recommended Answers

All 2 Replies

If fgets() doesn't work, I can only think of reading a character at a time..

But, you should see this about scanf() and strings.

fgets() would work perfectly well, IF you used it to read the first integer as well.

fgets( buff, sizeof buff, stdin );
sscanf( buff, "%d", &n );

Then fgets() inside the loop will preserve everything the user types in, and you can do what you want.

If you mix and match your input methods, then a disaster is all but certain (as in this case).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.