Чтение строки целых чисел при игнорировании неверных данных (c ++) - PullRequest
2 голосов
/ 31 марта 2012

Я читаю ввод, используя istringstreams для простого преобразования строки в целое число. У меня проблемы с чтением строки, когда она содержит ошибки, такие как «1 45 3 XXXX 45 X», где я хочу, чтобы она просто игнорировала буквы. Обычно без ошибок я бы просто сделал:

string s = "1 2 34 5 6";
istringstream stream(s);
int temp;

cout << s << " -> ";

while(stream >> temp){
    //do something with temp for ex:
    cout << temp << " ";
}

Это даст

 "1 2 34 5 6" -> 1 2 34 5 6

Очевидно, что это не работает, когда у меня есть строка вида "1 45 3 XXXX 45 X", так как она обрывается в XXXX и не продолжается. Но я хотел бы получить:

"1 45 3 XXXX 45 X" -> 1 45 3 45

Итак, я знаю проблему, но я застрял на том, как ее решить. У меня такое чувство, что должно быть очень простое решение, но я не могу понять, и большинство примеров, которые я искал в Интернете, не учитывают ошибки в данных или слишком сложны для моих нужд.

Ответы [ 5 ]

4 голосов
/ 01 апреля 2012

Если вы хотите обработать string и получить все, что похоже на int, то попробуйте следующий подход:

#include <iostream>
#include <string>
#include <sstream>


int main() {
    std::string s = "1 45 3 XXXX 45 X 11111111111111111111 2.3";
    std::istringstream stream(s);
    int foo;

    while(true) {
        if(stream >> foo) {
            std::cout << foo << std::endl; // do something with the int
        } else if (stream.eof()) {
            break; // We're done
        } else {
            // We've hit a non-int
            stream.clear(); // clear the error flags
            stream.ignore(); // ignore everything till the delimeter
        }
    }
}

Или, в качестве альтернативы, версию, использующую исключения:

int main() {
    std::string s = "1 45 3 XXXX 45 X 11111111111111111111 2.3";
    std::istringstream stream(s);
    stream.exceptions(std::ios::failbit | std::ios::badbit);
    int foo;

    while(!stream.eof()) {
        try {
            stream >> foo;
            std::cout << foo << std::endl;
        } catch (const std::ios::failure & e) {
            stream.clear();
            stream.ignore();
        }
    }
}

Вывод:

1
45
3
45
2
3
1 голос
/ 31 марта 2012

Удаление всего, что не является числом или пробелом из вашей строки перед ее анализом, решает вашу проблему. Вы рассматривали это?

Что-то подобное должно сделать это.

void filter(string * input) {
    for(int i = 0; i < input->length(); i++) {
        char val = input->at(i);
        if (val != ' ' && !isdigit(val)) {
            // not a valid character
            input->erase(i, 1);
            i--;
        }
    }
}
0 голосов
/ 01 апреля 2012

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

std::string s = "1 45 3 XXXX 45 X";
int temp[4] = {0}; 

cout << s << " -> "; 

sscanf(s.c_str(), "%d %d %d %*s %d", &temp[0], &temp[1], &temp[2], &temp[3]);

for(int i = 0; i < 4; ++i)
{ 
    cout << temp[i] << " "; 
} 
0 голосов
/ 31 марта 2012

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

char *cstr;
bool flag = true;

while(stream >> temp){
    i=0;
    flag = true;
    cstr = new char[temp.size()+1];
    strcpy (cstr, temp.c_str());
    while(cstr[i]) {
     if(!isdigit(cstr[i])) { 
       flag = false;
       break;
     }
    i++;
    }
    if(flag) 
    cout << temp << " ";
}

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

0 голосов
/ 31 марта 2012

Отфильтруйте алфавиты в строке перед передачей в istringstrem, как показано ниже

string s = "1 2 34 xxx 5 6"; 
string data;

for (unsigned int i = 0; i < sizeof(s); i++)
{
  if ((std::isdigit(s[i])) || (s[i] = ' '))
  data += s[i];
}
istringstream stream(data); 
cout << data << " -> ";  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...