0

Cを忘れないようにするために(仕事ではほとんどXSLTや他のあまり面白くない言語を扱わなければなりません)、時々小さなユーティリティプログラムを書くのが好きです。

2番目のファイルを生成せずに任意の種類のファイルの文字列を置き換えるアプリケーション(これを説明するより良いフレーズはありますか?)は、今日私の頭に浮かんだものです。

私が思いついたのは次のとおりです。

#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);
    }
}

プログラムは動作しますが、置換文字列のサイズが元の文字列と異なる場合、小さなエラーが発生します。長くなると、ファイルの末尾がカットされます。短い場合、出力にはいくつかの場所でいくつかのガベージ値があります。問題はの1つにあると思いますfseek

このプログラムを修正する方法は?

解決策はおそらく簡単ですが、今日は頭がおかしいと思いますが、安らかに眠りたいです:)。

4

2 に答える 2

4

ファイルのチャンクを別のサイズのチャンクに置き換える良い方法がないため、実行しようとしていることを実際に実行することはできません。

置き換えられる文字列がチャンクの境界を越えた場合も失敗します。

また、短い文字列を長い文字列に置き換えると、バッファにそのためのスペースがないため、おそらく非常に悪いことが起こります。

本当にこれを実行したい場合は、まだ読み取っていないバイトを書き込まないように、読み取りと書き込みを別々に追跡する、ある種のバッファリングスキームが必要になります。そして、ファイルの拡大や切り捨てに対処する必要があります...

于 2012-12-17T17:57:44.580 に答える
1

JasonDが言ったこと-あなたはファイルのビットを異なるサイズのファイルで上書きしようとしているのですが、ファイルシステムにはファイルの中央を魔法のように縮小/拡大する方法がありません。ソースをRAMにロードしてから、新しいファイルを作成するか、ソースを削除/名前変更/バックアップしてから、元の名前で結果を書き込みます。

于 2012-12-17T18:05:02.860 に答える