【问题标题】:Why fgets is not inputting first value?为什么 fgets 没有输入第一个值?
【发布时间】:2013-12-04 05:46:35
【问题描述】:

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

#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]);
    }

}

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

我在 stackoverflow 上搜索了一些问题,发现 fgets() 查找最后一个 \0 字符,而 \0 将其停止。
我还发现我应该使用 buffer 通过fgets() 很好地输入,所以我使用了:setvbufsetbuf,但这也没有用(我可能编码错误)。在我的第一个和最后一个(以及)scanf 语句之后,我还使用了fflush(stdin) 从标准输入中删除任何\0 字符,但这也不起作用。

有什么方法可以接受fgets() 的第一个输入吗?
我现在使用标准输入和标准输出。我没有访问、读取或写入任何文件。

【问题讨论】:

  • @interjay 不!这是真的。 :D 这只是我的。
  • 什么?我只是说这个问题与链接的问题基本相同。我没有说你复制它或类似的东西。它只是一个自动生成的评论,当有人投票关闭一个问题作为另一个问题的副本时创建。
  • @AshishTomer;是的,我们知道这是你的:)。 @interjay 只是想说这种类型的问题以前已经被问过了。
  • 好的! :D :D 哈哈哈

标签: c input io output fgets


【解决方案1】:

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

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

C 中的二维数组

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

char **question 为例:

第一步是分配一个char*的数组。 malloc 返回一个指向它已分配内存开始的指针,或者 NULL 如果它失败了。所以检查question是不是NULL

第二个是让每个char* 指向它们自己的char 数组。所以for 循环为question 的每个元素分配一个大小为100 chars 的数组。同样,这些mallocs 中的每一个都可能返回NULL,所以你应该检查一下。

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

malloc reference

strtol

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

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

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

如果endptr 不是NULL,它将指向第三部分,所以你知道strtol 在哪里结束。你可以这样使用它:

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

输出:

number interpreted as 123
rest of string: some more stuff

strtol reference

【讨论】:

  • 我已经在询问用户他想输入的问题数量。那我为什么要使用malloc。 malloc 不会增加处理时间吗?因为这个程序看起来比我的要长得多。 (我是初学者:P)
  • 您在程序执行过程中发现数组应该有多大——您事先并不知道。即使您依赖用户的手动输入,您是否真的担心执行几个mallocs 所需的时间?
  • @AshishTomer 我还为您添加了几行 - 您应该检查 malloc 是否成功。如果不是,则返回一个NULL 指针。
  • 我很高兴您通过第一个 for 循环创建二维数组。 if statement 在第一个 for loop 中是否检查 malloc 是否成功?另外,strtol() 函数中第二个参数的作用是什么?我在互联网上读到了一些你想要转换为长整数的字符的下一个字符。但这还不够清楚。你能给我解释一下吗?或者,如果你能给我一个链接。
  • 我无法消化你的回答:
【解决方案2】:

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

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

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

【讨论】:

  • 我只是在scanf(....) 声明之后写getchar(); 吗?不会出错吧?
  • 是的,getchar(); 在 scanf() 之后。这不会是一个错误,因为 getchar() 只是读取一个字符并且您将其丢弃而不存储。您还应该检查 scanf() 上的输入失败。
  • @hacks 不,我只是在问。
【解决方案3】:

根据documentation

fgets() 函数应该从流中读取字节到数组中 由 s 指向,直到 n-1 个字节被读取,或者 a 被读取并且 转移到s,或遇到文件结束条件

scanf("%d",&amp;question_no); 的情况下,缓冲区中会留下一个换行符并由

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

然后退出。

为了flush the buffer你应该这样做,

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

清除缓冲区中多余的字符

【讨论】:

  • Yeeeeiiiiii!!!!它正在工作!呜呜呜!谢谢@Vusp!这真的很有帮助:) :D
  • 它消耗了我一整天。该死!
猜你喜欢
  • 2022-01-10
  • 2021-03-02
  • 2021-10-08
  • 1970-01-01
  • 2020-07-24
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 2011-08-30
相关资源
最近更新 更多