C语言打印人员信息为空问题求助:numOfPersons索引无法输出数据
问题分析与解决
核心问题:索引错误
你代码里的addPerson函数逻辑是先把新人员数据存入personDataBase.personList[personDataBase.numOfPersons],紧接着执行personDataBase.numOfPersons++,这就导致numOfPersons的值比刚存入数据的索引大1。比如第一次添加人员时,初始numOfPersons是0,数据存在索引0的位置,自增后numOfPersons变成1,此时用1作为索引访问,指向的是未初始化的空元素,所以输出为空。而用索引0能正常打印,正好验证了这一点。
修复步骤
- 修正main函数的索引:把访问索引改成
personDataBase.numOfPersons - 1,指向刚添加的人员数据。 - 调整createPerson的输出语句位置:
return p;之后的打印语句永远不会执行,把它移到return之前。 - 替换不安全的gets函数:改用
fgets避免缓冲区溢出,注意手动去除输入末尾的换行符。 - 修复ID重复检查逻辑:只遍历已添加的人员(
i < personDataBase.numOfPersons),避免和未初始化的空元素比较。
修改后的完整代码
#include <stdio.h> #include <string.h> typedef struct person { char firstName[40]; char lastName[40]; char id[40]; } Person; struct personDataBase { Person personList[100]; int numOfPersons; } personDataBase; // 去除字符串末尾的换行符 void removeNewline(char *str) { str[strcspn(str, "\n")] = '\0'; } Person createPerson() { Person p; printf("Please enter your first name:\n"); fgets(p.firstName, sizeof(p.firstName), stdin); removeNewline(p.firstName); printf("Please enter your last name:\n"); fgets(p.lastName, sizeof(p.lastName), stdin); removeNewline(p.lastName); printf("Please enter your ID number:\n"); fgets(p.id, sizeof(p.id), stdin); removeNewline(p.id); // 只检查已添加的人员 for (int i = 0; i < personDataBase.numOfPersons; i++) { while (strcmp(p.id, personDataBase.personList[i].id) == 0) { printf("ID already registered in the system, please enter ID correctly:\n"); fgets(p.id, sizeof(p.id), stdin); removeNewline(p.id); } } printf("** Client registered successfully **\n"); return p; } void addPerson() { personDataBase.personList[personDataBase.numOfPersons] = createPerson(); personDataBase.numOfPersons++; printf("** New person added to the system **\n"); } int main() { addPerson(); // 使用numOfPersons - 1作为索引 int lastIndex = personDataBase.numOfPersons - 1; puts(personDataBase.personList[lastIndex].firstName); puts(personDataBase.personList[lastIndex].lastName); puts(personDataBase.personList[lastIndex].id); return 0; }
说明
- 新增的
removeNewline函数用来处理fgets读取到的换行符,避免输出时多一个空行。 - ID检查循环现在只遍历已添加的人员,避免了未初始化内存的干扰。
- 替换
gets为fgets后,输入长度被限制在数组大小内,不会出现缓冲区溢出问题。
内容的提问来源于stack exchange,提问作者דניאל בוזגלו
相关产品推荐
相关产品推荐

