2014-09-03 45 views
-2
#include <stdio.h> 
#include <conio.h> 

struct person { 
    char name[50]; 
    int id; 
    int age; 
}; 

int main() { 
    struct person p[4]; 

    int i; 
    for (i = 0; i < 4; i++) { 
     printf("Enter the person%d details\n", i + 1); 
     gets(p[i].name); 
     scanf("%d", &p[i].id); 
     scanf("%d", &p[i].age); 
    } 
    printf(
     "------------------------------------------------------------------"); 
    for (i = 0; i < 4; i++) { 
     printf("\nPerson%d details\n", i + 1); 
     printf("Name:%s\nID:%d\nAge:%d\n", p[i].name, p[i].id, p[i].age); 
     printf("---------------------------------------------------------------" 
       "---"); 
    } 

    getch(); 
    return 0; 
} 

输出:C结构串读出错误

Enter person1 details 
mark mike 
123 
24 

Enter person2 details 
sourav ganguly 
Enter person3 details 

的问题是为什么scanf不接受person2 id and age细节。任何帮助,将不胜感激。

+2

频繁重复 - 对于同样的问题,存在很多等同的问题。 '%d'格式在缓冲区中保留了换行符,而'gets()'(它不应该被首先使用) - 使用'fgets()'代替)将新行读为整条线。如果您也注意输入函数的返回值,那么您会知道更多 - 您不能检查输入函数。 – 2014-09-03 14:53:20

回答

0

new-line字符在输入之后的第一次迭代循环中未被scanf读取。它在输入流中被最后的scanf保留在人#1的迭代上。

在下一次迭代中,待处理的new-line字符被gets读取,并被解释为空字符串,即人员#2的空名称。程序然后等待您的输入。你假设它等待人#2的名字,但实际上它等待为人#2的id。您输入sourav ganguly(错误地认为您输入了名称),但scanf将其视为%d格式说明符的错误输入。这导致人#2的scanfs跳过垃圾idage人#2。同时,sourav ganguly仍保留在输入流中。

在下一次迭代中,sourav ganguly最终被gets读取为人#3的名称。等等......

如果你在每个scanf的前面加上一个额外的调试printf's,你会看到实际发生了什么。例如。试试这个,看看会发生什么

for (i = 0; i < 4; i++) { 
    printf("Enter the person%d name\n", i + 1); 
    gets(p[i].name); 
    printf("Enter the person%d id\n", i + 1); 
    scanf("%d", &p[i].id); 
    printf("Enter the person%d age\n", i + 1); 
    scanf("%d", &p[i].age); 
} 

修复它是停止混合getsscanf输入尝试的最佳方式。解决这个问题的一种方法是将所有数据作为字符串读取,然后手动解析。解决它的另一种方法是摆脱gets并使用scanf来代替。 scanf可用于读取其中有空格的字符串,但看起来不会很漂亮。无论如何,scanf文档将帮助你弄清楚这一点。 (提示:请阅读%[]格式说明符。)

无论如何gets功能不应该使用,因为它不提供缓冲区溢出保护。