Result of std::regex_match seems wrong [duplicate] - c++

This question already has answers here:
Simple std::regex_search() code won't compile with Apple clang++ -std=c++14
(3 answers)
Closed 6 years ago.
I'm trying to understand the behavior of the following code.
I think it might be a bug since the result looks wrong to me.
#include <iostream>
#include <regex>
int main(int ac, char **av)
{
std::regex reg("lib(.*)\\.so");
std::smatch match;
std::cout << std::regex_match(std::string("libscio.so"), match, reg) << std::endl;
std::cout << match.str(1) << std::endl;
return 0;
}
I'm expecting
1
scio
But it gives me
1
ocio
Compiled with gcc version 4.9.2 (Debian 4.9.2-10) on x86_64 GNU/Linux

I had to structure the program differently because it would not compile otherwise in VS 2015. Maybe that's causing your problem, with your compiler, too? Note the string temporary variable.
#include <iostream>
#include <regex>
int main(int ac, char **av)
{
std::regex reg("lib(.*)\\.so");
std::smatch match;
std::string target = "libscio.so";
std::cout << std::regex_match(target, match, reg) << std::endl;
std::cout << match.str(1) << std::endl;
return 0;
}
This yields 1 and scio in VS 2015 as expected.
According to the link #LogicStuff posted, this is because passing in a temporary object means that the matches point to iterators that are invalidated when the temporary goes out of scope. So what you see probably is the garbage left over when your temporary string got deleted.

Related

how do i fix this no matching function for call to 'stoi(int&)'|

i keep getting this error. i know this is a c++ 11 function but it still isnt working with code blocks c++ compiler. am i using this function correctly of is it a problem with the codeblocks compiler. i tried changing the compiler. using the "have g++ follow the c++11 iso standard" i still keep getting this error. or getting the "stoi() does not exist in the current scope" error
#include <iostream>
#include <string>
using namespace std;
int main()
{
int test = 34;
cout << stoi(test);
}
stoi means "String To Int". It will read an int from a std::string (or std::wstring). See also the reference.
You were probably looking for the reverse std::to_string (reference). But you don't need either, there is no need to convert to string before printing:
#include <iostream>
int main()
{
int test = 34;
std::cout << test;
}
stoi means string to int. So it takes a string as an input.
This should work:
string test = "34"; cout << stoi(test);

Differences in regex support between gcc 4.9.2 and gcc 5.3

Can anyone more familiar with gcc point out why the sample below fails to match on gcc 4.9.2 but succeeds on gcc 5.3? Is there anything I can do to alternate the pattern so that it would work (also seems to work fine on VS 2013)?
#include <iostream>
#include <regex>
std::regex pattern("HTTP/(\\d\\.\\d)\\s(\\d{3})\\s(.*)\\r\\n(([!#\\$%&\\*\\+\\-\\./a-zA-Z\\^_`\\|-]+\\:[^\\r]+\\r\\n)*)\\r\\n");
const char* test = "HTTP/1.1 200 OK\r\nHost: 192.168.1.72:8080\r\nContent-Length: 86\r\n\r\n";
int main()
{
std::cmatch results;
bool matched = std::regex_search(test, test + strlen(test), results, pattern);
std::cout << matched;
return 0;
}
I assume I am using something that is not supported in gcc 4.9.2 but was added on or fixed later, but I have no idea where to look it up.
UPDATE
Due to the amount of help and suggestions I tried to backtrack the issue instead of just switching to gcc 5. I get correct matches with this modification:
#include <iostream>
#include <regex>
std::regex pattern("HTTP/(\\d\\.\\d)\\s(\\d{3})\\s(.*?)\\r\\n(?:([^:]+\\:[^\\r]+\\r\\n)*)\\r\\n");
const char* test = "HTTP/1.1 200 OK\r\nHost: 192.168.1.72:8080\r\nContent-Length: 86\r\n\r\n";
int main()
{
std::cmatch results;
bool matched = std::regex_search(test, test + strlen(test), results, pattern);
std::cout << matched << std::endl;
if (matched)
{
for (const auto& result : results)
{
std::cout << "matched: " << result.str() << std::endl;
}
}
return 0;
}
So I guess the problem is with the group that matches the HTTP header name. Will check further.
UPDATE 2
std::regex pattern(R"(HTTP/(\d\.\d)\s(\d{3})\s(.*?)\r\n(?:([!#$&a-zA-Z^_`|-]+\:[^\r]+\r\n)*)\r\n)")
is the last thing that works. Adding any of the remaining characters that I had in my group - %*+-. (escaped or not epscaped) - breaks it.
So I know GCC did not support the c++11 regex library until GCC 4.9 officially. See Is gcc 4.8 or earlier buggy about regular expressions?. Since it was so new, it is likely that it had a few bugs to smooth out. Pinning down the exact cause would be difficult, but the problem is in the implementation and not in the regex.
Side note: I remember spending 20 minutes one time trying to figure out what was wrong with my regex when I found the mentioned article and realized that I was using gcc 4.8.*. Since the machine I had to run on wasn't mine, I basically ended up compiling on a different, similar platform with a later version of gcc and a few hacks and then it ran on the target platform.

Why does the c++ regex_match function require the search string to be defined outside of the function?

I am using Visual Studio 2013 for development, which uses v12 of Microsoft's c++ compiler tools.
The following code executes fine, printing "foo" to the console:
#include <regex>
#include <iostream>
#include <string>
std::string get() {
return std::string("foo bar");
}
int main() {
std::smatch matches;
std::string s = get();
std::regex_match(s, matches, std::regex("^(foo).*"));
std::cout << matches[1] << std::endl;
}
// Works as expected.
The same code, with the string "s" substituted for the "get()" function, throws a "string iterators incompatible" error at runtime:
#include <regex>
#include <iostream>
#include <string>
std::string get() {
return std::string("foo bar");
}
int main() {
std::smatch matches;
std::regex_match(get(), matches, std::regex("^(foo).*"));
std::cout << matches[1] << std::endl;
}
// Debug Assertion Failed!
// Expression: string iterators incompatible
This makes no sense to me. Can anyone explain why this happens?
The reason is that get() returns a temporary string, so the match results contains iterators into an object that no longer exists, and trying to use them is undefined behaviour. The debugging assertions in the Visual Studio C++ library notice this problem and abort your program.
Originally C++11 did allow what you're trying to do, but because it is so dangerous it was prevented by adding a deleted overload of std::regex_match which gets used when trying to get match results from a temporary string, see LWG DR 2329. That means your program should not compile in C++14 (or in compilers that implement the DR in C++11 mode too). GCC does not yet implement the change yet, I'll fix that.

How to use C++11 std::stoi with gcc? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to convert a number to string and vice versa in C++
I am using Qt Creator 2.5.0 and gcc 4.7 (Debian 4.7.2-4). I added "QMAKE_CXXFLAGS += -std=c++11" to .pro file. Everything seems to be OK, I used C++11 std::for_each and so on. But when I included "string" header and wanted to use stoi, i got the following error:
performer.cpp:336: error: 'std::string' has no member named 'stoi'
I found some questions related to MinGW and one more, to Eclipse CDT and they had their answers. But I use Linux, why it is NOT working here?
#include <iostream>
#include <string>
int main()
{
std::string test = "45";
int myint = stoi(test);
std::cout << myint << '\n';
}
or
#include <iostream>
#include <string>
using namespace std
int main()
{
string test = "45";
int myint = stoi(test);
cout << myint << '\n';
}
look at http://en.cppreference.com/w/cpp/string/basic_string/stol
std::stoi is a function at namespace scope, taking a string as its argument:
std::string s = "123";
int i = std::stoi(s);
From the error message, it looks like you expect it to be a member of string, invoked as s.stoi() (or perhaps std::string::stoi(s)); that is not the case. If that's not the problem, then please post the problematic code so we don't need to guess what's wrong with it.

C++ regex string capture

Tring to get C++ regex string capture to work. I have tried all four combinations of Windows vs. Linux, Boost vs. native C++ 0x11. The sample code is:
#include <string>
#include <iostream>
#include <boost/regex.hpp>
//#include <regex>
using namespace std;
using namespace boost;
int main(int argc, char** argv)
{
smatch sm1;
regex_search(string("abhelloworld.jpg"), sm1, regex("(.*)jpg"));
cout << sm1[1] << endl;
smatch sm2;
regex_search(string("hell.g"), sm2, regex("(.*)g"));
cout << sm2[1] << endl;
}
The closest that works is g++ (4.7) with Boost (1.51.0). There, the first cout outputs the expected abhelloworld. but nothing from the second cout.
g++ 4.7 with -std=gnu++11 and <regex> instead of <boost/regex.hpp> produces no output.
Visual Studio 2012 using native <regex> yields an exception regarding incompatible string iterators.
Visual Studio 2008 with Boost 1.51.0 and <boost/regex.hpp> yields an exception regarding "Standard C++ Libraries Invalid argument".
Are these bugs in C++ regex, or am I doing something wrong?
Are these bugs in C++ regex, or am I doing something wrong?
At the time of your posting, gcc didn't support <regex> as noted in the other answer (it does now). As for the other problems, your problem is you are passing temporary string objects. Change your code to the following:
smatch sm1;
string s1("abhelloworld.jpg");
regex_search(s1, sm1, regex("(.*)jpg"));
cout << sm1[1] << endl;
smatch sm2;
string s2("hell.g");
regex_search(s2, sm2, regex("(.*)g"));
cout << sm2[1] << endl;
Your original example compiles because regex_search takes a const reference which temporary objects can bind to, however, smatch only stores iterators into your temporary object which no longer exists. The solution is to not pass temporaries.
If you look in the C++ standard at [ยง 28.11.3/5], you will find the following:
Returns: The result of regex_search(s.begin(), s.end(), m, e, flags).
What this means is that internally, only iterators to your passed in string are used, so if you pass in a temporary, iterators to that temporary object will be used which are invalid and the actual temporary itself is not stored.
GCC doesn't support <regex> yet. Refer to the Manual