3

readNextString(ifstream &file , char* &pBuffer)私はファイルから次の文字列を抽出するという名前の関数を持っています','または'\n'到達するまで、文字列の最初と最後にある空白を削除し、残りを pBuffer に保存し、すべてが正常に機能した場合は true、そうでない場合は false を返します。ファイルの終わりに到達するまで、すべてが機能します。eofフラグが設定されていると、get ポインターを移動できません。私はこれを試しました:

if(file.eof())
{
   file.clear();
   file.seekg(0 , ios::end)
}

...そして、文字列の末尾にある空白を削除します。これはほとんど役に立ちました。関数はスペースなしで文字列を抽出しますが、無限ループが発生します。

私の実際の質問は次のとおりです。次の文字がEOFであるかどうかを確認するにはどうすればよいですか。できない場合は、これを行う別の方法はありますか?

これが私の実際の機能です:

bool readNextString(ifstream &file , char* &pBuffer)
{
    if(file.eof()){
        return false;
    }
    for(; file.good() && isWhitespace(file.peek()) && !file.eof() ; file.seekg(1 , ios::cur))
        ;
    if(file.eof()){
        cout << "The file is empty.\n";
        return false;
    }else{
        streamoff startPos = file.tellg();
        cout << "startPos : " << startPos << endl;
        for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
            ;
        streamoff A = file.tellg();
        cout << "A : " << A << endl;
        file.seekg(-1 , ios::cur);
        for(;file.good() && isWhitespace(file.peek()) ; file.seekg(-1 , ios::cur))
            ;
        file.seekg(2 , ios::cur);
        streamoff endPos = file.tellg();
        cout << "endPos : " << endPos << endl;
        pBuffer = new char[endPos-startPos];
        if(pBuffer)
        {
            file.seekg(startPos , ios::beg);
            file.get(pBuffer , endPos-startPos , ',' || '\n');
            for(;file.good() && file.peek()!='\n' && file.peek()!=',' && file.peek()!= EOF; file.seekg(1 , ios::cur))
                ;
            file.seekg(2 , ios::cur);
            streamoff temp = file.tellg();
            cout << "temp : " << temp << endl;
            return true;
        }else{
            cout << "Error! Not enough memory to complete the task.\nPlease close some applications and try again.\n";
            return false;
        }
    }
}

そして、それは私がそれを呼ぶ1つの場所です:

void printCities()
{
    ifstream city ;
    city.open("cities.txt", fstream::in);
    if(city.is_open())
    {
        char *currCity;
        int counter = 1;
        while(readNextString(city , currCity))
        {
            cout << counter++ << ". " << currCity << endl;
            delete[] currCity;
            currCity = NULL;
        }
        if(city.eof())
            cout << "There are no cities added.\n";
        city.close();
    }else
        cout << "Error by opening 'cities.txt'.Make sure that the file exist and try again.\n";
}

私が十分に明確だったことを願っています。他の間違いやエラーの可能性を見つけた場合は、喜んでそれを聞き、そこから学びます.

4

3 に答える 3

3

次の文字が EOF かどうかを確認するにはどうすればよいですか?

このような

if (file.peek() == EOF)
{
    // next char is EOF
    ...
}
于 2013-05-01T12:11:00.070 に答える
2

まず、シークを使用して空白をスキップしないでください。キャラクターを取得して、それで完了です。

次に、 と の意味を誤解しているよう istream::good()ですistream::eof()。 いつでも適切な場所はなく、 通常入力が失敗した後にのみ適切です。空白をスキップするループについては、通常の解決策は次のとおりです。istream::good()istream::eof()

while ( isspace( file.peek() ) && file.peek() != EOF ) {
    file.get();     //  ignore read character...
}

同様のコメントが他のループにも当てはまりますが、読み取り文字を無視したくない場合があります。次の までの文字を収集するには','、たとえば、次のようにします。

std::string field;
while ( file.peek() != ',' && file.peek() != EOF ) {
    field.push_back( file.get() );
}

(そして、file.get( pBuffer, endPos - startPos, ',' || '\n' ) あなたの期待どおりの結果は得られません。式',' || '\n'は常に に評価されtrue、これは に変換されると、charになり'\01ます。)

std::stream最後に、上記の戦略は機能しますが、より大きな単位のテキストを に入力し、それを解析する方がはるかに望ましいです。テキストが行指向の場合は、次のようなものを使用します。

std::string line;
while ( std::getline( file, line ) ) {
    //  Parse line, using std::istringstream if appropriate,
    //  although this doesn't seem to be the case for your code.
}

これは、あなたがしていることよりも桁違いに簡単です。

于 2013-05-01T14:18:29.670 に答える
0

わかりました。別の方法でやりました! WIN の getline() ! :Dだから、これは私のコードです(今回ははるかに読みやすいです):

bool readNextString(ifstream &file , char pBuffer[] )
{
    while(isWhitespace(file.peek()) && !file.eof())
        file.ignore(1);
    if(!file.eof())
    {
        streamoff start = file.tellg();
        stringstream toComma;
        if(file.getline(pBuffer , 200 , ','))
        {
            toComma << pBuffer;
            toComma.getline(pBuffer ,200, '\n');
            int i=strlen(pBuffer)-1;
            for(; isWhitespace(pBuffer[i]) ;i--)
                ;
            pBuffer[i+1] = '\0';
            file.clear();
            file.seekg(start + strlen(pBuffer) , file.beg);
            return true;
        }else return false;
    }
    return false;
}

私は他の機能にもいくつかの変更を加えました:

void printCities()
{
    ifstream city ;
    city.open("cities.txt", fstream::in);
    if(city.is_open())
    {
        if(!isEmpty(city))
        {
            char currCity[200];
            int counter = 1;
            while(readNextString(city , currCity) && counter < 10)
                cout << counter++ << ". " << currCity << endl;
        }else
            cout << "There are no cities added.\n";
        city.close();
    }else
        cout << "Error by opening 'cities.txt'.Make sure that the file exist and try again.\n";
}

この関数isEmpty(ifstream &file)は、ファイルが空の場合は true を返し、それ以外の場合は false を返します。

助けてくれてありがとう!よろしくお願いします !

于 2013-05-01T23:59:15.160 に答える