3

I want to read in lines from a text file which have the following format:a r3, r2, r1 and i want to split this into individual pieces so i have a variable which holds a, r3, r2, and r1 individually, so i need to remove the whitespace and comma. Im not sure how to do this. I've searched around but could only find examples (like this) with pre-defined strings.

I know how to read in a text from a file and place it into a char array, but ideally i'd like to place each element of a line into a separate variable.

So something like:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

void main()
{
  string var1, var2, var3, var4;
  ifstream inFile("myfile.txt");

  if (inFile.is_open()){
      while (!inFile.eof()){
         inFile >> var1 >> var2 >> var3 >> var4;
      }
   }
}

but where it handles whitespaces, commas, and new lines. Any suggestions on how to do this?

Community
  • 1
  • 1
Noobgineer
  • 632
  • 2
  • 9
  • 20
  • 1
    First of all, [don't do this: `while (!inFile.eof())`](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – WhozCraig May 01 '16 at 22:34
  • `string.replace()?` comma by empty-ness. Or even better `string.erase()` the comma. `string.pop_back()` the last character? – Khalil Khalaf May 01 '16 at 22:48

3 Answers3

1

All the below ways work for your case:

You can use such routine for every string. Check if the last character is a comma. if yes, replace it with "empty-ness":

if (var1[var1.size() - 1] == ',')
    var1.replace(var1.size() - 1, var1.size() - 1, ""); // (From index, to index, with)

You can pop_back() the last character if it is a comma:

if (var2[var2.size() - 1] == ',')
    var2.pop_back();

Also, you can just erase the comma if it is the last character:

if (var3[var3.size() - 1] == ',')
    var3.erase(var3.size() - 1, var3.size() - 1); // (From index, to index)
Khalil Khalaf
  • 8,448
  • 7
  • 47
  • 92
  • Does this handle whitespaces? – Noobgineer May 02 '16 at 00:55
  • @noobgineer `inFile >> var1` ignores spaces by default – Khalil Khalaf May 02 '16 at 01:04
  • What if i have a different number of variables, so lets say one line only had 3 elements or another one has 5 elements, would I just declare the max number of variables i need and not worry about var5 not reading anything? – Noobgineer May 02 '16 at 01:12
  • You can do that and test it, else you would need a `vector` of strings where you push elements to it every time you read `while(inFile>>temp)`, or a linked list as to create a new node for every input. Maybe it is too much for if you are a beginner but you should learn that. – Khalil Khalaf May 02 '16 at 01:19
  • If i want to remove the first character from the variable, lets say var2, what would i need to do? So, the inputs will be r1, r2, etc.. for any numerical value and this could be up to 3 digits so r127. But i want to also strip the "r" and keep the number. – Noobgineer May 02 '16 at 01:29
1

You can read a line with std::getline(<stream>, <string>).

std::string line;
while(std::getline(inFile, line))
{
    // You successfully read a line.
}

There is actually a third parameter to std::getline() that specifies the end of line. By default this is '\n' but you you specify your on line end (which would be ',').

std::stringstream   lineStream(line);    // convert your line into a stream.

if (std::getline(lineStream, a, ',') &&
    std::getline(lineStream, r1, ',') &&
    std::getline(lineStream, r2, ',') &&
    std::getline(lineStream, r3, ',')
   )
{
    // Read all the values successfully
}

If you line is broken up by space the use operator>> rather than std::getline().

std::stringstream   lineStream(line);    // convert your line into a stream.

if (lineStream >> a >> r1 >> r2 >> r3)
{
    // Read all the values successfully
}
Martin York
  • 234,851
  • 74
  • 306
  • 532
  • Im not sure i follow what you mean with the on line end ','. If my line is a (space) ra, ra, rc there's no line end except for \n that would be read – Noobgineer May 02 '16 at 00:52
  • The third parameter to `std::getline()` is the character that it will stop reading at. By default it stops at `'\n'` but you can use any other character (like `','`). If your words a are space separated used `operator>>` – Martin York May 02 '16 at 02:32
  • my line is broken up with spaces and commas as shown in the question: a(space)r1,(space)r2,(space)r3\n – Noobgineer May 02 '16 at 03:43
0

Not the most elegant solution however something along these lines will work:

void parse_input(const std::string& _buffer, std::string& _s1, std::string& _s2,
 std::string& _s3, std::string& _s4);

int main(void) {   
    std::ifstream inFile("foo.txt");

    std::string var1, var2, var3, var4;
    std::string buffer = "";
    while(std::getline(inFile, buffer)) {
        parse_input(buffer, var1, var2, var3, var4);
    }
}

void parse_input(const std::string& _buffer, std::string& _s1, std::string& _s2,
 std::string& _s3, std::string& _s4) {
    size_t count = 0;
    // increment count until first space char
    while (buffer.at(count) != ' ') {
        ++count;
    }
    // set _s1 to substring of _buffer from start to first space
    _s1 = _buffer.substr(0, count);
    size_t prev_count = count;
    // repeat above for comma char instead...
    while (buffer.at(count) != ',') {
        ++count;
    }
    _s2 = _buffer.substr(prev_count, count);
    prev_count = count;
    while (buffer.at(count) != ',') {
        ++count;
    }
    _s3 = _buffer.substr(prev_count, count);
    prev_count = count;
    while (buffer.at(count) != ',') {
        ++count;
    }
    _s4 = _buffer.substr(prev_count, count);
}

Note that this doesn't prevent index out of bounds errors in the _buffer argument of parse_input - you would need to add additional checks in the while loops such as && count < _buffer.size().

sjrowlinson
  • 2,954
  • 1
  • 14
  • 31