Ad

Reading In Information From Test.txt In C++

- 1 answer

I'm trying to read in from a text file in C++ for a Testing Harness. The idea is that I have to read in the 5 values of dice and put it into an array, and then read in a string, run through the program, then read in 5 more values of dice and put those into an array, and then read in a string, and run the program, etc.

The text file looks like this:

1 1 2 1 1 Aces
2 2 4 5 6 Twos
3 3 3 2 2 FullHouse
1 2 3 4 4 SmallStraight
2 3 4 5 6 LargeStraight
6 6 6 6 6 Sixes

What would be the best way using ifstream to search the file for 1 1 2 1 1 and put those values into an array, and then read in "Aces" into a string, and then go to the next line and do the same with the values 2 2 4 5 6 and the string "Twos."

Ad

Answer

One possible and also C++-style and object oriented approach is, to put the data and operations on the data in a tiny claas.

So let's create a small struct containing an array with 5 integers and a std::string.

For that class, we additionally overwrite the 'inserter' and 'extractor' operator. Then we can use this class for input and output in the same way like for an integral data type.

The inserter operator is ultra simple an just puts the 5 integers and the text in an std:ostream. The exteractor operator is some lines more and basically works like this:

  • Read a complete line with std::getline
  • Put the read line in an std::istringstream. With that we can easily extract further data
  • Then we use the std::istream_iterator and copy exact 5 integers from the std::istringstream. And at the end, we read the text.

This is overall not so complicated.

Then, we can simply call in main the standard IO mechanisms.

Please see the example below:

#include <iostream>
#include <sstream>
#include <iterator>
#include <string>
#include <array>
#include <algorithm>

std::istringstream sourceFile{R"(1 1 2 1 1 Aces
2 2 4 5 6 Twos
3 3 3 2 2 FullHouse
1 2 3 4 4 SmallStraight
2 3 4 5 6 LargeStraight
6 6 6 6 6 Sixes)"
};


constexpr size_t MaxValues = 5U;

// Proxy class for reading one line of given format
struct PData {
    // The Array for the values
    std::array<int, MaxValues> values{};
    // The description
    std::string text{};

    // Overwrite extractor operator
    friend std::istream& operator >> (std::istream& is, PData& pdata) {
        // Read complete line
        std::string line{};
        if (std::getline(is, line)) {
            // Put line in istringstream
            std::istringstream iss(line);
            // Extract all integers
            std::copy_n(std::istream_iterator<int>(iss), MaxValues, pdata.values.begin());
            // Read the text
            iss >> pdata.text;
        }
        return is;
    }
    // Overwrite inserter operator
    friend std::ostream& operator << (std::ostream& os, const PData& pdata) {
        std::copy_n(pdata.values.begin(), 5, std::ostream_iterator<int>(os, "\n"));
        return os << pdata.text << "\n";
    }
};


int main() {

    PData p{};

    // Read lines and split them
    while (sourceFile >> p) {

        // Some debug output (Not necessary)
        std::cout << p << "\n\n";

        // Now do with p whatever you want

    }
    return 0;
}

Please note: Since I do have no files on SO, I use the std::istringstream as input file. You can of course use any other std::ifstream.

Ad
source: stackoverflow.com
Ad