0

I'm trying to read a file line by line. My file is somewhat like this:

a 4 558 5

a 123 145 782

x 47 45 789

If the first character is a, i want to store the three values in front of it in an array. I'm trying this but it doesn't seem to work:

 while (std::getline(newfile, line))
    {
        if (line[0] == 'a')
        {
            vertex[0] = line[1];
            vertex[1] = line[2];
            vertex[2] = line[3];
            //vertices.push_back(vertex);
        }

2 Answers2

1

I'm trying this but it doesn't seem to work:

When you use

vertex[0] = line[1];

the 1-th character of line is assigned to vertex[0]. It's not your intent. You want to assign the first number after a in the line to vertex[0].

You can use std::istringstream to extract the numbers.

if (line[0] == 'a')
{
   // Make sure to ignore the the first character of the line when
   // constructing the istringstream object.

   std::istringstream str(&line[1]);
   str >> vertex[0] >> vertex[1] >> vertex[2];
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • @sweenish, the number of tools in the C++ standar library toolbox is rather large. I am still discovering useful things in the standard library. – R Sahu Oct 24 '19 at 19:21
0

This bit of code incorporates the advice and answers to this point.

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

int main()
{
    std::ifstream newfile("vals");
    if (!newfile)
        std::cout << "Exiting...\n";
    std::string line;
    int vertex[3][3];

    int i = 0;
    while(std::getline(newfile, line)) {
        if (line.empty()) continue;
        if (line[0] == 'a') {
            // Make sure to ignore the the first character of the line when
            // constructing the istringstream object.
            std::istringstream str(&line[1]);
            str >> vertex[i][0] >> vertex[i][1] >> vertex[i][2];
        }
        ++i;
    }
    newfile.close();

    for (int j = 0; j < 3; ++j) {
        for (int k = 0; k < 3; ++k) {
            std::cout << vertex[j][k] << ' ';
        }
        std::cout << '\n';
    }
}

The issue is that the variable line is a std::string, and using [n] on a string will get you the character and index n, and you're trying to get the nth word.

Another way to go about this (for the learning, the above code uses the preferred method) would be to manually extract the numbers yourself.

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

int main()
{
    std::ifstream newfile("vals");
    if (!newfile)
        std::cout << "Exiting...\n";
    std::string line;
    int vertex[3][3];

    int i = 0;
    while(std::getline(newfile, line)) {
        if (line.empty()) continue;
        if (line[0] == 'a') {
            line = line.substr(2);
            int j = 0;
            std::string::size_type loc;
            do {
                loc = line.find_first_of(" ");
                std::string tmp = line.substr(0, loc);
                vertex[i][j] = std::stoi(tmp);
                line = line.substr(loc + 1);
                ++j;
            } while(loc != std::string::npos);
        }
        ++i;
    }
    newfile.close();

    for (int j = 0; j < 3; ++j) {
        for (int k = 0; k < 3; ++k) {
            std::cout << vertex[j][k] << ' ';
        }
        std::cout << '\n';
    }
}

It should be pretty clear why the stringstream method is preferred. This method manually chops up line and manually converts the extracted number (still stored as a string) into an int for storing in the array. Meanwhile, the above method hides a lot of the dirty work from you, and does the work pretty darn efficiently as well. While I probably don't have to keep trimming the variable line in the second example (but I'd need another variable instead), my rebuttal is that I simply wouldn't have chosen this route in the first place.

sweenish
  • 4,793
  • 3
  • 12
  • 23