问题
I am writing a program to write my html files rapidly. And when I came to write the content of my page I got a problem.
#include<stdio.h>
int main()
{
int track;
int question_no;
printf("\nHow many questions?\t");
scanf("%d",&question_no);
char question[question_no][100];
for(track=1;track<=question_no;track++)
{
printf("\n<div class=\"question\">%d. ",track);
printf("\nQuestion number %d.\t",track);
fgets(question[track-1],sizeof(question[track-1]),stdin);
printf("\n\n\tQ%d. %s </div>",track,question[track-1]);
}
}
In this program I am writing some questions and their answers (in html file). When I test run this program I input the value of question_no
to 3. But when I enter my first question it doesn't go in question[0]
and consequently the first question doesn't output. The rest of the questions input without issue.
I searched some questions on stackoverflow and found that fgets()
looks for last \0
character and that \0
stops it.
I also found that I should use buffer to input well through fgets()
so I used: setvbuf
and setbuf
but that also didn't work (I may have coded that wrong). I also used fflush(stdin)
after my first and last (as well) scanf
statement to remove any \0
character from stdin but that also didn't work.
Is there any way to accept the first input by fgets()
?
I am using stdin and stdout for now. I am not accessing, reading or writing any file.
回答1:
Use fgets
for the first prompt too. You should also malloc
your array as you don't know how long it is going to be at compile time.
#include <stdlib.h>
#include <stdio.h>
#define BUFSIZE 8
int main()
{
int track, i;
int question_no;
char buffer[BUFSIZE], **question;
printf("\nHow many questions?\t");
fgets(buffer, BUFSIZE, stdin);
question_no = strtol(buffer, NULL, 10);
question = malloc(question_no * sizeof (char*));
if (question == NULL) {
return EXIT_FAILURE;
}
for (i = 0; i < question_no; ++i) {
question[i] = malloc(100 * sizeof (char));
if (question[i] == NULL) {
return EXIT_FAILURE;
}
}
for(track=1;track<=question_no;track++)
{
printf("\n<div class=\"question\">%d. ",track);
printf("\nQuestion number %d.\t",track);
fgets(question[track-1],100,stdin);
printf("\n\n\tQ%d. %s </div>",track,question[track-1]);
}
for (i = 0; i < question_no; ++i) free(question[i]);
free(question);
return EXIT_SUCCESS;
}
2D arrays in C
A 2D array of type
can be represented by an array of pointers to type
, or equivalently type**
(pointer to pointer to type
). This requires two steps.
Using char **question
as an exemplar:
The first step is to allocate an array of char*
. malloc
returns a pointer to the start of the memory it has allocated, or NULL
if it has failed. So check whether question
is NULL
.
Second is to make each of these char*
point to their own array of char
. So the for
loop allocates an array the size of 100 char
s to each element of question
. Again, each of these malloc
s could return NULL
so you should check for that.
Every malloc
deserves a free
so you should perform the process in reverse when you have finished using the memory you have allocated.
malloc reference
strtol
long int strtol(const char *str, char **endptr, int base);
strtol
returns a long int
(which in the code above is casted to an int
). It splits str
into three parts:
- Any white-space preceding the numerical content of the string
- The part it recognises as numerical, which it will try to convert
- The rest of the string
If endptr
is not NULL
, it will point to the 3rd part, so you know where strtol
finished. You could use it like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char * endptr = NULL, *str = " 123some more stuff";
int number = strtol(str, &endptr, 10);
printf("number interpreted as %d\n"
"rest of string: %s\n", number, endptr);
return EXIT_SUCCESS;
}
output:
number interpreted as 123
rest of string: some more stuff
strtol reference
回答2:
This is because the previous newline character left in the input stream by scanf(). Note that fgets() stops if it encounters a newline too.
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
Don't mix fgets() and scanf(). A trivial solution is to use getchar() right after scanf() in order to consume the newline left in the input stream by scanf().
回答3:
As per the documentation,
The fgets() function shall read bytes from stream into the array pointed to by s, until n-1 bytes are read, or a < newline > is read and transferred to s, or an end-of-file condition is encountered
In case of scanf("%d",&question_no);
a newline is left in the buffer and that is read by
fgets(question[track-1],sizeof(question[track-1]),stdin);
and it exits.
In order to flush the buffer you should do,
while((c = getchar()) != '\n' && c != EOF)
/* discard */ ;
to clear the extra characters in the buffer
来源:https://stackoverflow.com/questions/20092468/why-fgets-is-not-inputting-first-value