0

免責事項 これは宿題の質問です。私が書いているプログラムの完全な解決策を求めているのではなく、何が起こっているのかをよりよく理解するよう求めているだけです。前もって感謝します。

提供された関数は、次のようなファイルから読み取ります。

foo;bar
foo;bar

そして、次のようなファイルから読み取るように関数を変更したいと思います

foo;bar;foobar
foo;bar;foobar

提供される関数は次のようになります

void EntryList::loadfile(const char filefoo[])
{
    ifstream        in;
    char            foo[MAX_CHAR];
    char            bar[MAX_CHAR];
    AddressEntry    anEntry;    

    in.open (filefoo);
    if(!in)
    {
        in.clear();
        cerr << endl << "Fail to open " << filefoo << " for input!" << endl << endl;
        exit(1);
    }   

    in.get(foo, MAX_CHAR, ';');
    while (!in.eof())
    {
        in.get();                       //remove field seperator ';'            
        in.get(bar, MAX_CHAR, '\n');
        in.ignore(100, '\n');               //remove record seperator '\n'  

        anEntry.setfoo(foo);
        anEntry.setbar(bar);    

        addEntry(anEntry);  

        in.get(foo, MAX_CHAR, ';');             //start the next record
    }
    in.close();
}

私が変更した関数は次のようになります

void EntryList::loadfile(const char fileName[])
{
    ifstream        in;
    char            foo[MAX_CHAR];
    char            bar[MAX_CHAR];
    char            foobar[MAX_CHAR];
    TaskList        theEntry;   

    in.open(fileName);
    if (!in) {
        in.clear();
        cerr << endl
        << "Failed to open "
        << fileName
        << " for input!" << endl << endl;
        exit(1);
    }   

    in.get(foo, MAX_CHAR, ';');
    while (!in.eof())
    {
        in.get(); // rm ;
        in.get(bar, MAX_CHAR, ';');
        in.get(foobar, MAX_CHAR, '\n'); // rm '\n'
        in.ignore(100, '\n');   

        theEntry.setfoo(foo);
        theEntry.setbar(bar);
        theEntry.setfoobar(foobar); 

        addEntry(theEntry); 

        in.get(foo, MAX_CHAR, ';'); 

    }   

    in.close(); 

}

私はこのプログラムを少なくとも 4 回書き直しています。そして、私は(人間的に)私がこれにすべきだと思う方法でファイルを変更しました。私は過去にこのようにして問題を抱えていました。(まだプログラムの他の部分に取り組んでいるので、今はあまり具体的に言うことはできませんが、私の結果が予想外だったことは知っています)だから私の質問は、私がやろうとしていることに対して、私が修正した関数は正しいように見えますか?私は1つずれていますか?元の機能がどのように機能しているかを理解するのに苦労していると思います。(体系的に段階的に。)したがって、変更された関数についての私の混乱。

私はまた、あなたが見たいと思う他の関数、私のセッターとゲッターを提供することができます. また、ご質問やご意見がございましたら、よろしくお願いいたします。

4

1 に答える 1

1

元の関数も変更された関数も間違っています。何かを読み取ろうとしたは、入力が成功したかどうかを常に確認する必要があります(最終的に亡くなった場合、墓石にそれが刻まれると思います...)。一般に、入力ループを制御するために使用しても機能しません!in.eof()

行が文字数未満の文字列で終わる場合、MAX_CHAR次の行は無視されます。入力が改行文字で終わっているかどうかを確認し、そうでない場合は残りの文字を無視する必要があります。最後の入力が改行文字で終わる場合、文字を無視したくありません。また、行がたまたま 100 文字を超える文字列で終わっている場合も機能しません。std::istream::ignore()必要な数の文字を無視するための魔法の定数 forは、不都合なことにスペルstd::numeric_limits<std::streamsize>::max()され、ヘッダーで宣言されてい<limitsます >.

基本的に、ループは次のように開始する必要があります

while (in.getline(foo, MAX_CHAR, ';')
         .getline(bar, MAX_CHAR, ';')
         .get(foobar, MAX_CHAR, '\n')) {
    if (foobar[in.gcount() - 1] == '\n') {
        foobar[in.gcount() - 1] = '\0';
    }
    else {
        in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    // process the inputs
}

コードはstd::istream::getline()、最初の 2 つのコンポーネントを使用して、セパレートが格納されるのを回避します。セパレータが抽出され、入力が停止されれば十分です。std::istream::get()保存された最後の文字が改行であったかどうかを確認する必要があるため、最後のコンポーネントが使用されます。std::istream::gcount()最後に格納された文字は、最後にフォーマットされていない入力関数によって格納された文字数を含むaccess usingです。入力は成功し、改行の格納時またはMAX_CHAR文字の格納後に停止するため、in.gcount() - 1常に有効なインデックスです。ただし、コードはテストされていないことに注意してください...

于 2013-11-09T20:18:02.813 に答える