C语言结构体链表打印结构体数组元素异常问题求助
你遇到的问题核心是结构体设计错误+内存越界访问,导致链表节点只保存了第一个候选人的信息,其余候选人的信息根本没被正确存入链表节点。
原因拆解
1. 结构体设计不符合需求
你的election结构体里只定义了一个char name_candidate[n]数组,这只能存一个候选人的名字。但你在createElection里用(pole+i)->name_candidate来写入第i个候选人的名字,本质是把pole(也就是info指针)当成了election数组来操作——但info只通过malloc(sizeof(election))申请了单个election的内存空间,后续的(pole+1)、(pole+2)都是越界访问info后面的未知内存。
直接打印info时能显示所有候选人名字,纯粹是因为那段越界的内存暂时还没被其他操作覆盖,属于“侥幸”行为,本身已经是非法内存访问了。
2. 链表插入时只复制了单个election的内容
insertElection里执行newnode->voting = *info;,只会复制单个election结构体的内容——也就是info指向的第一个election大小的内存,而你越界写入到info后面的候选人名字,根本不会被复制到链表节点里。
3. 打印函数的遍历逻辑错误
在printElection里,你用(tmp+i)->voting.name_candidate来获取第i个候选人的名字,这里的tmp是链表节点指针,tmp+i会指向链表的第i个节点(甚至越界),而不是当前节点里的第i个候选人。每个链表节点的voting成员只有一个name_candidate,所以后面的打印自然是空的。
解决步骤
步骤1:修改election结构体,支持存储多个候选人名字
把name_candidate改成二维数组(假设最多存10个候选人,可按需调整):
typedef struct pole{ int year; char county[n]; char ID_election[n]; char ID_electionUser[n]; int num_candidates; char name_candidate[10][n]; // 改成二维数组,存多个候选人名字 int limit_votes; }election;
如果候选人数量不确定,也可以用动态分配的指针数组,比如char **name_candidate;,但二维数组实现更简单。
步骤2:修正createElection的写入逻辑
不再用越界的(pole+i),直接访问二维数组的对应索引:
void createElection(node_pole *head_pole, election *info){ election *pole = info; int i = 0; printf("\nInsert data: \n Year: "); scanf("%d", &pole->year); printf(" County:"); scanf("%s", pole->county); printf(" Voters' limit:"); scanf("%d", &pole->limit_votes); printf("ID_Election: "); scanf("%s", pole->ID_election); printf("ID_Election_User: "); scanf("%s", pole->ID_electionUser); printf("Candidates' number: "); scanf("%d", &pole->num_candidates); // 检查候选人数量不超过数组上限 if(pole->num_candidates > 10){ printf("Too many candidates, max 10 allowed.\n"); pole->num_candidates = 10; } for(i = 0; i < pole->num_candidates; i++){ printf("\n Candidates' names [%d]:", i+1); scanf("%s", pole->name_candidate[i]); // 直接访问二维数组的第i行 } return; }
步骤3:修正printElection的遍历逻辑
直接访问当前节点voting成员里的二维数组:
void printElection(node_pole *head_pole){ int i; node_pole *tmp = head_pole; if(tmp == NULL){ printf("\nNo poll in the database."); return; } while(tmp != NULL){ printf("\n----- Your election ----- "); printf("\nID Election:%s \nID Elect_User: %s \nYear:%d \nCounty:%s \nMax voters:%d", tmp->voting.ID_election, tmp->voting.ID_electionUser, tmp->voting.year, tmp->voting.county, tmp->voting.limit_votes); printf("\nCandidates' number:%d", tmp->voting.num_candidates); for(i = 0; i < tmp->voting.num_candidates; i++){ printf("\nCandidates' name [%d]: %s", i + 1, tmp->voting.name_candidate[i]); // 访问当前节点的候选人数组 } tmp = tmp->next_pole; } return; }
步骤4:修正主函数里的打印逻辑
同样改成访问二维数组,避免之前的越界访问:
for(i = 0; i < info->num_candidates; i++){ printf("\nCandidates' name [%d]: %s", i+1, info->name_candidate[i]); }
额外提醒
- 之前的
(pole+i)->name_candidate属于未定义行为,虽然暂时能显示,但随时可能因为内存被覆盖导致程序崩溃或输出乱码,必须修正。 - 如果候选人数量动态变化,建议用指针数组+动态分配:在
createElection里根据num_candidates为name_candidate分配内存,记得在销毁链表时释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者DM10

