I'm trying to learn how to use the regex library in c++11.
On ubuntu 13.10 I'm trying to compile the following example from cplusplus.com:
// regex_replace example
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
int main ()
{
std::string s ("there is a subsequence in the string\n");
std::regex e ("\\b(sub)([^ ]*)"); // matches words beginning by "sub"
// using string/c-string (3) version:
std::cout << std::regex_replace (s,e,"sub-$2");
// using range/c-string (6) version:
std::string result;
std::regex_replace (std::back_inserter(result), s.begin(), s.end(), e, "$2");
std::cout << result;
// with flags:
std::cout << std::regex_replace (s,e,"$1 and $2",std::regex_constants::format_no_copy);
std::cout << std::endl;
return 0;
}
With the command:
$ g++ -std=c++11 -o file file.cc
I get the following output:
file.cc:13:48: error: no matching function for call to ‘regex_replace(std::string&, std::regex&, const char [7])’
What am I doing wrong?! There's not much hair left on my head...
Thanks in advance
You need to update your compiler from GCC 4.8 to GCC 4.9.
Unfortunately, GCC 4.9 has not been released yet, but it's stable enough to go with a trunk build if you need this functionality imminently.
Alternatively, give Clang or Boost.Regex a go.
Related
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.
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.
I'm using C++ Primer 5th to learn C++. The code below is copied from P729.
#include <iostream>
#include <regex>
#include <string>
int main()
{
// find the characters ei that follow a character other than c
std::string pattern("[^c]ei");
pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
std::regex r(pattern);
// ~~~~~~~~~~~^~~~~~~~~~~ where the exception was thrown.
std::smatch results;
std::string test_str = "receipt freind theif receive";
if (regex_search(test_str, results, r))
std::cout << results.str() << std::endl;
return 0;
}
When running it, an exception was thrown :
terminate called after throwing an instance of 'std::regex_error'
what(): regex_error
Press <RETURN> to close this window...
By debugging step by step, I found it was thrown while constructing the object r from the code from bits/regex_compiler.h:
template<typename _InIter, typename _TraitsT>
bool
_Compiler<_InIter, _TraitsT>::
_M_bracket_expression()
{
if (_M_match_token(_ScannerT::_S_token_bracket_begin))
{
_RMatcherT __matcher(_M_match_token(_ScannerT::_S_token_line_begin),
_M_traits);
if (!_M_bracket_list(__matcher)
|| !_M_match_token(_ScannerT::_S_token_bracket_end))
__throw_regex_error(regex_constants::error_brack);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_M_stack.push(_StateSeq(_M_state_store,
_M_state_store._M_insert_matcher(__matcher)));
return true;
}
return false;
}
OK.The code above is totally beyond what I can understand.That's what I have tried so far.Can anyone tell me what's gong on here? How to fix it?
UPDATE:
The compiler I'm using:
gcc version 4.8.1 (Ubuntu 4.8.1-2ubuntu1~13.04)
You need to use minimal version of g++ 4.9 to use regex properly.(You can compile it with lower versions, but it's broken)
You can download g++ 4.9 from their side. GCC SITE
After that try:
g++49 -std=c++0x -static-libstdc++.
I try to search more about it for you.
EDIT: g++49, because of the reason, that version 4.9 can't be default after building it.
According to this reference, I should be able to match a single digit with
std::regex e1 ("\\d");
However, when I run the following test code I get a regex exception.
#include <iostream>
#include <string>
#include <regex>
int main()
{
std::regex r("\\d");
std::string s("9");
if (std::regex_match(s, r)) { std::cout << "matched!" << std::endl; }
}
GCC's std::regex support is not yet ready for prime time. See: Is gcc 4.8 or earlier buggy about regular expressions?
If std::regex support is still buggy as #qwrrty suggests, the character class '[0-9]' is a substitute for '\d'.
I ran into an unexpected compilation error when trying to use getline() with a temporary stream object:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string input = "hello\nworld\nof\ndelimiters";
string line;
if (getline(stringstream(input), line)) // ERROR!
{
cout << line << endl;
}
}
It looks like no overload of getline() exists that accepts an rvalue reference to a stream object. If I change main() to use an lvalue, it compiles and runs as expected:
int main()
{
string input = "hello\nworld\nof\ndelimiters";
string line;
stringstream ss(inpupt);
if (getline(ss, line)) // OK
{
cout << line << endl;
}
}
So I had a look in the C++11 Standard and I found out (§ 21.4.8.9) that an overload of getline() that takes an rvalue reference to a stream object should be present.
Am I missing something obvious, or is this a bug? The error occurs both with GCC 4.7.2 and with Clang 3.2. I cannot test this on VC at the moment.
If I compile on OS X with the following line, it compiles successfully. What version of the libstdc++ or libc++ are you using?
clang++ -std=c++11 -stdlib=libc++ foo.cc
libstdc++ (and libc++ for that matter) do not yet fully implement the C++ 2011 standard library. This appears to be one of the missing functions from libstdc++.
Sadly, I don't know of any resource that lists exactly what is missing from each implementation.