user3447513
user3447513

Reputation: 11

Need help inputting variables from a .txt file

This is my current code, everywhere I have looked online says that it should work.

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

using namespace std;

int main()
{
    string infile;
    string outfile;
    int batch1;
    int temp1;
    int press1;
    double dwell1;
    int batch2;

    cout<<"Enter Input File: "<<endl;
    cin>>infile;
    cout<<endl<<"Enter Output File: "<<endl;
    cin>>outfile;
    cout<<endl;

    string line;
    ifstream myfile (infile);

    if (myfile.is_open())
    {
        while ( getline (myfile,line) )
        {
            //cout << line << endl<<endl;
            myfile>>batch1>>temp1>>press1>>dwell1;
            // myfile>>batch2;
        }
        myfile.close();
        cout<<batch1<<" "<<temp1<<" "<<press1<<" "<<dwell1<<" "<<batch2;
    }
    else
        cout << "Unable to open input file";

    ofstream file;
    file.open (outfile);
    if (file.is_open())
    {
        file << "Writing this to a file.\n";
        file.close();
    }
    else
        cout<<"Unable to open output file"<<endl;

    return 0;
}

Right now it outputs 347 0 0 0 0 I cannot figure out why it starts on the second line and why the next few variables are zeros. The file I am reading from looks like this:

123 189 49 4.0

347 160 65 1.5

390 145 75 2.0

456 150 60 2.5

478 170 62 3.0

567 160 78 4.2

Thanks so much, I have been stuck here for a while now.

Upvotes: 1

Views: 76

Answers (2)

wonko realtime
wonko realtime

Reputation: 565

There are many approaches to parse line by line.

Approaching it using getline() leads to the urge to manually parse the resulting string, either by re-creating a stream object which then can be parsed using stream operators like >> or using sscanf or whatever else could do the job.

However, since you already have an input stream (myfile), reading a line into a string and recreating an input stream from it is not necessary.

Putting it in other words, replacing

while ( getline (myfile,line) )

which reads a line and checks the end condition at once with

while (!myfile.eof())

which only checks the end condition could already do the job since you're still reading line by line using

myfile>>batch1>>temp1>>press1>>dwell1;

just that each line is composed of/defined by 4 elements.

Here's a short example using a stringstream to replace the file input:

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

using namespace std;

int main()
{
    int batch1;
    int temp1;
    int press1;
    double dwell1;

    stringstream ss;
    ss << "123 189 49 4.0\n347 160 65 1.5\n390 145 75 2.0";

    while (!ss.eof())
    {
        ss >> batch1 >> temp1 >> press1 >> dwell1;
        cout << batch1 << "|" << temp1 << "|" << press1 << "|" << dwell1 << endl;
    }

    return 0;
}

Upvotes: 1

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

I cannot figure out why it starts on the second line and why the next few variables are zeros

The whole line is already read in from the getline() function. If you're reading further values directly from myfile, these will be consumed from the input stream additionally.

Put line into a std::istringstream and input your variables from that one:

while ( getline (myfile,line) )
{
    std::istringstream iss(line);
    //cout << line << endl<<endl;
    iss >>batch1>>temp1>>press1>>dwell1;
   // iss>>batch2;

    cout<<batch1<<" "<<temp1<<" "<<press1<<" "<<dwell1<<" "<<batch2;
}

UPDATE
To store multiple value sets (as per input line) create a small data structure

struct DataRecord {
    int batch1;
    int temp1;
    int press1;
    int dwell1;
    int batch2;
};

and keep all input (lines) in a std::vector<> of such:

std::vector<DataRecord> records;

while ( getline (myfile,line) )
{
    std::istringstream iss(line);
    DataRecord record;

    iss >> record.batch1 
        >> record.temp1 
        >> record.press1 
        >> record.dwell1 
        >> record.batch2;
    records.push_back(record);
}

for(std::vector<DataRecord>::iterator it = records.begin();
    it != records.end();
    ++it)
{
    cout << it->batch1 << " "
         << it->temp1  << " "
         << it->press1 << " "
         << it->dwell1 << " "
         << it->batch2 << std::endl;

}

Upvotes: 2

Related Questions