2
votes

I want to write a program that reads lines of text from a file. Each line contains several strings, one integer and one double value. The number of lines is not known in advance (i.e., the program needs to read lines until end of file) and the length of each line is not known as well. The while loop checks if the line ordered in following manner:

 --  string -- integer -- double --- string  
Cat.     3:           18.00 Kr.       [ Tvål ]    
Cat.     1:           14.50 Kr.       [ Äppelmos Bob ]     
Cat.     1:           12.00 Kr.       [ Coca Cola 2 lit. ]     
Cat.     1:           18.00 Kr.       [ Kroppkakor 4 st. ] 

The problem is the last string contains several spaces, so the program does not take it as a one entire string. The last string is accepted like several strings and I see on my screen only Cat. 3: 18.00 Kr. instead of whole list of lines.

I tried to handle program like this:

double doubleValue;

int intValue;

string str1, str2, str3;

ifstream infile("Register.txt", ifstream::in);

while (infile >> str1 >> intValue >> str2 >> doubleValue >> str3)
{   
   cout << intValue << " " << doubleValue << endl;
}

Thanks in advance.

3
This is slightly off topic.. 4 kroppkakor for 18 kr is a pretty nice deal.Martin G
you should probably look in the direction of reading line by line and using regular expressions (std::regex) to get the data from it - solving things like 'one ore more spaces' is bascially what regex is maded forstijn
You're going to need more sophisticated line parsing. Try looking for the : and for the [ and ] characters. That will much more reliably delimit your input fields.Edward

3 Answers

2
votes

This is because operator>> will stop parsing at white spaces.

To work out, you can read the whole line first by using std::getline(). Then, parse the first four parts (by applying std::stringstream), and finally get the remaining part by calling std::getline() again.

#include <sstream>
using namespace std;

string line;
while (getline(infile, line)) // read the whole line from the file
{
    stringstream ss(line);
    ss >> str1 >> intValue >> str2 >> doubleValue; // pause the first four parts
    getline(ss, str3); // parse the remaining part to str3, e.g. "Kr. [ Tvål ]"
}
2
votes

you could always use fscanf, it will let you, as long as you know the format:

fscanf(f, "%s %d [ %[^\x5D]\x5D %lf", str1, &int1, str2, &double1);

I personally prefer scanf, here is a simple table:

fmt   meaning
%s    non-whitespace string
%d    integer
%u    unsigned integer
%ld   long
%lu   unsigned long
%f    float
%lf   double
%llf  long double

It also handles special formats as well, but that is beyond the scope of this. But its useful if you say have a file like this:

30.1 multi word string

you can read it by

scanf("%lf %[^\n]\n", &mydouble, strbuf);

Preference is key here, but I recommend you use fscanf for it

fscanf(FILE *f, char *fmt, ...);

http://www.manpagez.com/man/3/fscanf/

0
votes

It's working, thanks to herohuyongtao. This is a full code snippet that allows to read .txt file which contains strings, integers, doubles and print only integer and double values.
This is a part from a txt file.

Cat.     3:           14.50 Kr.       [ Äppelmos Bob ]     
Cat.     2:           12.00 Kr.       [ Coca Cola 2 lit. ]     
Cat.     5:           18.00 Kr.       [ Kroppkakor 4 st. ]

..........

..........

Solution is below.

    using namespace std;

        cout << "Category totals for last opening period: " << endl;

        double doubleValue;
        int intValue;
        string line, str, str2, str3;

        ifstream infile("Register.txt", ifstream::in);
        getline(infile, line);

        while (getline(infile, line))
        {   
            stringstream infile(line);
            infile >> str >> intValue >> str2 >> doubleValue;
            getline(infile, str3);
            cout << endl;

                cout << setw(3) << str << setw(1) << intValue << setw(7)                                                 << str2 << doubleValue << str3;
        cout << endl;

        }