0

行自体ではなく、ファイル内の行の順序をどのように尊重できますか。ファイルが巨大になる可能性があります。

ラインの長さについて仮定を立てる必要はありません。

入力:

this is line1
this is line2
this is line3

出力例:

this is line3
this is line2
this is line1

スタックデータ構造のように、別のファイルをバッファとして使用することを考えましたが、実際にはどこにも行けませんでした。

これについて何か考えはありますか?

4

3 に答える 3

3

両端から始まるファイルの大きなブロックを読み取ります。これらのブロック内で、最初の行を最後の行と交換し、両方のポインターを移動して、現在の場所を追跡します。各ブロックを記入しながら書き出します。2 つのポインターが中央で一致したら、完了です。

その場でブロックを変更しようとしないでください。物事がより複雑になります。最初の読み取りブロック、最初の書き込みブロック、最後の読み取りブロック、最後の書き込みブロックの 4 つのブロックを使用します。各書き込みブロックが完了すると、それを書き出します。各読み取りブロックが使い果たされると、別のブロックを読み取ります。まだ読んでいないものを上書きしないように注意してください!

それはかなり簡単で、退屈なだけです。最適化する必要がない場合は、ブロックを逆方向に読み取り、新しいファイルを書き出してから、既存のファイルの上に移動することができます。

于 2013-10-21T21:20:58.380 に答える
1

ファイルがメモリに収まらない場合は、2 パス プロセスになります。最初のパスでは、ファイルのチャンク (メモリに収まる行数) を読み取り、それらを一時ファイルに逆の順序で書き込みます。だからあなたは持っています:

while not end of input
    read chunk of file into array of lines
    write lines from array to temporary file, in reverse order
end while

最初のパスが完了すると、temp1.txt、temp2.​​txt、temp3.txt ... tempN.txt という一連の一時ファイルが作成されます。

最後のファイル (tempN.txt) を追加用に開き、逆の順序でファイルの追加を開始します。だからあなたは持っています:

open fileN for append
fileno = N-1
while fileno > 0
    append file_fileno to fileN
    fileno--
end while

次に、tempN.txt の名前を変更し、他の一時ファイルを削除します。

ちなみに、手順 2 にはオペレーティング システムが提供する連結ユーティリティを使用できます。たとえば、Windows では、手順 2 を次のように置き換えることができます。

copy /A file4.txt+file3.txt+file2.txt+file1.txt mynewfile.txt

他のプラットフォームにも同様のユーティリティがあります。

ただし、コマンド ラインの長さの制限に遭遇する可能性があります。

于 2013-10-21T22:18:30.923 に答える
0

2 つの簡単な手順で実行できます。

ステップ 1: すべてのファイルを逆にする

ステップ 2: 各行を反転

step:0   1       2
---------------------
abc      zyx     xyz
1234 =>  4321 => 1234 
xyz      cba     abc

編集:ここに完全な解決策があります:

#include <iostream>
#include <fstream>
#include <algorithm>
#define BUFFSIZE 4098 /*make sure this is larger then the longest line...*/
using namespace std;

bool reverse_file(const char* input, const char* output)
{
    streamsize count=0;
    streamoff size=0,pos;
    char buff[BUFFSIZE];

    ifstream fin(input);
    ofstream fout(output);

    if(fin.fail() || fout.fail()){
        return false;
    }

    fin.seekg(0, ios::end);
    size = fin.tellg();
    fin.seekg(0);
    while(!fin.eof()){  
        fin.read(buff, BUFFSIZE);
        count = fin.gcount();
        reverse(buff,buff+count);
        pos = fin.tellg();
        if(pos<0) {
            pos = size;
        }
        fout.seekp(size - pos);
        fout.write(buff,count);
    }
    return true;
}

bool reverse_file_lines(const char* input, const char* output)
{
    streamsize count=0;

    char buff[BUFFSIZE];

    ifstream fin(input);
    ofstream fout(output);

    if(fin.fail() || fout.fail()){
        return false;
    }

    while(!fin.eof()){  
        fin.getline(buff, BUFFSIZE);
    /*if BUFFSIZE is smallest then line size gcount will return 0, 
        but I didn't handle it...*/
        count = fin.gcount();
        if(buff[count-1]==0)count--;
        reverse(buff,buff+count);
        fout.write(buff,count);
        if(!fin.eof()){
            fout<<endl;
        }
    }
    return true;
}


int main()
{
    reverse_file("test.in", "test.tmp");
    reverse_file_lines("test.tmp","test.out");
    return 0;
}
于 2013-10-22T15:41:23.457 に答える