Почему istream :: getline () возвращает столько раз (ни с чем) - PullRequest
1 голос
/ 07 сентября 2011

Я пытаюсь прочитать плохо отформатированный текстовый файл, и, возможно, я поступаю об этом неправильно, но на основании документации по getline это звучало так, как будто бы он извлекал значения до тех пор, пока значения не станут значением разделителя (' ', в моем случае):

"Если разделитель найден, он извлекается и отбрасывается, т.е. не сохраняется, и следующая операция ввода начнется после нее. если ты не хотите, чтобы этот символ был извлечен, вы можете использовать член получить вместо этого. "

Но почему-то он много раз ничего не возвращает. Смотрите строки 604-607, все эти запятые в моем выводе являются возвращениями getline. Может ли кто-нибудь сказать мне, почему он возвращает пробелы 6 раз, прежде чем доходит до значения? Текстовый файл содержит только один пробел перед значением. Заранее спасибо. :)

Соответствующий скриншот: http://j.drhu.me/2011-09-07_1317.png

#include <iostream>
#include <fstream>
#include <string>
void CMuscleModel::LoadOpParams()
{
int i, j;

ifstream param("params.txt", ios::in);
        if (param.is_open())
        {
            stringstream iss, isn;
            string line, word;

            i=0; j=0;
            while (getline(param,line))
            {
                isn.clear();
                isn << line;
                if(i>27){
                    while (getline(isn,word,' ')) {
                        //LGma[i][j]=atof(word.c_str());
                        if(word == "SM"){
                            getline(param,line);
                            cout << line << endl << endl;

                            isn.clear(); isn << line;

                            getline(isn,word,' ');

                            int junk=0;
                            while (atof(word.c_str())==0){
                                junk++;
                                getline(isn,word,' ');
                            }

                            cout << atof(word.c_str()) << ", " << junk << endl;
                        }
                        if(word == "ST"){
                            cout << word << endl;
                        }
                        if(word == "BFL"){
                            cout << word << endl;
                        }
                        if(word == "BFS"){
                            cout << word << endl;
                        }
                        if(word == "MG"){
                            cout << word << endl;
                        }
                        if(word == "LG"){
                            cout << word << endl;
                        }
                        if(word == "RF"){
                            cout << word << endl;
                        }
                        if(word == "VM"){
                            cout << word << endl;
                        }
                        if(word == "VL"){
                            cout << word << endl;
                        }
                        if(word == "VI"){
                            cout << word << endl;
                        }
                        j++;
                    }
                }
                j=0; i++;
                isn.clear();
            }
        }
        param.close();
}

Ах, простите, что не включили код.

Ответы [ 3 ]

1 голос
/ 07 сентября 2011

Двунаправленный ввод / вывод с std::stringstream действительно неоднозначен.Я рекомендую вам использовать его немного по-другому.

ifstream param("params.txt", ios::in);
if (param.is_open())
{
    stringstream iss;
    string line, word;
    i=0; j=0;
    while (getline(param,line))
    {
        istringstream isn(line);
        // ...
    }
}

Это создает новый поток строк с чистым состоянием и каждый раз содержит содержимое строки, считываемой из файла.Если вы действительно хотите повторно использовать экземпляр для чтения токенов на нескольких строках, я рекомендую использовать синтаксис .str(line) вместо .clear() и operator<<.

Если вы хотите очистить пробел вВ начале каждой строки вы можете использовать std::ws манипулятор :

istringstream isn(line);
isn >> ws;
// ...
1 голос
/ 16 сентября 2011

Я думаю, что у выходного текстового файла, из которого я читал, были завершающие пробелы, и они просто помещались в поток, так что я был действительно смущен происходящим.Я просто использовал .str ("") в конце каждой строки, чтобы сбросить текущий поток, и все получилось чудесно.Спасибо за помощь, ребята.

1 голос
/ 07 сентября 2011

Если вы используете пробел в качестве разделителя в любое время, когда он встречается, getline вернет все, что было до разделителя.Если в файле было 5 пробелов подряд перед любыми другими символами, например, теперь вам нужно было бы вызывать getline 6 раз.

Возможно, вместо символа новой строки по умолчанию используется '\n'?

Редактировать: Не видел код раньше.Возможно, реструктурируйте свой код для чтения строк, а затем используйте find в сочетании с substr в каждой строке для поиска ваших ключевых слов?Был бы более простой код и меньше циклов.Нет смысла читать из файла только для вывода в поток строк, из которого вы затем читаете.

...