Extracting one type of data from a file

Hello!
I'm studying C++ and am currently learning how to get information to and from files with my program. I've learned how to do it with one type of data at a time from my professor and the book we're using, like if there's a file with only char's in it.
The assignment though is to create a file with both char's and int's in it, like so:

My Name
10

Your Name
35

etc.

I've found some code online made by others that can take the char's and save it in one variable, then the int's and save it in another.
Problem is that not only did I not 100% understand what I was reading so I didn't just wanna copy-paste it, but I also have no need for the char's in my program - I just need the int's for some calculations.
And this is where I'm stuck; what on earth do I use to extract just the int's from the file?
So far I've been looking at links about c_str and getline.ignore() and such, though I have no real idea how I would apply them or how it would actually work even if I did.

I do realize I could just go ahead and get all of it, then try to sort the int's in to a vector and use that and leave the char's where they are, never to be used, since my program is very small and won't take up a lot of space either way.
I do however plan to work as a programmer in the future, so knowing how to do it "right" or more efficiently from the beginning would be nice.

Thank you in advance!
Last edited on
Tomoecchi wrote:
what on earth do I use to extract just the int's from the file?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

istringstream fileData( "My Name\n"
                        "10\n"
                        "\n"
                        "Your Name\n"
                        "35\n" );
                        
int main()
{
   int data;
   string dummy;
   while ( getline( fileData >> ws, dummy ) && fileData >> data ) cout << data << '\n';
}


10
35




If you want to store your data then you can do
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

istringstream fileData( "My Name\n"
                        "10\n"
                        "\n"
                        "Your Name\n"
                        "35\n" );
                        
int main()
{
   vector<int> stuff;
   string dummy;
   for ( int data; getline( fileData >> ws, dummy ) && fileData >> data; ) stuff.push_back( data );
   
   cout << "Data: ";
   for ( int e : stuff ) cout << e << ' ';
}


Data: 10 35 




Tomoecchi wrote:
so knowing how to do it "right" ... from the beginning would be nice

Better ignore me then!
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct My_Struct
{
    std::string name;
    int integer;
};

std::ostream & operator<<( std::ostream & ostr, const My_Struct & my_struct )
{
    ostr << my_struct.name << '\n' << my_struct.integer;
    return ostr;
}

std::istream & operator>>( std::istream & istr, My_Struct & my_struct )
{
    istr >> my_struct.name >> my_struct.integer;
    return istr;
}


1
2
3
4
for( const My_Struct & my_struct : my_container )
{
    my_file << my_struct;
}


Extracting only the the ints:
1
2
3
4
while( my_file.getline( tmp, std::numeric_limits<std::size_t>::max()) && my_file >> my_int )
{
    my_vector.push_back( my_int );
}


I suggest, reading a good, actual C++ book for beginners.
Last edited on
Hello Tomoecchi,

My first question is what have you tried? and why did you not post that code that code?

I can not help you through what is wrong if I do not know what it is or what you have done.

The above answers are good and you might understand them in a few months or we can work with what you know.

Andy
Hi Andy!

I basically tried a mashup of different things I found on Google, but they were all above my current level and went straight over my head so I kinda counted it as not having any actual code of my own...
Next time I will post it anyway though, even if it doesn't make much sense!

I did manage to figure it out with the help of lastchance's reply and the program is now running as intended!
My biggest issue right now that keeps me from turning it in to my teacher is that I don't understand the behind the scenes so to speak behind this part:

for ( int data; getline( fileData >> ws, dummy ) && fileData >> data; )

This is the part that I ended up using, but I don't get how it actually works.
Why won't it work, or even get past the debug, unless you put the ws in there before the string? I have read about std::ws, but I still don't get how or why this would make or break that line of code. I thought getline() included whitespaces till it encountered the end of a line by itself, so why add something extra that removes or skips it, and why will getline() show an error without it?
If anyone could dumb it down for me, I'd appreciate it.

And how come you can combine the >> and the getline()?
What I'm being taught from my textbook is basically that it's either or, depending on if the content of the textfile is one type of data or several mixed together.
As in you either use >> if it's all int's and you want to store it as such, or getline() if it's mixed types of data so that you get all of it into a string.

I'm fairly new to coding in general, not just C++, so thanks for being patient with me.
Why won't it work, or even get past the debug, unless you put the ws in there before the string?

Probably because the stream contains whitespace that contains the '\n' character ( the end of line character).

In this usage the stream >> ws is extracting any leading whitespace characters if present, including the problematic end of line character ('\n') that causes problems with getline(). Also remember that the operator>> acts much like a function that returns the stream, this so you can "chain" the operations, ie:
cin >> variable1 >> getline(cin, varible2, ',') >> variable3;

Oooh, so it goes to the end of the first line, then removes the '\n' so that it takes it as just a single string and then jumps to the second line instead of aborting mission, and so on?

How come it only removes the end of line character and not the regular spaces though? (I'm very glad it doesn't, just curious so I know how I can use it in the future!).
Reading about std::ws I took it as it extracted ALL whitespace, not just the end of line ones.
How come it only removes the end of line character and not the regular spaces though?

The stream >> ws; removes all leading whitespace, and remember that stream >> someVariable stops processing at the first whitespace character.

Hello Tomoecchi,

There are many ways to write a for loop. In the beginning you are taught:
for (int i = 0; i < 10; i++) and this would be the basic construct of the for loop. After this what you put in a for loop and how you use it will depend on what you need to do as long as you follow the basic construct of its construction.

In lastchance's example:
1
2
for ( int data; getline( fileData >> ws, dummy ) && fileData >> data; )
    stuff.push_back( data );


for ( int data; getline( fileData >> ws, dummy ) && fileData >> data; )
He defines the "int" "data" to read the number in the file. Which becomes a local variable to the for loop. The middle section is where most of the work is done.

for ( int data; getline( fileData >> ws, dummy ) && fileData >> data; )
First the "getline" is reading the first line of the file, Where the input comes from, it is reading and skipping any leading white space, whatever it may be, and putting what is left in the variable "dummy".

Whether you use formatted or unformatted input and a variable called "dummy" or "junk" to get by something that you do not need this comes in very handy at times.

I am not sure why lastchance used the "std::ws" here. I am thinking that:
1
2
for ( int data; getline( fileData, dummy ) && fileData >> data; )
    stuff.push_back( data );
should work since all you are dong is getting by the first line. But I have not tried that yet.

The (&&) and what is to the right of it reads the number that you actually want.

Since the middle part of the for loop is an (&&) both sides have to be true for the loop to continue. Here the "getline" will more likely set the "eof" bit on the file stream and cause the condition to become false and end the while loop.

In his example the 3rd part is empty because there is nothing to do, so the middle part keeps repeating until "eof" is reached.

Although I understand the for loop forgive me and bear with me if I got something wrong or I have misunderstood something. If there is any part that youstill do not understand let me know and I will work on it.

Andy

 "My Name\n"
 "10\n"
 "\n"
 "Your Name\n"
 "35\n" );


 
getline( fileData >> ws, dummy ) && fileData >> data;


1) All leading ws is removed. In the first case there isn't any.
2) getline() gets "My Name\n" to dummy
3) >> data obtains 10
4) You now have "\n\nYour Name\n"
5) the leading ws is removed (removing "\n\n")
6) getline() gets "Your Name\n" to dummy
7) >> data obtains the 35
8) You now have "\n"
9) the leading ws is removed
10) getline() fails and the for loop is terminated.

Also, as there's no blank lines (line-feed) before the first string, you can use:

1
2
while (getline(fileData, dummy) && fileData >> data >> ws)
    cout << data << '\n';


This will remove all white-space chars after the found number - ready for the next getline()
Last edited on
Topic archived. No new replies allowed.