问题
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.
回答1:
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.
回答2:
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
来源:https://stackoverflow.com/questions/4929338/problem-with-scanf-and-fgets