文件已有内容时fputs函数失效的问题排查求助
核心问题及修复
1. Save函数未初始化目标字符串导致崩溃
Save函数中的fullString是局部字符数组,默认未初始化,内存中为随机垃圾数据。strcat要求目标字符串必须以'\0'结尾才能正确拼接,空文件时可能巧合内存初始为0,但非空文件时垃圾数据中无'\0',strcat会越界访问内存,直接导致程序崩溃。
修复:初始化fullString为空字符串
void Save(struct SEED arrayToSave[], int size) { FILE* myFile = fopen("Catalogue.txt", "w"); char fullString[1000000] = {0}; // 初始化空字符串 for(int i = 0; i < size; i++) { struct SEED currentStruct = arrayToSave[i]; char stringToAdd[1000]; sprintf(stringToAdd, "%d %s %s %f %f\n", currentStruct.index, currentStruct.type, currentStruct.name, currentStruct.mass, currentStruct.price); strcat(fullString, stringToAdd); } printf("%s\n", fullString); fputs(fullString, myFile); fclose(myFile); }
2. GetText函数未添加字符串终止符
GetText从文件读取字符到text数组后,未手动添加'\0',导致strlen、strtok等字符串函数无法识别字符串结束位置,会读取数组外的垃圾数据,引发后续numberOfItems计算错误、字符串分割异常。
修复:读取完成后添加终止符,同时增加文件打开失败判断和数组越界防护
void GetText() { FILE* catalogueFile; char ch; int counter = 0; catalogueFile = fopen(path, "r"); if (!catalogueFile) return; // 处理文件打开失败情况 while((ch = fgetc(catalogueFile)) != EOF && counter < 999999) { // 防止数组越界 text[counter] = ch; counter++; } text[counter] = '\0'; // 添加字符串终止符 fclose(catalogueFile); }
3. GetArrayOfStructs内存分配错误
代码中malloc(numberOfItems * sizeof(arrayOfStructs))里的arrayOfStructs是指针,sizeof得到的是指针大小(通常4/8字节),而非struct SEED的实际大小,导致分配内存远小于需求,结构体数组越界写入破坏内存。
修复:改为按结构体大小分配
struct SEED* arrayOfStructs = malloc(numberOfItems * sizeof(struct SEED));
4. AddNew函数错误传参
GetArrayOfStructs是无参函数,但AddNew中调用时传了path参数,不符合函数定义,会引发未定义行为。
修复:去掉多余参数
struct SEED* oldArrayOfStructs = GetArrayOfStructs();
5. 输入缓冲区残留换行导致异常
UserInput中用getchar()读取选择后,缓冲区残留的换行符会被AddNew中第一个fgets读取,导致用户输入被跳过。
修复:清理输入缓冲区,同时简化AddNew中的fgets调用
void UserInput() { char choice; int choiceInt; printf("Add new item - print 1\n\n"); printf("Input your choice: "); choice = getchar(); // 清理缓冲区剩余字符 while (getchar() != '\n'); choiceInt = choice - '0'; printf("\n"); switch(choiceInt) { case 1: AddNew(); break; default: printf("Bye!\n"); break; } }
AddNew中保留一次fgets即可:
printf("Input type, name, mass and price\nof the new seed with spaces: "); fgets(tempChar, 200, stdin);
6. sscanf多余转义字符
AddNew中sscanf(tempChar, "%s %s %f %f\\n", ...)里的\\n是多余的,sscanf会自动跳过空白字符,反而可能导致匹配失败。
修复:去掉\\n
sscanf(tempChar, "%s %s %f %f", newType, newName, &newMass, &newPrice);
内容的提问来源于stack exchange,提问作者Maxymus 989

