Нужно проанализировать строку целых чисел и получить пробел

У меня есть файл, заполненный целыми числами (переменная сумма в строке), разделенными пробелом. Я хотел бы проанализировать int, затем пробел, затем int, затем пробел ... до символа новой строки, а затем начать с новой строки до eof. Пример файла будет выглядеть примерно так:

1 1 324 234 12 123 
2 2 312 403 234 234 123 125 23 34
...

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

std::ifstream inStream(file.txt);
std::string line;
int myInt = 0;
while(getline(inStream, line)) {
    std::stringstream ss(line);
    while(ss) {
        ss >> myInt;
        //process...
    }
}

Мой вопрос в том, есть ли простой способ получить пробел и конечный символ из ss? Или мне лучше всего написать мою программу, предполагающую пробел после каждого индекса и новую строку в конце ss? что-то вроде этого:

std::ifstream inStream(file.txt);
std::string line;
int myInt = 0;
while(getline(inStream, line)) {
    std::stringstream ss(line);
    while(ss) {
        ss >> myInt;
        // process...
        // done with myInt
        char mySpace = ' ';
        // now process mySpace
    }
    char myNewLine = '\n';
    // now process myNewLine
}

person zeus_masta_funk    schedule 20.03.2014    source источник
comment
Ожидаете ли вы, что пробел между числами будет отличаться от ' '?   -  person R Sahu    schedule 21.03.2014
comment
Между числами всегда будет один пробел. Вот почему я могу жестко запрограммировать его, если это необходимо, но если есть простой способ получить его из ss, я бы предпочел это.   -  person zeus_masta_funk    schedule 21.03.2014
comment
Если это всегда один ' ', то зачем вообще пытаться его извлечь? Притворяться. Пусть stringstream проглотит за вас пробелы и разрывы строк. Прочитайте 'int', и если он еще не в конце потока, то примите ' ', а затем, когда будет достигнут конец потока, примите '\n'.   -  person Remy Lebeau    schedule 21.03.2014
comment
Если вы действительно хотите получить дескриптор следующего символа, strtol будет хорошая функция для использования.   -  person R Sahu    schedule 21.03.2014


Ответы (2)


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

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

static void handle_number_string(std::string& literal) {
  if (!literal.empty()) {
    std::istringstream iss {literal};
    int value;
    if (iss >> value) {
      std::clog << "<" << value << ">";
    } else {
      // TODO: Handle malformed integer literal
    }
    literal.clear();
  }
}

int main(int argc, char** argv) {
  for (int i = 1; i < argc; i++) {
    std::string aux;
    std::ifstream istr {argv[i]};
    std::clog << argv[i] << ": ";
    while (istr.good()) {
      const int next = istr.get();
      switch (next) {
      case ' ':
        handle_number_string(aux);
        std::clog << "<SPC>";
        break;
      case '\n':
        handle_number_string(aux);
        std::clog << "<EOL>";
        break;
      default:
        aux.push_back(next);
      }
    }
    // Handle case that the last line was not terminated with '\n'.
    handle_number_string(aux);
    std::clog << std::endl;
  }
  return 0;
}

Дополнение: я бы сделал это только в случае крайней необходимости. Правильная обработка всех возможностей (несколько пробелов, неразрывные пробелы, табуляция, \r\n,…) потребует много работы. Если вы на самом деле хотите обрабатывать логические токены разделитель полей и конец строки, ручной анализ пробелов кажется неправильным путем. Было бы печально, если бы ваша программа вылетала только потому, что пользователь выровнял столбцы во входном файле (используя, таким образом, переменное количество пробелов).

person 5gon12eder    schedule 20.03.2014

Попробуйте что-то вроде этого:

std::ifstream inStream(file.txt);
std::string line;
int myInt;
while (std::getline(inStream, line))
{
    std::stringstream ss(line);
    ss >> myInt;
    if (ss)
    {
        do
        {
            // process...
            // done with myInt

            ss >> myInt;
            if (!ss) break;

            char mySpace = ' ';
            // now process mySpace
        }
        while (true);
    }

    char myNewLine = '\n';
    // now process myNewLine
}
person Remy Lebeau    schedule 20.03.2014