C语言putw写入int到文件乱码、getw读取返回-1问题求解
贪吃蛇高分存储功能写入乱码、读取值变-1问题修复
问题相关代码
fp = fopen("rank.txt", "w"); if(fp == NULL){ clear(); refresh(); mvprintw(y/2,x/2-5,"File Error"); sleep(3); break; } else{ ch1 = getw(fp); if(score > ch1){ mvprintw(y/2-2,x/2-(strlen(title)/2),"%s", title); mvprintw(y/2,x/2-(strlen(rank)/2), "%s", rank); mvprintw(y/2+2, x/2, "%d", score); refresh(); sleep(5); putw(score,fp); fclose(fp); break; } else{ mvprintw(y/2-2,x/2-(strlen(title)/2),"%s", title); mvprintw(y/2,x/2-3,"SCORE:"); mvprintw(y/2+2, x/2, "%d", score); refresh(); fclose(fp); break; } } }
错误定位
代码一共有3个核心问题,直接对应你遇到的两个故障现象:
- 文件打开模式完全错误:你用
"w"模式打开文件,该模式是只写模式,打开瞬间会直接清空文件原有所有内容,且不支持读操作。你在打开后立刻调用getw()读历史高分,此时文件已经被清空,且在只写流上执行读操作属于未定义行为,根本读不到之前存储的有效分数。 - 读写函数使用错误:
getw()/putw()是二进制读写函数,直接把int类型的二进制字节流写入文件,不是写入人类可读的数字ASCII字符,所以你用文本编辑器打开rank.txt看到的自然是乱码。同时这两个函数在读失败、读到文件尾时会返回EOF(值为-1),你没有做任何读成功校验就直接使用返回值,这就是分数显示几秒后变成-1的直接原因。 - 逻辑顺序错误:文件打开后没有先判断读操作是否成功,直接拿无效的读结果和当前分数做比较,后续写入的位置也因为之前的非法读操作出现偏移,写入的内容根本不在文件正确位置。
修复方案
推荐用明文文本格式存储分数,方便调试排查,也不会出现乱码问题,修复逻辑如下:
- 先以只读模式
"r"打开rank.txt,读取历史最高分,读取完成后关闭文件;如果文件打开失败(首次运行游戏还没生成分数文件),就把历史最高分默认设为0。 - 再以只写模式
"w"打开文件,判断当前分数是否超过历史最高分:如果超过就把新的最高分写入文件,否则保留旧的最高分写入。 - 读写整数改用格式化IO函数
fscanf()/fprintf(),写入的内容是明文数字,直接打开txt文件就能看到正常数值。
修复后的参考代码:
int ch1 = 0; FILE *fp = fopen("rank.txt", "r"); // 先读取历史最高分 if (fp != NULL) { fscanf(fp, "%d", &ch1); fclose(fp); } // 重新打开文件写入最新最高分 fp = fopen("rank.txt", "w"); if(fp == NULL){ clear(); refresh(); mvprintw(y/2,x/2-5,"File Error"); sleep(3); break; } if(score > ch1){ mvprintw(y/2-2,x/2-(strlen(title)/2),"%s", title); mvprintw(y/2,x/2-(strlen(rank)/2), "%s", rank); mvprintw(y/2+2, x/2, "%d", score); refresh(); sleep(5); fprintf(fp, "%d", score); }else{ mvprintw(y/2-2,x/2-(strlen(title)/2),"%s", title); mvprintw(y/2,x/2-3,"SCORE:"); mvprintw(y/2+2, x/2, "%d", score); refresh(); fprintf(fp, "%d", ch1); } fclose(fp); break;
如果你确实需要用二进制模式存储分数,要把文件打开模式改为带
b的二进制模式(如"rb"、"wb"),同时替换getw/putw为移植性更好的fread/fwrite,注意跨平台运行时要处理字节序和int长度差异问题。
内容的提问来源于stack exchange,提问作者Suki Sebastian
相关产品推荐
相关产品推荐

