程序崩溃问题排查:疑与sort函数中第二个for循环相关
程序崩溃问题排查与修复方案
兄弟,我一眼就揪出了导致你程序崩溃的核心问题,还有几个细节也得调整下,咱们一步步来解决:
核心崩溃原因:格式符类型不匹配
你在sort函数的第二个printf语句里犯了一个低级但致命的错误:
printf("Total Homework Score: %d\nTotal Exam Score: %d\nClass Percentage: %f Grade: %s", s[i].totalhw, s[i].totalex, s[i].classperc, s[i].grade);
这里的%s是用来打印**字符串(char数组)**的格式符,但s[i].grade是单个char类型变量!用%s会让程序从grade的内存地址开始,一直读取数据直到遇到\0,直接触发非法内存访问,导致程序崩溃。
把%s改成%c就能解决这个崩溃问题:
printf("Total Homework Score: %d\nTotal Exam Score: %d\nClass Percentage: %f Grade: %c", s[i].totalhw, s[i].totalex, s[i].classperc, s[i].grade);
次要问题:排序循环的硬编码值
你的sort函数里的排序循环用了固定的SIZE而不是传入的参数n:
for (int i = 0; i < SIZE - 1; i++) { for (int j = i + 1; j< SIZE; j++) {
虽然当前main函数里传入的n等于SIZE,但如果后续你修改了数组大小或者传入不同的n,这会导致数组越界问题。改成用参数n来控制循环范围更健壮:
for (int i = 0; i < n - 1; i++) { for (int j = i + 1; j < n; j++) {
额外优化:符合C标准的main函数
C标准规定main函数的返回类型应该是int,而不是void。虽然有些编译器允许void main(),但改成标准写法更规范:
int main() { // 现有代码... system("PAUSE"); return 0; }
修复后的完整代码
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE 5 struct student { char name[20]; int hw1, hw2, hw3, ex1, ex2, totalhw, totalex; float classperc; char grade; }; void student_info(struct student s[], int n, int *classex1, int *classex2, int *a, int *b, int *c, int *d, int *f) { for (int i = 0; i < n; i++) { printf("\n\nPlease enter the student's name:\n"); gets_s(s[i].name, 20); printf("\nPlease enter the student's homework grades:\n"); scanf("%d %d %d", &(s[i].hw1), &(s[i].hw2), &(s[i].hw3)); printf("\nPlease enter the student's exam scores:\n"); scanf("%d %d", &(s[i].ex1), &(s[i].ex2)); getchar(); s[i].totalhw = s[i].hw1 + s[i].hw2 + s[i].hw3; s[i].totalex = s[i].ex1 + s[i].ex2; *classex1 += s[i].ex1; *classex2 += s[i].ex2; s[i].classperc = ((float)s[i].totalhw / 1.875) + ((float)s[i].totalex / 3.333); if (s[i].classperc >= 90) { *a = *a + 1; s[i].grade = 'A'; } else if (s[i].classperc >= 80) { *b = *b + 1; s[i].grade = 'B'; } else if (s[i].classperc >= 70) { *c = *c + 1; s[i].grade = 'C'; } else if (s[i].classperc >= 60) { *d = *d + 1; s[i].grade = 'D'; } else { *f = *f + 1; s[i].grade = 'F'; } } } void sort(struct student s[], int n) { struct student temp; // 修改:用n代替SIZE控制循环范围 for (int i = 0; i < n - 1; i++) { for (int j = i + 1; j < n; j++) { if (strcmp(s[i].name, s[j].name) > 0) { temp = s[i]; s[i] = s[j]; s[j] = temp; } } } for (int i = 0; i < n; i++) { printf("\nStudent: %s\nThe Three Homework Scores: %d %d %d\nThe Two Exam Scores: %d %d\n", s[i].name, s[i].hw1, s[i].hw2, s[i].hw3, s[i].ex1, s[i].ex2); // 修改:把%s改成%c打印char类型的grade printf("Total Homework Score: %d\nTotal Exam Score: %d\nClass Percentage: %f Grade: %c", s[i].totalhw, s[i].totalex, s[i].classperc, s[i].grade); } } void avg_exams(int classex1, int classex2, float *avgex1, float *avgex2) { *avgex1 = classex1 / (float)5; *avgex2 = classex2 / (float)5; } void print_classinfo(float avgex1, float avgex2, int a, int b, int c, int d, int f) { printf("\n\nThe Average Exam Score for Exam 1 is: %0.2f\nThe Average Exam Score for Exam 2 is: %0.2f\n", avgex1, avgex2); printf("There were %d A's, %d B's, %d C's, %d D's, %d F's in the class overall\n\n", a, b, c, d, f); } // 修改:改成标准的int main() int main() { struct student s[SIZE]; int a, b, c, d, f , classex1, classex2; a = b = c = d = f = 0; classex1 = classex2 = 0; float classperc, avgex1, avgex2; student_info( s, SIZE, &classex1, &classex2, &a, &b, &c, &d, &f); sort(s, SIZE); avg_exams(classex1, classex2, &avgex1, &avgex2); print_classinfo(avgex1, avgex2, a, b, c, d, f); system("PAUSE"); return 0; }
把这些修改做完后,你的程序应该就能正常运行,不会再崩溃了!
内容的提问来源于stack exchange,提问作者Lado Dolidze
相关产品推荐
相关产品推荐

