You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言基于文本文件实现持久化计数器的代码问题排查

代码问题诊断

你的代码存在几个核心错误,直接导致计数无法持久累加:

  • 首要错误是fopen打开模式选择错误:你使用的"w+"模式会在打开文件时直接将文件截断为0字节的空文件,无论之前文件里存储了什么计数内容,打开的瞬间就被清空了,后续你检查文件大小永远得到0,自然每次都只会写入初始值1,完全读不到历史数据。
  • 未给文件名分配合法的存储缓冲区:你直接对FILENAME执行sprintf写入,如果FILENAME是未初始化的指针、或者缓冲区长度不足,会触发内存溢出,轻则文件名乱码,重则程序直接崩溃。
  • 文件流读写切换不符合C标准规范:C语言规定对同一个文件流交替执行读、写操作时,必须插入fseek/rewind/fflush这类流定位/刷新操作,否则会出现写入位置错位、内容混乱的未定义行为。
  • 未校验读取操作的有效性:你直接使用fscanf的读取结果,但没有判断是否读取成功,如果文件为空、内容不是合法整数,Count会是未初始化的随机值,累加后的结果完全不可控。
  • 没有处理旧内容残留:如果你从文件头开始写入新值,但新值的长度比旧值短,旧值多出来的尾部字符会残留在文件中,下次读取会得到错误的数值。
修正实现

核心思路是调整文件打开逻辑:先以不破坏原内容的"r+"模式尝试打开已有文件,读取现有计数累加;如果文件不存在(打开失败),再新建文件写入初始值1。同时补全缓冲区定义、操作校验、残留清理逻辑。
可直接运行的修正代码:

#include <stdio.h>
// 类Unix系统使用ftruncate需要引入该头文件,Windows平台可替换为<io.h>并将ftruncate替换为_chsize
#include <unistd.h>

int main() {
    int Num;
    // 修正原代码的拼写问题,Entera补空格为Enter a
    printf("Enter a number:\t");
    scanf("%d", &Num);

    // 预分配128字节的文件名缓冲区,足够存储任意int范围数字拼接后的文件名
    char FILENAME[128];
    sprintf(FILENAME, "counter.%d.txt", Num);

    FILE *counter;
    int Count, NewCount;

    // 第一步:尝试打开已存在的计数文件,r+模式不会清空原内容
    counter = fopen(FILENAME, "r+");
    if (counter != NULL) {
        // 尝试读取文件中存储的合法整数
        int read_res = fscanf(counter, "%d", &Count);
        if (read_res == 1) {
            NewCount = Count + 1;
        } else {
            // 文件内容损坏/为空,重置为初始值
            NewCount = 1;
        }
        // 读切换为写前,定位回文件开头
        rewind(counter);
        fprintf(counter, "%d", NewCount);
        // 刷新流、截断文件到当前写入位置,清除旧内容残留
        fflush(counter);
        ftruncate(fileno(counter), ftell(counter));
        fclose(counter);
    } else {
        // 文件不存在,新建文件写入初始值1
        counter = fopen(FILENAME, "w");
        if (counter == NULL) {
            perror("Failed to create counter file");
            return 1;
        }
        fprintf(counter, "1");
        fclose(counter);
    }

    // 验证:读取最终存储的计数值打印
    counter = fopen(FILENAME, "r");
    if (counter != NULL) {
        fscanf(counter, "%d", &Count);
        printf("Current count: %d\n", Count);
        fclose(counter);
    }
    return 0;
}
关键注意点
  • 牢记C语言文件打开模式的核心差异:带w的模式打开时都会截断/新建空文件,适合创建新文件、覆盖写入场景;带r的模式要求文件必须存在,不会清空原内容,适合读、修改已有文件的场景;带+代表同时支持读写。
  • 所有文件IO操作都要校验返回值,不要默认操作一定成功,否则遇到权限不足、文件损坏、磁盘满等异常场景时程序会出现不可预期的错误。
  • 覆盖写入文件内容时,如果新内容长度和旧内容不一致,一定要在写入后截断文件,避免旧内容残留。

内容的提问来源于stack exchange,提问作者Huwee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:48:17