C语言项目:emptyLineCounter函数在n()中触发段错误求助
段错误根源及修复方案
核心错误:scanf越界破坏指针
你的main函数中使用scanf("%s", &opt);读取用户输入,但opt是单个char类型变量,%s格式符会读取整行输入(包括结束符\0),而&opt仅指向1字节的内存空间,写入时会越界覆盖栈上的其他变量(比如v_val文件指针),导致传递给n()的指针变成无效野指针,触发段错误。
修复:将scanf改为读取单个字符,用scanf(" %c", &opt);(前面的空格用于跳过换行符等空白字符)。
次要问题:文件指针位置错误导致统计失效
在v()函数中,你先通过while(fgets(...))将文件指针读到了文件末尾,之后调用emptyLineCounter(dataloger)时,fgets直接返回NULL,无法统计任何内容,返回的emptyLineCount只是初始值1,并非正确结果。
修复:在调用emptyLineCounter前,调用rewind(dataloger);重置文件指针到开头。
其他潜在问题修复
- 避免无限循环:
checkFileStatus的循环添加重试次数限制,防止文件无法打开时程序卡死。 - 修正空行统计初始值:
emptyLineCounter的初始值从1改为0,确保统计结果准确。 - 调整无效代码位置:将
printf("\n");移到switch块末尾,保证每次操作后换行。 - 添加文件关闭逻辑:退出时关闭打开的文件,避免资源泄漏。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 void checkArrayStatus() { //check if dynamic arrays (dynamicke polia) are created } int checkFileStatus(FILE *file, const char *filename) { //checks if file is open or close if (file != NULL) { return 1; } else { printf("Neotvoreny subor %s\n", filename); return -1; } } int emptyLineCounter(FILE *file) { //empty lines counter; number of empty lines == number of meassurments done int emptyLineCount = 0; // 修正初始值为0 char line[MAXSIZE]; while (fgets(line, sizeof(line), file) != NULL) { int isEmpty = 1; //assume line empty for (int i = 0; line[i] != '\0'; i++) { if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n' && line[i] != '\r') { isEmpty = 0; // Line is not empty break; } } if (isEmpty) { emptyLineCount++; } } return emptyLineCount; } FILE* v() { //declare files as empty values FILE *dataloger = NULL; char *output[] = {"ID. mer. modulu:", "Pozícia modulu:", "Typ mer. veliciny:", "Hodnota:", "Cas merania:", "Datum merania:", ""}; // 添加重试次数限制,避免无限循环 int retry = 3; while (checkFileStatus(dataloger, "dataloger.txt") == -1 && retry-- > 0) { dataloger = fopen("dataloger.txt", "r"); } // 如果重试后还是打不开,直接退出 if (!dataloger) { exit(EXIT_FAILURE); } char line[MAXSIZE]; int pos = 0; while (fgets(line, sizeof(line), dataloger) != NULL) { if (pos == 7) { pos = 0; } printf("%s ", output[pos]); printf("%s", line); pos++; } rewind(dataloger); // 重置文件指针到开头,再统计空行 int measurement = emptyLineCounter(dataloger); printf("统计得到空行数:%d\n", measurement); // 可以打印验证 return dataloger; } int n(FILE **file) { if (!*file) { // 先检查指针是否有效,避免rewind空指针 printf("文件指针无效\n"); return -1; } rewind(*file); if (checkFileStatus(*file, "dataloger.txt") == -1) { printf("Checking ... Failing\n"); return -1; } printf("passed\n"); printf("HERE: %d\n", emptyLineCounter(*file));//length of array based on number of measurmenets /* int dim1 = 3; int dim2 = 6; // Number of "inner" arrays char ***dynamicArray = (char ***)malloc(dim1 * sizeof(char **)); //rework so that it accepts each line instead of input for (int i = 0; i < dim1; i++) { dynamicArray[i] = (char **)malloc(dim2 * sizeof(char *)); for (int j = 0; j < dim2; j++) { dynamicArray[i][j] = (char *)malloc(256 * sizeof(char)); // Assuming a maximum string length of 255 characters printf("Enter a string for element [%d][%d]: ", i, j); scanf("%s", dynamicArray[i][j]); } }*/ return 0; } void c() { printf("c\n"); } void s() { printf("s\n"); } void h() { printf("h\n"); } void z() { printf("z\n"); } int main() { //char to store user option char opt; FILE *v_val = NULL; //while true keep running -> end at option k while(1) { scanf(" %c", &opt); // 修正为读取单个字符,跳过空白 switch(opt){ //two cases to include capital/lowercase letters case 'v': case 'V': v_val = v(); //printf("%p", v_val); break; case 'n': case 'N': n(&v_val); break; case 'c': case 'C': c(); break; case 's': case 'S': s(); break; case 'h': case 'H': h(); break; case 'z': case 'Z': z(); break; case 'k': case 'K': printf("end\n"); if (v_val) { fclose(v_val); // 关闭文件,避免资源泄漏 } return 0; default: printf("Nesprávna možnosť\n"); //check for what the output should be break; } printf("\n"); // 移到这里,每次操作后换行 } return 0; }
内容的提问来源于stack exchange,提问作者Jakub
相关产品推荐
相关产品推荐

