C:单文件串替换程序

时间:2012-12-17 17:53:50

标签: c string file-io

为了不忘记C(在工作中我主要处理XSLT和其他语言不那么有趣),我不时会写一个小实用程序。

一个应用程序替换任何类型文件中的字符串而不生成第二个文件(是否有一个更好的短语来描述这个?)是我今天想到的。

我想出的是:

#include <stdio.h>
#include <string.h>

#define CHUNKLEN 256

void replcnks(char *str, char *cnk1, char *cnk2);

int main(int argc, char **argv)
{
    FILE *file;
    char *old, *new, *fname, buf[CHUNKLEN];
    long len;

    if(argc != 4)
    {
        puts("Invalid arguments\n");
        return 0;
    }

    old = argv[1];
    new = argv[2];
    fname = argv[3];

    file = fopen(fname, "rb+");

    do
    {
        len = fread(buf, 1, CHUNKLEN, file);
        replcnks(buf, old, new);
        fseek(file, -len, SEEK_CUR);
        fwrite(buf, 1, len, file);
        fseek(file, len, SEEK_CUR);
    }
    while(len == CHUNKLEN);

    fclose(file);

    return 0;
}

void replcnks(char *str, char *cnk1, char *cnk2)
{
    char *pos;
    int clen1 = strlen(cnk1), clen2 = strlen(cnk2);
    while((pos = strstr(str, cnk1)))
    {
        memmove(pos + clen2, pos + clen1, strlen(pos) - clen1 + 1);
        memcpy(pos, cnk2, clen2);
    }
}

该程序有效,但当替换字符串的大小与原始字符串不同时,会产生轻微错误。当它更长时,文件的结尾被剪切;当它更短时,输出在某些地方有一些垃圾值。我想问题出在fseek s。

之一

如何修复此计划?

解决方案可能很简单,但我想我今天没有脑力 - 但我想和平地睡觉:)。

2 个答案:

答案 0 :(得分:4)

你无法真正做到你想要做的事情,因为用一个不同大小的块替换一个文件块是没有好办法的。

如果被替换的字符串跨越块边界,它也会失败。

如果用较长的字符串替换短字符串,它可能会做很糟糕的事情,因为缓冲区中没有空间。

如果你真的想要这样做,你必须有一些缓冲方案,你可以单独跟踪读写,这样你就不会写你还没读过的字节。然后你仍然需要应对增长或截断文件......

答案 1 :(得分:1)

JasonD说的是 - 你试图用一个不同大小的文件来覆盖一些文件,文件系统无法神奇地缩小/扩展文件的中间以适应。我将源加载到RAM中,然后创建一个新文件,或者删除/重命名/备份源,然后用原始名称写出结果。