Возможен ли такой подход?преобразовать из строки в int? - PullRequest
2 голосов
/ 20 февраля 2011

Возможен ли такой поток? Я пытаюсь читать с ifstream и преобразовать его.

string things = "10 11 12 -10";
int i1;
int i2;
int i3;
int i4;
stringstream into;
into << things;
into >> i1;
into >> i2;
into >> i3;
into >> i4;

Я ожидаю, что это будет:

i1 = 10
i2 = 11
i3 = 12
i4 = -10

это правильно?

Может ли одна и та же переменная потока строк использоваться несколько раз?

Когда я пытался, первый раз был в порядке, но все остальное - просто 0.

Ответы [ 5 ]

6 голосов
/ 20 февраля 2011

Это определенно должно работать.Вы даже можете смешивать типы, как показано ниже:

string things = "10 Nawaz 87.87 A";
int i;
std::string s;
float f;
char c;

stringstream into;
into << things;
into >> i >> s >> f >> c; //all are different types!

cout << i <<"  "<< s <<"  "<< f <<"  "<< c;

Вывод:

10 Nawaz 87.87 A

Демо на ideone: http://www.ideone.com/eb0dR

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

То, что вы опубликовали, работает вместе с решением Джеремии Уилкока, используя вместо этого istringstream. Но рассмотрите возможность использования семейства функций scanf (всего для пары целых чисел это не имеет большого значения, но для более сложного ввода использование scanf может быть гораздо более кратким, чем возиться с потоковые манипуляторы):

string things = "10 11 12 -10";
int i1, i2, i3, i4, i5, i6;
sscanf(things.c_str(), "%d %d %d %d", &i1, &i2, &i3, &i4);

Причина, по которой ваш пример просто дает 0 после этого, заключается в том, что буфер stringstream пуст после того, как вы извлечете -10: вам нужно будет вставить больше в буфер, прежде чем вы сможете извлечь больше. Вы можете использовать один и тот же экземпляр stringstream несколько раз, но вам придется либо каждый раз полностью использовать буфер, либо понимать, что в буфере есть еще что-то, прежде чем следующий элемент вставляется в буфер:

* * 1010

Кроме того, ios (от которого наследуется stringstream) также определяет оператор ! и приведение к void*, чтобы вы могли удобно проверить, не удалось ли извлечь (технически проверяет, failbit или badbit установлен, и я считаю, что failbit - это тот, который устанавливается вместе с eofbit, когда в буфере недостаточно):

string things = "10 11 12 -10";
int i1, i2, i3, i4;
stringstream into;
into << things;
into >> i1 >> i2 >> i3 >> i4;
if (into >> i5) {
    cout << "extraction to i5 succeeded" << endl;
}
if (!(into >> i6)) {
    cout << "extraction to i6 failed" << endl;
}
1 голос
/ 20 февраля 2011

это работает? Я бы так и сделал:

istringstream into(things);
into >> i1;

и так далее. Это даст результат, который вы опубликовали.

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

Что касается вашего второго вопроса Может ли одна и та же переменная потока строк использоваться несколько раз? ,
вероятно clear и seek потока необходимы перед повторным использованием.
Например, следующий код будет служить вашим вторым вопросом:

int main() {
  string  s = "-1 2";
  stringstream  ss;
  ss << s;
  int i, j;
  ss >> i >> j;
  cout<< i <<' '<< j <<endl;
  ss.clear();
  ss.seekg( 0 );
  i = j = 0;
  ss >> i >> j;
  cout<< i <<' '<< j <<endl;
}

Надеюсь, это поможет.

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

Да, это будет работать.
Единственное, что я хотел бы сделать, это:

string things = "10 11 12 -10";
int i1;
int i2;
int i3;
int i4;

stringstream into(things);    // Initialize in the constructor
into >> i1 >> i2 >> i3 >> i4; // Chain the inputs.

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

stringstream into(things)
int val;
while(into >> val)                   // loop exits after 4 numbers as into.eof() 
{                                    // returns true after trying to read the 5 number.
    std::cout << "G(" << val << ")\n";
}

Например, мне нравится делать следующее при чтении нескольких строк с 4 числами:

std::string  line;
while(std::getline(std::cin, line))
{
    /*
     * This way if a line is formatted incorrectly (only 3 numbers)
     * The error is local to the line and we will pick it up in linestream
     * without affecting the scanning of subsequent lines
     */
    std::stringstream linestream(line);

    int i1,i2,i3,i4;
    linestream >> i1 >> i2 >> i3 >> i4;
}
...