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

C语言文件字符替换异常:双引号替换为成对符号失败

双引号替换逻辑的问题排查与修复

问题背景

需要将文本文件中的双引号按顺序替换:第1、3...个双引号替换为两个反引号(``),第2、4...个替换为两个单引号('')。原代码执行后未达到预期效果,具体输入输出如下:

输入文本(test.txt)

"some text here"
"read it"

实际输出

"some text here"
"read it"``````````````````````````````````````````````````

预期输出

``some text here''
``read it''

原代码核心问题

  1. 缓冲区长度计算错误:size_t chars = sizeof(buffer)/sizeof(buffer[0]); 取了缓冲区总大小(51)而非实际读取的numRead值,导致遍历大量未初始化的空字符。
  2. 插入字符逻辑混乱:遇到双引号时的while循环直接将指针移到缓冲区末尾,后续遍历逻辑完全失效,且未正确插入第二个替换符号。
  3. 文件写入逻辑错误:未将文件指针移到开头,导致处理后的内容追加到原文件末尾;且仅写入MAX_READ个字符,截断了部分处理结果。
  4. 缓冲区溢出风险:固定大小的缓冲区在插入字符时容易超出容量,引发内存越界。

修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

#define MAX_READ 50
int main(){
    int fd;
    fd = open("test.txt", O_RDWR);
    if (fd == -1){
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    char buffer[MAX_READ * 2 + 1]; // 预留足够空间,应对字符数量翻倍的情况
    ssize_t numRead;

    numRead = read(fd, buffer, MAX_READ);
    if (numRead == -1){
        perror("Failed to read file");
        exit(EXIT_FAILURE);
    }
    buffer[numRead] = '\0';

    char result[MAX_READ * 2 + 1]; // 单独存储处理后的结果,避免原缓冲区操作混乱
    int result_idx = 0;
    int quote_count = 1; // 记录双引号的序号,从1开始计数

    for(int i = 0; i < numRead; i++){
        if(buffer[i] == '"'){
            if(quote_count % 2 != 0){
                // 奇数序号双引号,替换为两个反引号
                result[result_idx++] = '`';
                result[result_idx++] = '`';
            }else{
                // 偶数序号双引号,替换为两个单引号
                result[result_idx++] = '\'';
                result[result_idx++] = '\'';
            }
            quote_count++;
        }else{
            // 非双引号字符直接复制到结果缓冲区
            result[result_idx++] = buffer[i];
        }
    }
    result[result_idx] = '\0'; // 确保字符串以终止符结尾

    // 将文件指针移到文件开头,准备覆盖原内容
    if(lseek(fd, 0, SEEK_SET) == -1){
        perror("Failed to seek file");
        exit(EXIT_FAILURE);
    }

    // 截断文件,避免原内容长度大于新内容时残留多余字符
    if(ftruncate(fd, result_idx) == -1){
        perror("Failed to truncate file");
        exit(EXIT_FAILURE);
    }

    ssize_t numWrite = write(fd, result, result_idx);
    if (numWrite == -1){
        perror("Failed to write file");
        exit(EXIT_FAILURE);
    } 

    close(fd); // 关闭文件,释放资源
    return 0;
}

关键修正说明

  • 独立结果缓冲区:用单独的缓冲区存储处理后的内容,避免在原缓冲区中插入字符导致的遍历逻辑混乱,代码更易维护。
  • 基于实际读取长度遍历:循环仅处理numRead个有效字符,跳过未初始化的缓冲区空间。
  • 直接写入替换符号:遇到双引号时直接写入两个目标符号,无需移动后续字符,逻辑简单且高效。
  • 文件指针重置与截断:通过lseek重置文件指针到开头,用ftruncate截断文件,确保原内容被完全覆盖,不会残留旧内容。
  • 预留足够空间:结果缓冲区大小设为原缓冲区的2倍+1,确保每个双引号替换为两个字符时不会溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 09:40:24