Home > Blockchain >  A complex read text file
A complex read text file

Time:12-15

I have a text file, which emulates the input to my script. Example of the file:

4 15 30
....
....
....
....
1
1 2
3
1 2
2 1
2 2

The first line contains some constants, let's say n, a, and b. Next n rows contain some map nXn. Then there is a line with m - number of new coordinates and then m rows of these coordinates. I need to read these lines consequently and output some results. I found that I can read the file using

string myText;
ifstream MyReadFile("01");
while (getline (MyReadFile, myText)) {
    cout << myText << "\n";
}
MyReadFile.close();

but I don't understand how to implement a more complex reading of the input, as I need.

CodePudding user response:

Based on your description, your input problem seems to consist of 4 stages:

  1. read one line line which specifies n, a and b
  2. read n lines which represents the "map"
  3. read one line which specifies m
  4. read m lines which represents "new coordinates"

Although it is possible to solve the problem using only a single loop and using a variable to indicate in which stage the input currently is (which would have to be checked in every loop iteration), a simpler and more intuitive solution would be to simply write code for each individual stage one after another.

Since only stages 2 and 4 can consist of multiple lines, it makes sense to only use a loop for these two stages, and to only use a single call to std::getline for stages 1 and 3.

In your question, it seems unclear how the input in the file after stage 4 should be interpreted. My guess is that you want to want to jump back to stage 3 and continue processing input, until end-of-file is encountered.

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

void do_input()
{
    int n, a, b;
    int m;

    std::ifstream input_file( "input.txt" );
    std::string line;
    std::stringstream ss;


    //STAGE 1

    //attempt to read one line
    if ( !getline( input_file, line ) )
        throw std::runtime_error( "error reading from file" );

    //prepare stringstream object
    ss = std::stringstream( line );

    //attempt to read data
    ss >> n >> a >> b;
    if ( !ss )
        throw std::runtime_error( "error reading from file" );

    //display converted input
    std::cout << "STAGE 1: " <<
        "n = " << n << " " <<
        "a = " << a << " " <<
        "b = " << b << "\n" ;


    //STAGE 2

    // read n lines
    for ( int i = 0; i < n; i   )
    {
        if ( !getline( input_file, line ) )
            throw std::runtime_error( "error reading from file" );

        //display input line
        std::cout << "STAGE 2: Found map line: " << line << "\n";
    }

    //continue reading input, until end-of-file is encountered
    while ( true )
    {

        //STAGE 3

        //attempt to read one line
        if ( !getline( input_file, line ) )
            break;

        //prepare stringstream object
        ss = std::stringstream( line );

        //attempt to read data
        ss >> m;
        if ( !ss )
            break;

        //display converted input
        std::cout << "STAGE 3: " <<
            "m = " << m << "\n";


        //STAGE 4

        // read m lines
        for ( int i = 0; i < m; i   )
        {
            if ( !getline( input_file, line ) )
                throw std::runtime_error( "error reading from file" );

            //display input line
            std::cout << "STAGE 4: Found coordinates line: " << line << "\n";
        }
    }

    std::cout << "Could not read further input, stopping.\n";
}

int main()
{
    try
    {
        do_input();
    }
    catch ( std::runtime_error &err )
    {
        std::cout << "Runtime error occurred: " << err.what() << std::endl;
    }
}

With the sample input specified in the question, the program has the following output:

STAGE 1: n = 4 a = 15 b = 30
STAGE 2: Found map line: ....
STAGE 2: Found map line: ....
STAGE 2: Found map line: ....
STAGE 2: Found map line: ....
STAGE 3: m = 1
STAGE 4: Found coordinates line: 1 2
STAGE 3: m = 3
STAGE 4: Found coordinates line: 1 2
STAGE 4: Found coordinates line: 2 1
STAGE 4: Found coordinates line: 2 2
Could not read further input, stopping.

CodePudding user response:

I'm afraid there is no magic there, you might have two different options:

Either get the whole line as text and parse it (as you are doing right now with get line)

Or direcly fetch for the type as if it was a std::cin:

std::ifstream stream("fileName");
while(!stream.eof()){
   int x; 
   stream >> x; //Read the next int in your file. 
   // do something with it
} 
stream.close();

If you know before hand the structure of your file you can directly read those values using >> operator as shown before.

If your structure is undefined I'm afraid your only option is to parse it as string and then try to find what's the actual value either checking if it's a number or boolean or ...

  •  Tags:  
  • c
  • Related