Geany中执行糖尿病数据计算C代码无输出问题求助
代码无输出的问题排查与修复
核心问题分析
你的代码运行无输出,主要由以下关键错误导致:
- 未初始化变量:
getData函数中的i和j未初始化,初始值为随机垃圾值,导致逻辑分支混乱,程序提前进入错误流程。 - 指针误用与内存越界:
nationalAverage是单个double类型指针,你却用nationalAverage[(int)atof(token)-2015]当作数组访问,直接触发内存访问错误,导致程序崩溃。 - 统计数组未初始化:
provincialAverages、yearlyAverages、ageGroupAverages等数组在main中未初始化,初始值为垃圾值,统计结果完全错误。 - CSV解析逻辑错误:处理年龄组时重复调用
strtok,导致数据读取错位;年份和数值的累加逻辑缺失计数,无法正确计算平均值。 - 全国平均值逻辑缺失:未对全国数据做累加和求平均的处理,直接输出初始垃圾值。
修复后的完整代码
// Include libraries #include <stdio.h> #include <stdlib.h> #include <string.h> // Function prototypes void getData(FILE* fp, double* provincialAverages, double* nationalSum, int* nationalCount, double* yearlyAverages, int yearlyCounts[4][7], double* ageGroupAverages, int ageGroupCounts[5][3]); void calculateAverages(double* provincialAverages, double nationalAverage, double* yearlyAverages, int yearlyCounts[4][7], double* ageGroupAverages, int ageGroupCounts[5][3]); int main(){ FILE *fp; // 初始化所有统计变量为0,避免垃圾值干扰 double provincialAverages[4] = {0.0}; double nationalSum = 0.0; int nationalCount = 0; double yearlyAverages[4][7] = {0.0}; // 4个省份 × 7年(2015-2021) int yearlyCounts[4][7] = {0}; // 年份数据计数 double ageGroupAverages[5][3] = {0.0};// 5个区域(4省+全国) × 3个年龄组 int ageGroupCounts[5][3] = {0}; // 年龄组数据计数 // 打开文件 fp = fopen("statscan_diabetes.csv", "r"); if (fp == NULL){ printf("Error opening file.\n"); return 1; } getData(fp, provincialAverages, &nationalSum, &nationalCount, (double*)yearlyAverages, yearlyCounts, (double*)ageGroupAverages, ageGroupCounts); calculateAverages(provincialAverages, nationalSum / nationalCount, (double*)yearlyAverages, yearlyCounts, (double*)ageGroupAverages, ageGroupCounts); fclose(fp); return 0; } // 读取CSV数据并统计累加值 void getData(FILE *fp, double *provincialAverages, double *nationalSum, int *nationalCount, double *yearlyAverages, int yearlyCounts[4][7], double *ageGroupAverages, int ageGroupCounts[5][3]){ char line[200]; char *token; double sum[4] = {0.0}; int count[4] = {0}; int i, j; // 跳过CSV表头行 fgets(line, sizeof(line), fp); while (fgets(line, sizeof(line), fp) != NULL){ token = strtok(line, ","); i = 0; j = -1; // 初始化区域索引为无效值 double value = 0.0; int yearIdx = -1; int ageIdx = -1; while (token != NULL){ // 跳过前4个无关字段 if (i < 4){ token = strtok(NULL, ","); i++; } // 识别区域/省份 else if (i == 4){ if (strcmp(token, "Ontario") == 0) j = 0; else if (strcmp(token, "Quebec") == 0) j = 1; else if (strcmp(token, "British Columbia") == 0) j = 2; else if (strcmp(token, "Alberta") == 0) j = 3; else if (strcmp(token, "Canada excluding territories") == 0) j = 4; token = strtok(NULL, ","); i++; } // 识别年份 else if (i == 5){ int year = atoi(token); if (year >= 2015 && year <= 2021) yearIdx = year - 2015; token = strtok(NULL, ","); i++; } // 识别年龄组 else if (i == 6){ if (strcmp(token, "35 to 49 years") == 0) ageIdx = 0; else if (strcmp(token, "50 to 64 years") == 0) ageIdx = 1; else if (strcmp(token, "65 years and over") == 0) ageIdx = 2; token = strtok(NULL, ","); i++; } // 获取数值 else if (i == 7){ value = atof(token); token = strtok(NULL, ","); i++; } } // 仅处理有效数据 if (j != -1 && value > 0 && yearIdx != -1 && ageIdx != -1){ // 省份数据统计 if (j < 4){ sum[j] += value; count[j]++; yearlyAverages[j*7 + yearIdx] += value; yearlyCounts[j][yearIdx]++; ageGroupAverages[j*3 + ageIdx] += value; ageGroupCounts[j][ageIdx]++; } // 全国数据统计 else if (j == 4){ *nationalSum += value; *nationalCount += 1; ageGroupAverages[j*3 + ageIdx] += value; ageGroupCounts[j][ageIdx]++; } } } // 计算省份平均值 for (int k = 0; k < 4; k++){ if (count[k] > 0) provincialAverages[k] = sum[k] / count[k]; } } // 计算并打印所有平均值 void calculateAverages(double *provincialAverages, double nationalAverage, double *yearlyAverages, int yearlyCounts[4][7], double *ageGroupAverages, int ageGroupCounts[5][3]){ // 打印省份平均值 printf("Provincial Averages:\n"); printf("Ontario: %.2f%%\n", provincialAverages[0]); printf("Quebec: %.2f%%\n", provincialAverages[1]); printf("British Columbia: %.2f%%\n", provincialAverages[2]); printf("Alberta: %.2f%%\n\n", provincialAverages[3]); // 打印全国平均值 printf("National Average: %.2f%%\n\n", nationalAverage); // 打印各省份年度平均值 printf("Yearly Averages:\n"); char *provinces[] = {"Ontario", "Quebec", "British Columbia", "Alberta"}; for (int p = 0; p < 4; p++){ printf("%s:\n", provinces[p]); for (int y = 0; y < 7; y++){ if (yearlyCounts[p][y] > 0){ printf(" %d: %.2f%%\n", 2015 + y, yearlyAverages[p*7 + y] / yearlyCounts[p][y]); } } } printf("\n"); // 打印各区域年龄组平均值 printf("Age Group Averages:\n"); char *ageGroups[] = {"35 to 49 years", "50 to 64 years", "65 years and over"}; char *regions[] = {"Ontario", "Quebec", "British Columbia", "Alberta", "Canada (excl. territories)"}; for (int r = 0; r < 5; r++){ printf("%s:\n", regions[r]); for (int a = 0; a < 3; a++){ if (ageGroupCounts[r][a] > 0){ printf(" %s: %.2f%%\n", ageGroups[a], ageGroupAverages[r*3 + a] / ageGroupCounts[r][a]); } } } printf("\n"); }
关键修复说明
- 变量初始化:所有统计数组、计数器都初始化为0,彻底避免垃圾值干扰。
- 修正内存访问错误:将
nationalAverage改为累加和+计数的方式,不再当作数组访问;调整年份、年龄组数组为二维结构,清晰划分统计维度,避免越界。 - 优化CSV解析:跳过表头行,分步骤读取每个字段,避免重复调用
strtok导致的数据错位;增加有效数据校验,只统计合法数值。 - 完善统计逻辑:为年份、年龄组统计增加计数变量,确保求平均时分母不为0;单独处理全国数据的累加与平均。
- 优化输出格式:区分不同区域的统计结果,仅输出有有效数据的平均值,避免无效输出。
内容的提问来源于stack exchange,提问作者Hassan 4443
相关产品推荐
相关产品推荐

