如何在使用结构指针时实现gets()或fgets()?

时间:2014-01-15 13:07:21

标签: c struct fgets

以下代码与scanf()完美匹配,但我想输入字符和空格。我已经尝试了gets()fgets()(下面评论过),但它不起作用(它跳转到循环中的下一次迭代,并在{{1}使用的名称输入的输出期间显示空白(NULL) })。知道怎么做吗?

PS:我已经尝试了fgets()样本程序,它的工作正常。但是在使用结构指针时我很困惑。

fputs()
  

输出:

#include <stdio.h>
#include <stdlib.h>
struct details {
    uint Id;
    char Name[20];
};

int main() {
    int tot, i;
    struct details *info;
    printf("Enter no. of details to be stored = ");
    scanf("%d", &tot);
    info = (struct details *)malloc(tot*sizeof(struct details));

    for(i=0; i<tot; i++) {
        printf("%d)Id = ", i+1);
        scanf("%d", &info->Id);
        printf("%d)Name = ", i+1);
        fgets(info->Name, 20, stdin); //How to make fgets() work??
        //scanf("%s", &info->Name); //works fine with scanf() 
        info++;
    }

    for(i=0; i<tot; i++) {
    --info;
    }

    printf("\nDisplaying details:\n");
    for(i=0; i<tot; i++) {
        printf("%d)Id = %d\n%d)Name = %s\n", i+1, info->Id, i+1, info->Name);
    info++;
    }

return 0;
}

4 个答案:

答案 0 :(得分:4)

问题来自&#34;%d&#34; scanf函数。它不消耗行终止符,因此下一次读取会将其解释为空行。

您的info分配也是错误的。分配大小的用途不是info的大小,而是info指向的元素的大小。

printf("Enter no. of details to be stored = ");
scanf("%d\n", &tot); // <-- must consume end of line here
info = (struct details *)malloc(tot*
   sizeof(*info)); // <-- use size of the pointed object, not the pointer

此外,修改你的info指针是不必要和危险的 这样的事情会更简单,更安全

for(i=0; i<tot; i++) {
    printf("%d)Id = ", i+1);
    scanf("%d\n", &info[i].Id)); // <-- store input in current info record
                                 // and eat up the line terminator
    printf("%d)Name = ", i+1);
    fgets(info[i].Name,          // <-- idem
          sizeof(info[i].Name),  // fgets will guarantee no buffer overflow
          stdin);
}

printf("\nDisplaying details:\n");
for(i=0; i<tot; i++) {
    printf("%d)Id = %d\n%d)Name = %s\n", i+1, info[i].Id, i+1, info[i].Name);

对于scanf / fgets,在你的情况下(使用&#34;%s&#34;格式为scanf),他们都应该读取输入,直到输入新行,包括空格。

编辑:我在这里说错了,抱歉,感谢chux纠正我。

scanf ("%s")确实会停在第一个空白区域。如果你想要整条线,最简单的方法就是使用fgets。如果您真的想使用scanf,则需要使用"%[^\n]%*c"之类的语法。

如果用户输入超过20个字符,要确保缓冲区不会溢出,您可以

  • 使用"%19[^\n]%*c"作为scanf格式(&#39; \ 0&#39;终止符需要第20个字符),或
  • 使用fgets作为缓冲区大小传递20(fgets负责终结器,它最多可读取19个字符,以便能够添加&#39; \ 0&#39;溢出)。

当然,您应该使用sizeof来计算最大缓冲区大小,例如:

fgets(info[i].Name, sizeof(info[i].Name), stdin);

因此,如果您决定将缓冲区大小更改为50个字符,则不必修改该值。

答案 1 :(得分:2)

首先,您的代码中存在严重错误。

info = (struct details *)malloc(tot*sizeof(info));

sizeof(info)返回4或8(取决于平台,32位或64位),但与结构大小无关。所以你为指针分配内存,但是正在为你的struct使用那个空间。将数据写入此将覆盖内存中的其他数据(尽管可能不是在这个简单的示例中),因为您分配的字节太少。您想要使用的是sizeof(struct details),它将返回24。

现在输入您的输入问题。基本上,scanf和gets不应该像这样一起使用。问题是scanf会读取您键入的内容,直到您按下return(不包括在内)。在此之后调用gets时,它会看到此返回并立即返回一个空字符串。如果您将所有输入调用更改为gets,它将完美运行。例如:

char test[256];
printf("Enter no. of details to be stored = ");
gets(test);
tot = atoi(test);

答案 2 :(得分:0)

ID为scanf()的行与fgets()之间的

getchar() 像这样

scanf("%d",&(info->Id));
getchar();

答案 3 :(得分:-3)

我遇到了同样的问题!实际上,我来到这个页面来获得解决方案然后我记得缓冲区!所以这就是我解决它的方式:

[...]

cout << "\nType the name: " ;
fflush(stdin); (you always have to clean the buffer before saving chars to a variable)
gets(pers.nom);

[...]

干杯!! 附: cin和cout来自C ++,但像scanf和printf

一样工作