2012-02-04 2 views
4

Мне интересно, что лучший способ написать от std::stringstream в vector<int>.Струнный поток к вектору <int>

Вот пример того, что в stringstream: "31 #00 532 53 803 33 534 23 37"

Вот что я получил:

int buffer = 0; 
vector<int> analogueReadings; 
stringstream output; 

while(output >> buffer) 
    analogueReadings.push_back(buffer); 

Однако то, что, кажется, происходит это, он читает первую вещь, то он получает #00 и возвращает 0, потому что это не номер.

В идеале, я хочу, он достигает #, а затем просто пропускает все символы до следующего пробела. Это возможно с флагами или чем-то еще?

Спасибо.

ответ

5
#include <iostream> 
#include <sstream> 
#include <vector> 

int main (int, char **) 
{ 
    std::istringstream reader("31 #00 532 53 803 33 534 23 37"); 
    std::vector<int> numbers; 
    do 
    { 
     // read as many numbers as possible. 
     for (int number; reader >> number;) { 
      numbers.push_back(number); 
     } 
     // consume and discard token from stream. 
     if (reader.fail()) 
     { 
      reader.clear(); 
      std::string token; 
      reader >> token; 
     } 
    } 
    while (!reader.eof()); 

    for (std::size_t i=0; i < numbers.size(); ++i) { 
     std::cout << numbers[i] << std::endl; 
    } 
} 
+0

Если вы не хотите сразу читать всю последовательность, вы можете удалить внешний цикл while-while. В этом случае вы можете читать серии чисел, разделенных нетонами. –

+0

Запустите код. Он печатает 31, 532, 53, 803, 33, 534, 23, 37. Вставляется 0. –

+0

Мерси Андре. Мне нравится ваш алгоритм.Я не знал об ошибках и прочее. Спасибо за ваше время. –

1

Вам нужно проверить, есть ли у вас номер или нет. использовать ответ здесь:

How to determine if a string is a number with C++?

#include <iostream> 
#include <sstream> 
#include <vector> 
using namespace std; 

bool is_number(const std::string& s){ 
    std::string::const_iterator it = s.begin(); 
    while (it != s.end() && std::isdigit(*it)) ++it; 
    return !s.empty() && it == s.end(); 
} 
int main() 
{ 
    vector<int> analogueReadings; 
    std::istringstream output("31 #00 532 04hello 099 53 803 33 534 23 37"); 

    std::string tmpbuff; 
    while(output >> tmpbuff){ 
     if (is_number(tmpbuff)){ 
     int num; 
     stringstream(tmpbuff)>>num; 
     analogueReadings.push_back(num); 
     } 
    } 
} 

результат 31 532 99 53 803 33 534 23 37

Кроме того, важные недостатки использования лексических слепки, как это описано здесь: How to parse a string to an int in C++?, где дана альтернатива tringstream(tmpbuff)>>num.

Например, 04hello становится 4 и 7.4e55 становится 7. Есть также ужасные проблемы с нижним и нижним потоком. Чистое решение Андре Карон преобразует

25 10000000000 77 0 0 

в

25 0 0 

на моей системе. Обратите внимание, что 77 тоже отсутствует!

+0

Параметр 'Выход >> buffer' выражение с' buffer' типа 'int' уже проверяет, чтобы увидеть, если его номер. Хитрость заключается в том, что тест состояния цикла OP неоднозначен: он не отличает конец потока от отказа чтения номера. –

+0

Кстати, это страшный алгоритм. В общем случае (токен - число) символы маркера обрабатываются 3 раза: один раз, чтобы прочитать токен в строке, один раз для выполнения теста «является числом» и один раз для разбора номера. –

+0

Я считаю, что если первый элемент в строковом потоке является NAN, тогда цикл while больше никогда не будет запущен. Я думаю, поэтому André Caron использовал цикл DO-WHILE. –

0

Нет петель Версия:

#include <iostream> 
#include <vector> 
#include <iterator> 
#include <algorithm> 
#include <sstream> 

using namespace std; 

class IntegerFiller 
{ 
    vector<int> &m_vec; 
public: 
    IntegerFiller(vector<int> &vec): m_vec(vec) {} 

    void operator()(const std::string &str) 
    { 
     stringstream ss(str); 
     int n; 
     ss >> n; 
     if (!ss.fail()) 
      m_vec.push_back(n); 
    } 
}; 

int main() 
{ 
    vector<int> numbers; 
    IntegerFiller filler(numbers); 
    for_each(istream_iterator<string>(cin), istream_iterator<string>(), filler); 
    copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, " ")); 
    return 0; 
} 
Смежные вопросы