CS50第二周Plurality问题代码修复:解决2个check50检测错误
CS50第二周Plurality问题代码错误修复
原始代码
#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 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 if (!vote(name)) { 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 < 9; i++) { // If candidate name matches the entered string by voter, then increase vote by 1 if(strcmp(candidates[i].name,name) == 0) { candidates[i].votes += 1; return true; } } return false; } // Print the winner (or winners) of the election void print_winner(void) { // Check which candidate has the most votes int highest = candidates[0].votes; string highest_candidate = candidates[0].name; // For loop to find out most number of votes for (int i = 0; i < 9; i++) { if (candidates[i+1].votes > candidates[i].votes) { highest = candidates[i+1].votes; } } // For loop to print candidates with the most number of votes for (int i = 0; i < 9; i++) { if (candidates[i].votes == highest) { printf("%s\n", candidates[i].name); } } return; }
check50测试结果
:) plurality.c exists :) plurality compiles :) vote returns true when given name of first candidate :) vote returns true when given name of middle candidate :) vote returns true when given name of last candidate :( vote returns false when given name of invalid candidate // Error 1 vote function did not return false :) vote produces correct counts when all votes are zero :) vote produces correct counts after some have already voted :( vote leaves vote counts unchanged when voting for invalid candidate // Error 2 vote function modified vote totals incorrectly :) print_winner identifies Alice as winner of election :) print_winner identifies Bob as winner of election :) print_winner identifies Charlie as winner of election :) print_winner prints multiple winners in case of tie :) print_winner prints all names when all candidates are tied
问题原因
两个错误的根源都是数组越界访问未初始化元素:
vote函数循环条件写死为i < 9,但实际候选人数量是candidate_count(可能小于9)。投票给无效候选人时,循环会遍历到未初始化的candidates[i].name(野指针),调用strcmp触发段错误,导致程序直接崩溃,无法返回false,同时可能意外修改未初始化的votes值,引发错误2。print_winner函数同样写死遍历9次,不仅访问无效元素,还存在i+1超出数组最大索引(8)的越界风险。
修复方案
1. 修复vote函数
将循环条件改为遍历实际存在的候选人:
bool vote(string name) { for (int i = 0; i < candidate_count; i++) { if(strcmp(candidates[i].name, name) == 0) { candidates[i].votes += 1; return true; } } return false; }
2. 修复print_winner函数
修正遍历范围与最高票数查找逻辑:
void print_winner(void) { // 初始化最高票数为第一个候选人的票数 int highest = candidates[0].votes; // 遍历所有候选人,找到最高票数 for (int i = 1; i < candidate_count; i++) { if (candidates[i].votes > highest) { highest = candidates[i].votes; } } // 打印所有得最高票的候选人 for (int i = 0; i < candidate_count; i++) { if (candidates[i].votes == highest) { printf("%s\n", candidates[i].name); } } return; }
修复说明
- 修复后
vote函数仅访问已初始化的候选人元素,无效投票时不会触发段错误,能正确返回false,也不会修改无效元素的票数,解决错误1和错误2。 print_winner函数逻辑更严谨,避免越界访问,同时确保正确找到所有最高票候选人。
内容的提问来源于stack exchange,提问作者King Brain
相关产品推荐
相关产品推荐

