2011-08-31 116 views
0

这是一个家庭作业问题。我的编译器是CodeBlocks。使用for循环中的struct问题

这里是我的代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

struct Address{ 
    char number[5]; 
    char street[30]; 
    char city[30]; 
}; 

struct Employee{ 
    char ID[7]; 
    char name[31]; 
    struct Address *addr; 
}; 

int main(){ 
    int n,i; 
    char temp[7]; 
    printf("Enter number of Employee : "); 
    scanf("%d",&n); 
    struct Employee **p=(struct Employee **)malloc(n*sizeof(struct Employee *)); 

    for (i=0; i<n; i++) 
    { 
     p[i]=(struct Employee *)malloc(sizeof(struct Employee)); 
     p[i]->addr=(struct Address *)malloc(sizeof(struct Address)); 
    } 

    for(i=0; i<n; i++) 
    { 
     printf("Employee #%d\n",i+1); 
     printf("Enter ID : "); 
     gets(p[i]->ID); 
     printf("Enter Name : "); 
     gets(p[i]->name); 
     printf("Enter Home number : "); 
     gets(p[i]->addr->number); 
     printf("Enter Street : "); 
     gets(p[i]->addr->street); 
     printf("Enter City : "); 
     gets(p[i]->addr->city); 
    } 
} 

我的问题是,当我运行这段代码,我不能为#1名员工输入ID;但是,我可以输入员工#2和#3的ID。

我的问题在哪里?

+2

因为'scanf'在后面留下换行符。也不要使用'gets',你的代码是可怕的(没有冒犯,但所有那些(非常小!)固定大小的缓冲区,没有检查...) – user786653

+0

我秒这。考虑阅读['getline'](http://www.crasseux.com/books/ctutorial/getline.html#getline),并使用'strncpy'将行的第一个'n'字符复制到结构字段中。 –

+0

也没有必要施放'malloc'的返回。 –

回答

1

似乎有一些问题,gets()在循环的第一遍之前从控制台读取一些东西。

在循环似乎解决它之前添加gets(temp);。更好的解决方案是使用除get()之外的其他东西。

+1

嗯,如果我们只是想快速修复,我更喜欢'scanf(“%d [\ n]”,&n);' – user786653

+0

是的,这段代码太糟糕了,我不能让自己做任何事情,只是一个快速入侵。 :-)一旦他的工作成绩达到要求,教练就可以对整个结果进行评分。 –

0

初始scanf("%d", &n);不消耗尾随换行符,因此它可用于gets()调用。

顺便提一句,从不使用gets()。它不能安全使用。例如,如果您正在读取一个6字节的数组,并且用户输入了10个字符,则会发生缓冲区溢出。考虑使用fgets()代替(但请注意,与gets()不同,它将'\n'字符留在缓冲区中)。

+0

如果它的第二个参数很小,fgets还会在缓冲区中留下'\ n'。 – user411313

+0

@ user411313:通过“缓冲区”,我的意思是它存储该行的数组。如果length参数足够大(或者输入的行很短),则字符串的末尾会有一个'\ n'';如果不是,只读取一部分行,其中不包括''\ n'',它将保留下一个输入操作。你仍然需要做一些额外的工作,在存在很长的输入行的情况下保持100%的稳定性,但是对于这样一个简单的练习,只需要使目标数组足够大并忽略问题就可能了。 (这当然比'gets()'好。) –

0

您应该在任何用户输入后清楚地清除输入缓冲区。而且你应该让大小限制器的输入安全。你应该使用scanf的返回值。

scanf("%d",&n);while(getchar()!='\n'); 
... 
scanf("%6[^\n]",p[i]->ID);while(getchar()!='\n'); 
... 
scanf("%30[^\n]",p[i]->name);while(getchar()!='\n'); 
... 
scanf("%4[^\n]",p[i]->addr->number);while(getchar()!='\n'); 
... 
scanf("%29[^\n]",p[i]->addr->street);while(getchar()!='\n'); 
... 
scanf("%29[^\n]",p[i]->addr->city);while(getchar()!='\n');