C ++: проверьте, чтобы в istream не было пробелов, символов без табуляции и символов новой строки, оставшихся без извлечения символов - PullRequest
0 голосов
/ 06 февраля 2011

Я читаю std :: istream, и мне нужно без извлечения символов проверить, что:

1) Поток не "пустой", то есть попытка прочитать символ не приведет к сбоюсостояние (решается с помощью функции-члена peek () и проверки состояния сбоя, затем возвращается в исходное состояние)

2) Что среди оставшихся символов есть хотя бы один, который не является пробелом, табуляцией илисимвол новой строки

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

Peek (int n), вероятно, сделает то, что мне нужно, но я застрял с его реализацией.Я знаю, что мог бы просто читать istream как:

while (myInt << myIstream) {...} //Will fail when I am at the end 

, но та же самая проверка потерпела бы неудачу для ряда различных условий (скажем, у меня есть что-то, что не является целым числом в некоторой строке) и я мог различитьдве ошибки чтения (неожиданная вещь, ничего не осталось) помогли бы мне написать более надежный код, как я мог написать:

while (something_left(myIstream)) {
  myInt << myIstream;
  if (myStream.fail()) {...} //Horrible things happened
}

Спасибо!

Ответы [ 4 ]

2 голосов
/ 06 февраля 2011

Существует функция ws, которая использует пробельные символы.Возможно, вы могли бы назвать это после каждого чтения.Если это достигнет цели, то вы знаете, что у вас нормальное завершение.Если этого не произойдет, и при следующем чтении не будет получен правильный int, то вы знаете, что в вашем файле есть мусор.Может быть что-то вроде:

#include <fstream>
#include <iostream>

int main()
{
    std::ifstream infile("test.dat");
    while (infile)
    {
        int i;
        infile >> i;
        if (!infile.fail())
            std::cout << i << '\n';
        else
            std::cout << "garbage\n";
        ws(infile);
    }
}
1 голос
/ 06 февраля 2011

это то, что я сделал, чтобы пропустить пробел / обнаружить EOF до фактического ввода:

char c;
if (!(cin >> c)) //skip whitespace
    return false;  // EOF or other error
cin.unget();

Это не зависит от того, какие данные вы собираетесь читать.

Этот код опирается на манипулятор skipws, устанавливаемый по умолчанию для стандартных потоков, но его можно установить вручную cin >> skipw >> c;

1 голос
/ 06 февраля 2011

А простой

for(;;){
  if(!(myIstream >> myInt)){
    if(myIstream.eof()) {
     //end of file
    }else{
     //not an integer
    }
  }

  // Do something with myInt
}

не работает?Почему вам нужно знать, остались ли числа?

Редактировать Изменено предложение Бена.

0 голосов
/ 06 февраля 2011

Обычный способ справиться с этой ситуацией - не избегать чтения из потока, а при необходимости вернуть символы, которые были прочитаны, при необходимости:

int get_int(std::istream& in)
{
    int n = 0;
    while(true) {
        if (in >> n)
            return n;
        clean_input(in);
    }
}

void clean_input(std::istream& in)
{
    if (in.fail()) {
        in.clear();

        // throw away (skip) pending characters in input 
        // which are non-digits
        char ch;
        while (in >> ch) {
            if (isdigit(ch)) {
                // stuff digit back into the stream
                in.unget();
                return;
            }
        }
    }
    error("No input");    // eof or bad
}
...