C语言读取无表头三列数据绘制柱状图遇重复及数值错误问题
问题分析与修复方案
嘿,我看了你这段代码,问题主要出在数据读取和柱状图绘制的逻辑上,咱们一步步捋清楚:
核心问题点
1. 不必要的循环导致柱子重复
你在处理每一行数据时加了一个for(int j=0;j<3;j++)循环,这会让同一行数据重复调用3次appendBar,自然就出现了重复的柱子。这完全没必要,因为每行就是一组3列数据,只需要处理一次就行。
2. strtok的误用与冗余代码
你先是用strtok按\n分割每行,但fgets已经把每行单独存在line[i]里了,这步操作完全多余。而且后面又用sscanf直接读取整行数据,前面的strtok和strncpy都是无效操作,还容易搞乱数据解析。
3. 文件关闭时机错误
你把fclose(fptr)放在了waitExit()之后,而waitExit()应该是阻塞等待用户退出的函数,这时候文件句柄一直没关闭,属于资源泄漏,应该把它移到读取完文件之后的位置。
修复后的完整代码
#include "visualiser.h" #include <stdio.h> #include <stdlib.h> #include<string.h> #include <unistd.h> #define LSIZ 128 #define RSIZ 10 void passFile(char *arr); int main(int argc, char **argv){ initInterface("silver","blue"); if(argc <2){ passFile("data-file.txt"); } else if(argc == 2){ // 改成else if,避免多分支判断的逻辑漏洞 passFile(argv[1]); } else { printf("Invalid arguments"); exit(0); } return 0; } void passFile(char *arr){ char line[RSIZ][LSIZ]; int i = 0; int tot = 0; FILE *fptr = NULL; fptr = fopen(arr, "r"); if(fptr == NULL){ // 增加文件打开失败的判断,避免空指针错误 perror("Failed to open file"); exit(1); } // 读取所有行到数组 while(fgets(line[i], LSIZ, fptr)){ // 安全去除换行符(兼容无换行符的行) size_t len = strlen(line[i]); if(len > 0 && line[i][len-1] == '\n'){ line[i][len-1] = '\0'; } i++; } tot = i; fclose(fptr); // 读取完文件就关闭,避免资源泄漏 printf("\n The content of the file %s are : \n",arr); for(i = 0; i < tot; ++i){ char name[18]; int arrivalTime; int serviceTime; // 直接用sscanf解析整行的3列数据 if(sscanf(line[i], "%17s %d %d", name, &arrivalTime, &serviceTime) == 3){ appendRow(name); // 传入第一列的名称 appendBar(i+1, serviceTime, "black", " ", 0); // 只调用一次,绘制对应柱子 printf("Row: %s, Arrival: %d, Service: %d\n", name, arrivalTime, serviceTime); // 可选:打印调试信息 } else { printf("Invalid line format: %s\n", line[i]); // 处理格式错误的行 } } printf("\n"); sleep(100); waitExit(); }
额外优化说明
- 增加了文件打开失败的判断,避免空指针访问导致崩溃;
- 改进了换行符的去除逻辑,避免行尾没有换行符时修改字符串的错误;
- 把
main里的分支改成else if,避免原代码中argc<2和argc==2都可能执行的逻辑漏洞; - 增加了格式错误行的处理,方便调试不符合3列格式的行。
这样修改后,每行数据只会被解析一次,正确读取第三列的serviceTime来绘制柱状图,柱子重复和数值错误的问题就解决了。
内容的提问来源于stack exchange,提问作者wak.igo
相关产品推荐
相关产品推荐

