I have a file filled with ints (variable amount on a line), delimited by a space. I would like to parse out the int, then space, then int, then space ... until the newline char then start at a new line until the eof. An example file would look something like this:

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

To grab the ints I can do something like this:

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

My question is that is there an easy way to also get the whitespace and endline char from the ss? Or is my best bet to write my program assuming a space after each index and a newline at the end of the ss? something like this:

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
}
有帮助吗?

解决方案

If performance is not the most important issue, the following would be a general-purpose tokenizer for your input format. Whether this is a feasible solution depends of course on what you actually want to do with the input.

#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;
}

Addendum: I'd only do this if I absolutely had to. Handling all possibilities (multiple spaces, non-breaking spaces, tabs, \r\n,…) correctly will be a lot of work. If what you actually want to handle are the logical tokens field separator and end of line, manually parsing whitespace seems to be the wrong way to go. It would be sad if your program crashes just because a user has justified the columns in the input file (thus using a variable number of spaces).

其他提示

Try something like this:

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
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top