简体   繁体   中英

Why does the function find of C++ stl string sometimes go wrong sometime go right?

I am trying to do some file reading with C++ in Ubuntu 16.04 (GCC&G++ 5.4 and CMake 3.5.1). The test file (named 123.txt) have only a line words just like this:

Reprojection error: avg = 0.110258   max = 0.491361

I just want to get the avg error and max error. My method is to get a line and put them into a std::string and use string::find . My codes are very easy just like this:

#include <iostream>
#include <string>
#include <stdio.h>

using namespace std;

int main()
{
    FILE *fp = fopen("123.txt", "r");
    char tmp[60];
    string str;
    fgets(tmp, size_t(tmp), fp);
    fclose(fp);
    cout << tmp << endl;
    str = tmp;
    cout << str.size() << endl;
    size_t avg = str.find("avg");
    size_t max = str.find("max");
    cout << avg << endl;
    cout << max << endl;
}

I can use g++ to compile it successfully. But I meet a strange issue.

When I first run it in the command, it will get the right result:

Reprojection error: avg = 0.110258   max = 0.491361

52
20
37

If I run codes again, it will go wrong sometimes just like this:

p
2
18446744073709551615
18446744073709551615

The "p" is a disorderly code which can not be shown correctly in the command. I am not good at C++ and feel confused about it. Is there someone who can say something? Thank you!

The expression

fgets(tmp, size_t(tmp), fp);

is ill-formed, size_t(tmp) will not work as you expect, you need sizeof(tmp) .

The 52 value you get is because fgets consumes the \n character and this is counted too, actually the string has 51 characters counting with spaces.

That said, in this case you can use better C++ tools to replace the C ones you are using, fopen can be replaced by using the fstream library, fgets can be replaced by getline .

Something like:

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

int main()
{
    std::ifstream fp("123.txt"); //C++ filestream

    if (fp.is_open()) {//check for file opening errors

        std::string str;
        std::getline(fp, str); //C++ read from file
        fp.close();
        std::cout << str << std::endl;
        std::cout << str.size() << std::endl;
        size_t avg = str.find("avg");
        size_t max = str.find("max");
        std::cout << avg << std::endl;
        std::cout << max << std::endl;
    }
    else{
        std::cerr << "Couldn't open file";
    }
}

Note that I dind't use using namespace std; , this is for a reason, it's not a good practice, you can check this thread for more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM