Search code examples
c++regexstringcharatoi

Why can I not convert this regex return to a string to an integer or straight to an integer? (C++)


I've read a few StackExchange posts and other pages on converting strings to integers, but this is not working. This is the last thing I tried:

if (infile.is_open())
{
        while (getline (infile,line))
        {

            regex_match(line,matches,exp);

            regex_match((string)matches[1], time0, exp_time);

            buffer << time0[1];
            str = buffer.str();

            str.append("\0");


            cout << atoi(str.c_str()) << '\n';

            last_match = matches[2];
            buffer.str(string());
        }
        infile.close();
}

I can't think of any other ways. I tried the normal convert to string to char * to integer. I tried converting it to a string then using stoi() to convert it to an integer. I tried appending a NULL character ("\0") to it, I tried appending it in the buffer, too. I also tried atof() and stof(). stoi() and stof() both crash the program. atoi() and atof() both return 0, always.


Here's an SSCCE, with the problem featured (atoi(str.c_str()) should not be 0):

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

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

#include <sstream>

using namespace std;



int main(int argc, char* argv[])
{
    regex exp("^(.+),(.+),.+,.+,(.+),.+,.+$");
    regex exp_time("^(.+)-(.+)-(.+)");
    smatch matches;
    smatch time0;
    string line;
    ifstream infile(argv[1]);
    string last_match;
    stringstream buffer;
    string str;


    int i = 0;

    if (infile.is_open())
    {
        while (getline(infile, line))
        {

            regex_match(line, matches, exp);

            regex_match((string)matches[1], time0, exp_time);

            buffer << time0[1];
            str = buffer.str();

            str = time0[1].str();
            str.append("\0");



            cout << atoi(str.c_str()) << " " << time0[1] << '\n';

            last_match = matches[2];
            buffer.str(string());
            i++;
        }
        infile.close();
    }

    return 0;
}

The input would be a csv file with these values:

1996-09-04,19.00,19.25,18.62,18.87,528000,0.79
1996-09-03,19.00,19.37,18.75,19.00,1012800,0.79
1996-08-30,19.87,20.12,19.37,19.62,913600,0.82
1996-08-29,20.87,21.12,19.75,19.75,1987200,0.82
1996-08-28,20.12,22.12,20.12,21.12,5193600,0.88
1996-08-27,19.75,20.37,19.75,20.12,1897600,0.84
1996-08-26,20.12,20.12,19.75,19.75,388800,0.82
1996-08-23,19.75,20.25,19.75,19.75,1024000,0.82
1996-08-22,18.62,20.00,18.25,19.87,1921600,0.83
1996-08-21,19.12,19.25,18.25,18.62,688000,0.78
1996-08-20,19.62,19.62,19.12,19.12,494400,0.80
1996-08-19,19.37,19.62,19.37,19.62,428800,0.82
1996-08-16,19.50,19.87,19.12,19.37,864000,0.81

You would run the program with program.exe filename.csv

Here's a shorter program with the problems more apparent:


Solution

  • Your problem is in this line:

    regex_match((string)matches[1], time0, exp_time);
    

    You can't pass a temporary as the subject string of a regex match, because the string contents have to still be around when you query the match results. The result of (string)matches[1] is destroyed at the end of the current full expression (i.e. at the next semicolon); when you get around to querying time0[1] on the next line, the time0 match is referring to a string that doesn't exist any more, which is undefined behaviour.