0

現在、ICU ディクショナリ ベースのブレーク イテレータに新たに追加したテストを行っています。テキストドキュメントで単語分割をテストできるコードがありますが、テキストドキュメントが大きすぎると、エラーが発生します: bash: ./a.out: Argument list too long

任意のサイズのファイルをコードで実行できるように、引数リストが長くなりすぎたときに引数リストを分割するようにコードを編集する方法がわかりません。元のコードの作者はとても忙しいのですが、誰か助けてくれませんか?

調査されているものの印刷を削除して、それが役立つかどうかを確認しようとしましたが、大きなファイルでエラーが発生します(調査されているものを印刷する必要はありません-結果が必要です)。

ソース テキスト ファイルを 1 行ずつ読み取り、結果を 1 行ずつ別のテキスト ファイルにエクスポートするようにコードを変更できれば (完了時にすべての行が含まれる)、完璧です。

コードは次のとおりです。

/*
Written by George Rhoten to test how word segmentation works.
Code inspired by the break ICU sample.

Here is an example to run this code under Cygwin.

PATH=$PATH:icu-test/source/lib ./a.exe "`cat input.txt`" > output.txt

Encode input.txt as UTF-8.
The output text is UTF-8.
*/

#include <stdio.h>
#include <unicode/brkiter.h>
#include <unicode/ucnv.h>

#define ZW_SPACE "\xE2\x80\x8B"

void printUnicodeString(const UnicodeString &s) {
    int32_t len = s.length() * U8_MAX_LENGTH + 1;
    char *charBuf = new char[len];
    len = s.extract(0, s.length(), charBuf, len, NULL);
    charBuf[len] = 0;
    printf("%s", charBuf);
    delete charBuf;
}

/* Creating and using text boundaries */
int main(int argc, char **argv)
{
    ucnv_setDefaultName("UTF-8");
    UnicodeString stringToExamine("Aaa bbb ccc. Ddd eee fff.");
    printf("Examining: ");
    if (argc > 1) {
        // Override the default charset.
        stringToExamine = UnicodeString(argv[1]);
        if (stringToExamine.charAt(0) == 0xFEFF) {
            // Remove the BOM
            stringToExamine = UnicodeString(stringToExamine, 1);
        }
    }
    printUnicodeString(stringToExamine);
    puts("");

    //print each sentence in forward and reverse order
    UErrorCode status = U_ZERO_ERROR;
    BreakIterator* boundary = BreakIterator::createWordInstance(NULL, status);
    if (U_FAILURE(status)) {
        printf("Failed to create sentence break iterator. status = %s", 
            u_errorName(status));
        exit(1);
    }

    printf("Result:    ");
    //print each word in order
    boundary->setText(stringToExamine);
    int32_t start = boundary->first();
    int32_t end = boundary->next();
    while (end != BreakIterator::DONE) {
        if (start != 0) {
            printf(ZW_SPACE);
        }
        printUnicodeString(UnicodeString(stringToExamine, start, end-start));
        start = end;
        end = boundary->next();
    }

    delete boundary;

    return 0;
}

本当にありがとう!-ネイサン

4

2 に答える 2

1

Argument list too longエラーメッセージはbashシェルから送信され、コードの実行が開始される前に発生します。

この問題を解決するために修正できる唯一のコードはbashソースコード(またはカーネル内にある可能性があります)であり、そうすると、常に制限にぶつかることになります。コマンドラインの2048ファイルから10,000ファイルに増やすと、いつか10,001ファイルを処理する必要があります;-)

「大きすぎる」引数リストを管理するためのソリューションは多数あります。

標準化されたソリューションはxargsユーティリティです。

 find / -print | xargs echo 

役に立たないが、実用的な例です。

詳細については、引数リストが長すぎる場合に「xargs」を適切に使用する方法を参照してください。

xargsでさえ問題があります。これは、ファイル名にスペース、改行文字、およびその他のわかりにくいものが含まれている可能性があるためです。

これがお役に立てば幸いです。

于 2011-06-19T13:55:26.363 に答える
0

以下のコードは、コマンドラインの最初のパラメーターとして指定された名前のファイルの内容を読み取り、str::buffer. UnicodeString次に、 で関数を呼び出す代わりに、代わりにargv[1]そのバッファを使用します。

#include<iostream>
#include<fstream>

using namespace std;

int main(int argc, char **argv)
{
    std::string buffer;

    if(argc > 1) {
        std::ifstream t;
        t.open(argv[1]);
        std::string line;
        while(t){
            std::getline(t, line);
            buffer += line + '\n';
        }
    }
    cout << buffer;
    return 0;
}

アップデート:

への入力は でUnicodeStringある必要がありますchar*。関数GetFileIntoCharPointerはそれを行います。以下では、最も基本的なエラー チェックのみが実装されていることに注意してください。

#include<iostream>
#include<fstream>

using namespace std;

char * GetFileIntoCharPointer(char *pFile, long &lRet)
{
    FILE * fp = fopen(pFile,"rb");
    if (fp == NULL) return 0;

    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    char *pData = new char[size + 1];
    lRet = fread(pData, sizeof(char), size, fp);

    fclose(fp);

    return pData;
}

int main(int argc, char **argv)
{
    long Len;
    char * Data = GetFileIntoCharPointer(argv[1], Len);
    std::cout << Data << std::endl;

    if (Data != NULL)
        delete [] Data;

    return 0;
}
于 2011-06-19T15:41:56.887 に答える