Read File and extracting info from

Hi

Can anyone point me in right direction for ways to read a file and then extract the information from it. For example

someFile.txt
Title SomeTitle
SomeFloats 1.2 1.5 1.8
SomeInts ( 2 4 6 )
SomeFloats 2.0 5.5 4.4
etc...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  #include <string>
#include <vector>
#include <fstream>
#include <iostream>

int main()
{
	std::string title = "";
	std::vector <int> intVector;
	std::vector <float> floatVector;

	std::ifstream inFile;
	inFile.open("someFile");

	if (!inFile) {
		std::cout << "ERROR MESSGAE";
	}

	//cycle through file, extract data and put in title, and diffrent vectors.

}


Im guessing I would need to go through each line quering if it states Title, Somefloats etc but what would be a good way to go about such?

Thanks
You've got the right idea.

Some of what you need to do depends on what you're going to do with the data. For example, are the keywords you've shown the only keywords? Are the keywords always mixed case? What is the significance of the parens on the SomeInts line? Are there always three numbers oon a line? Is there any difference between the floats on the first SomeFloats line and the second SomeFloats line?

This should help you get started:
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    std::string keyword;
    std::string line;
    int someint;
    float somefloat;

    while (inFile >> keyword) 
    {   // upshift the keyword        
        inFile >> line;     // Read in the rest of the line
        std::stringstream ss(line);
        if (keyword == "TITLE")
            title = line;
        if (keyword == "SOMEINTS")
        {   //  Need to ignore parens
            while (ss >> someint) 
                intVector.push_back(someint);
        )
        if (keyword == "SOMEFLOATS")
        {   while (ss >> somefloat) 
                floatVector.push_back(somefloat);
        )
    }    

You need to observe the pattern.
Title SomeTitle
SomeFloats 1.2 1.5 1.8
SomeInts ( 2 4 6 )
SomeFloats 2.0 5.5 4.4
Notice that the first two words are for the title (or is it one word? I donno). So you can use the extraction operator >> to get rid of these two words.

Next you need to take floating values from the file. You can do that too with a loop and the extraction operator >>. But wait - when to stop? It seems that '(' marks the beginning of integers so if you come across '(' stop inputting floating values and start inputting integer values like you did with floating, with the extraction operator and a loop.

Finally you reach the ')', once you've spotted it, stop the loop and start another loop to extract floating points like you did until you read the end of the file EOF. Expressions with extraction give false value when they've read EOF so while loops are good for reading files.

Example of the loop:
1
2
3
4
5
6
7
8
9
10
std::vector <float> floating_values;
std::string string_variable;

while(file >> string_variable) {

   if (string_variable == '(') 
      break

   floating_values.push_back(std::stof(string_variable));
}


What you posted is all I had to deduce the pattern so it's an assumption. For example there might actually be the word "SomeFloats" then you need to discard that.
Thanks a lot. The above is just for testing purposes, Im unsure how the data will be formatted at the time, the brackets was just incase I need to have a work around.
Further to that rather than call an if stament for every item to ignore such as ( , { / etc would there any way to say ignore all of such in a better way.

And clarification on 2 things...

Stringstream, is that just to take the value to be able to put into any data type such as the int or string.

and the extraction operator >> , is this basically saying move on to next word, line or add to existing.

What do you know about the data?

You could read the text as a string and then see whether it's a double or an int (and accordingly list them), if neither then you can ignore it. Can't use stringstream in this case because both int and double will happily accept your values.

I don't know if there is a standard library function for checking if a value is float. If not you can write your own function.

Stringstream, is that just to take the value to be able to put into any data type such as the int or string.

You can say that yes.

and the extraction operator >> , is this basically saying move on to next word, line or add to existing.
It's the same extraction operator you use for cin>>var; It tells to move data from cin to var.



I was thinking about maybe doing something like this:

1
2
    cin >> num;
    cin.get(ch);

Where num will catch integers and cin.get() would take decimal point but I realize that it will make it unnecessarily complicated.

Yeah it's really very unnecessarily complicated.
How it would have looked like to use that method (but I didn't test):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int integer_part;
double decimal_part;
char decimal_point;

cin >> integer_part;
cin >> decimal_point;

if(!cin) {
   cin.clear();
   cin.ignore(INT_MAX, ' ');   
}

else if(decimal_point != '.') {
   putback(decimal_point);
   integer_array.push_back(integer_part);
}

else {
   cin >> decimal_part;
   while((int)decimal_part != 0)
      decimal_part /= 10;
   integer_part += decimal_part;
   floating_array.push_back(integer_part);
}


And also don't use this method because it relied on floating arithmetic as I just realized too.

So you're better off with a function that uses a for-loop to check for decimal points and verifies all other indexes are digits (and also makes sure there's only one decimal point).

Unless there's a standard library function then you could just use that.
Last edited on
Im unsure how the data will be formatted at the time

Without knowing the format of the data in the file, retrieving the data will be problematic.

Think I caused some confusion.

At this time Im not sure how the data will be formatted. I am first just messing with test examples such as above then moving on, I think first will be creating a list for all different variables I have type def such as keyboard input triggers and floats for things such as scroll speed for the mouse so Im not setting them in the code. Guess file for that would be quite straight forward with

key up "w"
key down "s"
key left "a"
mouse scroll speed 2.56
cam initial pos 1.0,0.0,-3.5

Then taking it further I would be looking at reading in files for things such as .obj or MD5 3d models, don't want to jump straight to that till I got some basics down. Looking at above I know if it my own file I would not format in such a way with such punctuation but for test/learning purposes I want to work such out.

In all cases I think I would know the data type but good potential solution Grime if not.
The more complicated you make your syntax, the harder it's going to be to parse.
If each keyword/keywords defines the type and number of arguments, then the stringstream approach I posted earlier works well.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct
{  char letter_up;
    char letter_down;
    char letter_left;
    char letter_right;
} params;

void parse_key(std::stringstream & ss)
{  std::string dir;
    char letter;

    ss >> dir;
    ss >> letter;   // Assume no quotes
    if (dir == "up")
        params.letter_up = letter;
    else if (dir == "down")
        params.letter_down = letter;
    else if (dir == "left")
        params.letter_left = letter;
    else if (dir == "right")
        params.letter_right = letter;
}


27
28
        if (keyword == "key")
            parse_key(ss);

Topic archived. No new replies allowed.