Problem with scanf and fgets

2019-02-15 07:27发布

This is for a homework assignment to sort some given strings. I'm prompting the user for the number of strings they'd like to sort with scanf, allocating an array based on that number, and then getting the strings themselves with fgets.

Everything works fine if the number of strings is hardcoded, but the addition of scanf to let the user decide screws things up. Here's the code:

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

#define LENGTH  20 // Maximum string length.

int main(void)
{
    int index, numStrings = 0;
    char **stringArray;
    printf("Input the number of strings that you'd like to sort: ");
    assert(scanf("%d", &numStrings) == 1);
    stringArray = (char **)malloc(numStrings * sizeof(char *));

    for (index = 0; index < numStrings; index++)
    {
        stringArray[index] = (char *)malloc(LENGTH * sizeof(char));
        assert(stringArray[index] != NULL);
        printf("Input string: ");
        assert(fgets(stringArray[index], LENGTH, stdin) != NULL);
    }

    // Sort strings, free allocated memory.

    return 0;
}

And here's what the console looks like:

Input the number of strings that you'd like to sort: 3
Input string: Input string: foo
Input string: bar

It skips over the first iteration of the loop, resulting in an empty string at the beginning of the array. My question is, why does it do that, and how can I fix it?


Here's what the console looks with the format string "%d\n" passed to scanf:

Input the number of strings that you'd like to sort: 3
foo
Input string: Input string: bar
Input string: baz

So, I can input all of the strings, but the first prompt for a string is in the wrong place.

2条回答
孤傲高冷的网名
2楼-- · 2019-02-15 08:04

The real answer (in my humble but ever-so-correct opinion :P) is not to use scanf. Use fgets to read the first line (i.e. the number) and then parse that string yourself with, say, sscanf or strtoul. That way you have the ability to handle errors when someone doesn't input the data in a nice format, and you don't have to hack around scanf's lack of robust whitespace handling.

Also, never used an int to store sizes unless you expect to have a lot of arrays with -4 length. The standard specifies the unsigned type size_t as an unsigned type that is large enough to store object sizes and array indices. Using any other type isn't guaranteed to work.

查看更多
虎瘦雄心在
3楼-- · 2019-02-15 08:09

You have to tell scanf to clobber the \n by putting \n in the scanf:

scanf("%d\n", &numStrings)

without it, scanf will read the residual newline character [from when the enter button was hit] as the first line in the loop

查看更多
登录 后发表回答