为什么fgets没有输入第一个值?

我正在编写一个程序来快速编写我的html文件。 当我来写我的页面内容时,我遇到了问题。

#include 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
%d. ",track); printf("\nQuestion number %d.\t",track); fgets(question[track-1],sizeof(question[track-1]),stdin); printf("\n\n\tQ%d. %s
",track,question[track-1]); } }

在这个程序中,我正在写一些问题及其答案(在html文件中)。 当我测试运行这个程序时,我将question_no的值输入到3.但是当我输入我的第一个问题时,它没有question[0] ,因此第一个问题没有输出。 其余的问题输入没有问题。

我在stackoverflow上搜索了一些问题,发现fgets()查找最后的\0字符,并且\0停止它。
我还发现我应该使用缓冲区通过fgets()输入,所以我使用: setvbufsetbuf但也没有用(我可能编码错了)。 在我的第一个和最后一个(以及) scanf语句之后我也使用了fflush(stdin)从stdin中删除任何\0字符,但这也没有用。

有没有办法接受fgets()的第一个输入?
我现在正在使用stdin和stdout。 我不访问,读取或写入任何文件。

也可以使用fgets作为第一个提示。 你也应该malloc你的数组,因为你不知道它在编译时会有多长。

 #include  #include  #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
%d. ",track); printf("\nQuestion number %d.\t",track); fgets(question[track-1],100,stdin); printf("\n\n\tQ%d. %s
",track,question[track-1]); } for (i = 0; i < question_no; ++i) free(question[i]); free(question); return EXIT_SUCCESS; }

C中的2D数组

type的2D数组可以由指向type的指针数组表示,或者等效地type** (指向type**指针的指针)。 这需要两个步骤。

使用char **question作为示例:

第一步是分配一个char*数组。 malloc返回指向已分配内存开头的指针,如果失败则返回NULL 。 所以检查question是否为NULL

其次是让每个char*指向自己的char数组。 因此for循环为每个question元素分配一个大小为100 char的数组。 同样,这些malloc的每一个都可以返回NULL因此您应该检查它。

每个malloc应该是free因此当您使用完已分配的内存后,应该反向执行该过程。

malloc参考

与strtol

long int strtol(const char *str, char **endptr, int base);

strtol返回一个long int (在上面的代码中将其转换为int )。 它将str分为三个部分:

  1. 字符串数字内容之前的任何空格
  2. 它识别为数字的部分,它将尝试转换
  3. 其余的字符串

如果endptr不是NULL ,它将指向第3部分,因此您知道strtol完成的位置。 你可以像这样使用它:

 #include  #include  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; } 

输出:

 number interpreted as 123 rest of string: some more stuff 

strtol参考

这是因为scanf()在输入流中留下了前一个换行符。 请注意,如果遇到换行符,fgets()也会停止。

fgets()从流中读取最多一个小于大小的字符,并将它们存储到s指向的缓冲区中。 阅读在EOF或换行后停止。 如果读取换行符,则将其存储到缓冲区中

不要混合fgets()和scanf()。 一个简单的解决方案是在scanf()之后立即使用getchar(),以便通过scanf()消耗输入流中留下的换行符。

根据文档 ,

fgets()函数应从流中读取字节到s指向的数组,直到读取n-1个字节,或者读取并将其传送给s,或者遇到文件结束条件

如果是scanf("%d",&question_no); 缓冲区中会留下一个换行符,并由其读取

 fgets(question[track-1],sizeof(question[track-1]),stdin); 

它退出了。

为了冲洗你应该做的缓冲区 ,

 while((c = getchar()) != '\n' && c != EOF) /* discard */ ; 

清除缓冲区中的额外字符