Search code examples
c++stringsubstr

C++ substring not giving me the correct result


I have the following code:

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

using namespace std;

int main()
{
    fstream file;
    string s;
    //file contains the following
    //id="123456789"
    //Note: There is no spaces at the end
    file.open("test.txt", ios::in);
    getline(file, s);
    s = s.substr(s.find("\"")+1, s.length()-1);
    cout << s << endl;
    return 0;
}

The results print:

123456789"

Why is there a quote at the end? A weird thing is that when I change s.length()-1 to s.length()-5, the code work how I wanted it to. What is the problem here?


Solution

  • The 2nd parameter of string::substr() is a count, not an index, like you are treating it.

    In your example, s.length()=14, so you are asking for 14-1=13 characters starting at the index +1 past the 1st " character (3+1=4), but there are only 10 characters remaining from that position onward. That is why the 2nd " character is being included in the substring.

    Use string::find() again to find the index of the 2nd " character, and then subtract the two indexes to get the length between them, eg:

    auto start = s.find('\"') + 1;
    auto stop = s.find('\"', start);
    s = s.substr(start, stop-start); 
    

    start will be the index +1 past the 1st " character (3+1=4), and stop will be the index of the 2nd " character (13). Thus, the length you get is 13-4=9 characters.


    Another way to handle this would be to put the string into an istringstream and then use the std::quoted I/O manipulator to extract the substring between the " characters, eg:

    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <iomanip>
    #include <string>
    
    using namespace std;
    
    int main()
    {
        ifstream file("test.txt");
        string s;
        getline(file, s);
        istringstream iss(s);
        iss.ignore(3);
        iss >> quoted(s);
        cout << s << endl;
        return 0;
    }