投票统计程序处理大量数据时出现Segmentation fault及无效投票问题求助
问题描述
我编写的投票统计C语言程序在处理少量数据时可正常运行,但处理大量数据时出现异常:
- 重复输入同一候选人姓名,第一次投票能正常增加票数,第二次却提示"invalid name"且不计数
- 输入其他候选人姓名时触发"Segmentation fault (core dumped)"错误
程序代码如下:
#include <cs50.h> #include <stdio.h> #include <string.h> // Max number of candidates #define MAX 9 // Candidates have name and vote count typedef struct { string name; int votes; } candidate; // Array of candidates candidate candidates[MAX]; // Number of candidates int candidate_count; // Function prototypes bool vote(string name); void print_winner(void); int largest(int list[], int n); int main(int argc, string argv[]) { // Check for invalid usage if (argc < 2) { printf("Usage: plurality [candidate ...]\n"); return 1; } // Populate array of candidates candidate_count = argc - 1; if (candidate_count > MAX) { printf("Maximum number of candidates is %i\n", MAX); return 2; } for (int i = 0; i < candidate_count; i++) { candidates[i].name = argv[i + 1]; candidates[i].votes = 0; } int voter_count = get_int("Number of voters: "); // Loop over all voters for (int i = 0; i < voter_count; i++) { string name = get_string("Vote: "); // Check for invalid vote vote(name); if (strcmp(name, candidates[i].name) != 0) { printf("Invalid vote.\n"); } } // Display winner of election print_winner(); } // Update vote totals given a new vote bool vote(string NAME) { for (int i = 0; i < candidate_count; i++) { if (strcmp(NAME, candidates[i].name) == 0) { candidates[i].votes++; } } return false; } // Print the winner (or winners) of the election void print_winner(void) { int Votes_here[candidate_count]; for (int j = 0; j < candidate_count; j++) { Votes_here[j] = candidates[j].votes; } for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes == largest(Votes_here, candidate_count)) { printf("%s\n", candidates[i].name); } } return; } int largest(int list[], int n) { int i; int l = list[0]; for (i = 1; i < n; i++) { if (list[i] > l) l = list[i]; } return l; }
期望程序能正确统计所有票数,并输出得票最多的获胜者。
问题分析与修复方案
1. 核心错误点:主循环无效投票判断逻辑错误
主函数遍历选民的循环用了变量i,之后直接用candidates[i].name和输入姓名对比——这里的i是选民的索引,不是候选人的索引!当选民数量超过候选人数量时,i会超出candidates数组范围,直接访问越界内存导致段错误;即使选民数少,也只会和第i个候选人对比,完全无法正确判断投票是否有效。
2. vote函数逻辑缺陷
vote函数找到匹配候选人后没有返回true,而是遍历完所有候选人后固定返回false,完全没发挥返回值的作用,无法给主函数传递投票是否有效的信号。
修复后的完整代码
#include <cs50.h> #include <stdio.h> #include <string.h> // Max number of candidates #define MAX 9 // Candidates have name and vote count typedef struct { string name; int votes; } candidate; // Array of candidates candidate candidates[MAX]; // Number of candidates int candidate_count; // Function prototypes bool vote(string name); void print_winner(void); int largest(int list[], int n); int main(int argc, string argv[]) { // Check for invalid usage if (argc < 2) { printf("Usage: plurality [candidate ...]\n"); return 1; } // Populate array of candidates candidate_count = argc - 1; if (candidate_count > MAX) { printf("Maximum number of candidates is %i\n", MAX); return 2; } for (int i = 0; i < candidate_count; i++) { candidates[i].name = argv[i + 1]; candidates[i].votes = 0; } int voter_count = get_int("Number of voters: "); // Loop over all voters for (int i = 0; i < voter_count; i++) { string name = get_string("Vote: "); // Check for invalid vote using vote function's return value bool valid = vote(name); if (!valid) { printf("Invalid vote.\n"); } } // Display winner of election print_winner(); } // Update vote totals given a new vote bool vote(string NAME) { for (int i = 0; i < candidate_count; i++) { if (strcmp(NAME, candidates[i].name) == 0) { candidates[i].votes++; return true; // 找到匹配后立即返回true } } return false; // 遍历完都没匹配,返回false } // Print the winner (or winners) of the election void print_winner(void) { int Votes_here[candidate_count]; for (int j = 0; j < candidate_count; j++) { Votes_here[j] = candidates[j].votes; } int max_votes = largest(Votes_here, candidate_count); for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes == max_votes) { printf("%s\n", candidates[i].name); } } return; } int largest(int list[], int n) { int i; int l = list[0]; for (i = 1; i < n; i++) { if (list[i] > l) l = list[i]; } return l; }
修复说明
- 主函数中调用
vote函数时接收其返回值,用该返回值判断投票是否有效,彻底避免了用选民索引访问候选人数组的越界问题。 vote函数在找到匹配候选人并增加票数后立即返回true,未找到则返回false,正确传递投票有效性状态。- 额外优化:
print_winner中先计算出最大票数再遍历判断,避免重复调用largest函数,提升运行效率。
内容的提问来源于stack exchange,提问作者AA-SLF
相关产品推荐
相关产品推荐

