0

入力ファイルを解析しようとすると、奇妙な問題が発生します。このファイルには他のファイルを含めることができ、それらも解析する必要があるという考えです。次のように定義された関数でこれを再帰的に行っています。

int parse_inp(const char* filename)

メイン ファイルは問題なく解析されますが、再帰呼び出しはファイル ストリームを開くことができません。

int parse_inp(const char* filename)
{
    char buffer[BUFFER_MAX+1];
    char* token;
    std::string tok;
    int keywordSection;
    bool end_of_file;
    int cardNum;

    ...

    int i;
    std::string tempop;
    double tempd1, tempd2;
    SetSegmentCard2 tempSetSegmentCard2;
    int offset;

    printf("%s\n", filename);
    std::ifstream inp;
    inp.clear();
    inp.open(filename, std::ios::in);
    if(!inp.good() || !inp.is_open())
    {
        char path1[256];
        getcwd(path1,256);
        printf("CWD: %s\n", path1);
        fflush(NULL);
        printf("Unable to open '%s'\n", filename);
        return 0;
    }
    std::set<std::string> unrecognized;
    std::string line;
    while(inp.good() && !inp.eof())
    {
        getline(inp, line);
        strcpy(buffer, line.c_str());

        if (isComments(buffer)) //skip the comments line
            continue;

        if (buffer[0]=='*') //this is a keyword line
        {
            token = strtok(buffer," \n");
            keywordSection = is_inp_keyw(token);

            if (keywordSection==0)
                unrecognized.insert(token);
            cardNum = 0;
            continue;
        }

        //a data line
        tempop="";
        char* found = NULL;
        char path_buffer[100] = "Dyna3DWriter\\";
        int pos = 0;
        switch(keywordSection)
        {
            case 0: //not recognized
                //end of last keyword, not recognizable word
                break;
            case 1: //KEYWORD
                //"KEYWORD didn't do anything
                break;
            case 2: //TITLE
                break;
            case 3: //INCLUDE
                token = strtok(buffer, "\n");
                inp.clear();
                parse_inp(token);
                break;
            ...
        }
    }
    if(inp.is_open())
    {
        inp.close();
        inp.clear();
    }
}

再帰ファイルは解析されません。私は多くのことを調べましたが、ほとんどの問題は、失敗ビットが設定されていること (これがinp.clear()多くの呼び出しを行っている理由です)、または現在の作業ディレクトリについて間違った仮定を行っていることのいずれかであると思われました。

2 番目の理論をテストするために、以下を追加しました。

if(!inp.good() || !inp.is_open())
{
    char path1[256];
    getcwd(path1,256);
    printf("CWD: %s\n", path1);
    fflush(NULL);
    printf("Unable to open '%s'\n", filename);
    return 0;
}

また、作業ディレクトリとファイル名はどちらも正しいです。fopen(filename, "r")--- の呼び出しを使用すると、同じ動作が見られperror("fopen")ます。結果は次のようになります。

fopen: no such file or directory

EDIT:より多くのコードを記入

4

2 に答える 2

2

ファイル名に、この問題の原因となるゴミや不適切な文字が含まれていないことを確認してください。エラーがファイルが見つからない場合は、ファイル名が何らかの形で間違っていることを意味します。

の間違った宣言から来るのbufferでしょうか? コードには表示されません。

別の可能性はstrtok、ファイルを開く前に初期化で再度使用することです。strtokこのような再帰的なメソッドには、グローバル ストレージに基づくものを使用しないでください。strtok_r代わりに使用する必要があります。

于 2010-10-20T20:09:04.663 に答える
0

再帰関数が非常に深く呼び出された場合、開いているファイルの数に関する OS の制限を簡単にオーバーロードできます。

以前は、Gentoo Linux を 1 プロセスあたりのファイル数を 250 に制限して実行していましたが、それ以上の数が必要なプログラムは例外でした。

Windows には、システムで使用できるメモリの量と、システム全体で既に作成されているオブジェクトの数によって異なる制限があります。

これを行う賢い方法は、2 つの関数を用意することです。最初の関数は、他のすべての人が呼び出す関数で、ファイルを開くなどのセットアップを行います。2 番目の関数は再帰関数であり、std::ifstream オブジェクトへの参照のみを受け取ります。

編集:

私はあなたの質問を誤解しているようで、同じファイルを再帰的に開いているわけではありません。とにかく、上記の段落を残します。

于 2010-10-20T20:23:03.647 に答える