Find float in *.txt file

I don't know how to solve following problem. I am programming with codeblocks in C++ under Windows7. The program will be a 32 bit console application. I have Boost installed and would like to use it.(but I still don't know it)

I have to find real numbers in an *.txt file. The file is about 1000 lines long. The input I can give to find the numbers is a marker at the beginning of the line and the position of the number i want to have.


Here is an example of a *.txt file. The example has 5 columns but the real file could have 1-10.

...
haus! 1.222 2.115 2000.1 50.0255 56.302
Garten 8556.2 6985 54.666 52.00 25.555
muell 654.1 6895.00 255.58 10 68.68
auto 6868.8 6856.8 7 66.888 1022.5
th&55 789.32 35.88 677.8 8.9987 5.511
!§rho 564.5 50.2 58.7 98.7 101.8
...

In my example the marker could be "auto" and the number of column "4". Therefore I would like to get the return value "66.888".

My function could look like this (but maybe you have a better idea):
float Findnumber(string input, string marker, int column) //input is a string with the whole *.txt file

I tried something with string.find() but then I just have the marker and don't know how to get the number.

So, you know an efficient way to do it?
Once u find the row u'll have to use something like 'getline' to capture the whole line and put it into a string. Then, u can parse the string based on whitespaces (keeping track of each encountered whitespace) until u reach the desired column.
Last edited on
Divide and conquer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <string>
#include <sstream>
#include <fstream>

std::string get_the_line( std::istream& stm, const std::string& marker )
{
    std::string line ;
    while( std::getline( stm, line ) ) if( line.find(marker) == 0 ) return line ;
    return "" ;
}

std::string get_the_field( const std::string& line, int column )
{
    std::string field ;
    std::istringstream stm(line) ;
    for( int i = 0 ; i<column ; ++i ) if( !( stm >> field ) ) return "" ;
    return field ;
}

float to_float( const std::string& field )
{
    std::istringstream stm(field) ;
    float value ;
    if( stm >> value && stm.eof() ) return value ;
    else /* error */ return 0 ;
}

float find_number( const char* path2file, const std::string& marker, int column )
{
    std::ifstream file( path2file ) ;
    return to_float( get_the_field( get_the_line(file,marker), column ) ) ;
}
Thank you very much for the code! I was looking for some hints, maybe library functions, but working code is of course much better.

But I had to so some modifications until it realy did what I needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
std::string get_the_line( std::istream& stm, const std::string& marker )
{
    std::string line ;
    while( std::getline( stm, line ) ) if( line.find(marker) != string::npos )
    {
        size_t pos=line.find(marker);
        pos=pos+marker.length();
        line=line.substr(pos,string::npos);
        return line;
    }
    return "" ;
}

std::string get_the_field( const std::string& line, int column )
{
    std::string field ;
    std::istringstream stm(line) ;
    for( int i = 0 ; i<=column ; ++i ) stm >> field;
    return field ;
}

float to_float( const std::string& field )
{
    std::istringstream stm(field) ;
    float value ;
    if( stm >> value && stm.eof() ) return value ;
    else /* error */ return 0 ;
}

float find_number( const char* path2file, const std::string& marker, int column )
{
    std::ifstream file( path2file ) ;
    return to_float( get_the_field( get_the_line(file,marker), column ) ) ;
}



Comments:
In get_the_line() the if statement "if( line.find(marker) == 0 ) return line;" didn't do the job, I changed it to "if( line.find(marker) != string::npos )". It is also better that the marker can now be anywhere in the line. Furthermore I extended the function that it doesn't return the whole line, but cuts the marker of and returns the rest of the line.

In get_the_field() I didn't understand the behavior of "if( !( stm >> field ) )". I would be glad if somebody could explain it! But it made some trouble and I changed it to the simple solution" stm >> field;". I didn't knew the ">>" operator before. This thing is pure genius and makes my problem simple. Thanx for it!
Inside the for-loop "for( int i = 0 ; i<=column ; ++i )" it had to be a "<=" operator in the middle to find the right column.

So, thanx again for the help!

> I was looking for some hints

The hint was 'divide and conquer'. In retrospect, the post would perhaps have been better if had given just the declarations of the three functions after that.


> I didn't understand the behavior of "if( !( stm >> field ) )"

stm >> field tries to extract field from stm and returns a reference to stm. If the attempt to extract field failed, stm would be in a failed state.

1
2
// if the stream input failed,  indicate failure by returning an empty string
if( !( stm >> field ) ) return "" ;



> ... the ">>" operator ... makes my problem simple

C++ now has std::stof() http://en.cppreference.com/w/cpp/string/basic_string/stof

If your implementation has std::stof(), you could just use that.


> Inside the for-loop "for( int i = 0 ; i<=column ; ++i )" it had to be a "<=" operator in the middle to find the right column.

There is one column less in the line once you cut the marker from the line.

With 'the marker can now be anywhere in the line.' and
'cuts the marker of and returns the rest of the line.'
what would happen if the marker was originally after the required column?
Topic archived. No new replies allowed.