I try to do the most basic regex example in C++ using the default lib, and I keep getting either crashes or incoherent behavior.
// with -std=c++11
#include <regex>
using namespace std;
int main()
{
// Copied from the documentation, this one works
if (std::regex_match ("subject", std::regex("(sub)(.*)") ))
std::cout << "string matched\n";
// The most simple example I could try, crash with "regex_error"
if (std::regex_match ("99", std::regex("[0-9]*") ))
std::cout << "integer matched\n";
}
I've tried multiple syntaxes and flags, but nothing seems to work. Since my code seems to be matching all the examples I can find, I'm struggling to see what I'm missing.
As #Wiktor Stribiżew stated, it was just my compiler being too old. Updating the compiler (from gcc 4.1 to gcc 4.9) solved the problem!
Related
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 don't manage to use back references in regular expression in c++.
After trying more esoteric things, I tried this simple script on gcc 4.8.1:
#include <iostream>
#include <regex>
#include <string>
using namespace std;
int main() {
regex e("(..)\\1");
string s("aaaa");
if (regex_match(s,e))
cout << "match" << endl;
return 0;
}
but it produces a runtime error. I tried various flags in regex_constants like ECMAScript or grep but to no avail. What's wrong with this way of using back references in C++ regex engine?
Just to make sure I was not missing something trivial, I tried this in Java
class TestIt
{
public static void main (String[] args) throws java.lang.Exception
{
final String s = "aaaa";
final String e = "(..)\\1";
if (s.matches(e))
System.out.printf("match");
}
};
and obviously it prints match as expected, which is reassuring.
The regex engine included in gcc (in libstdc++) is not fully working yet. This regex works as expected on clang. So this issue has nothing to do with the way C++ treats regular expressions; rather it depends on the compiler used.
I was recently modifying some code, and found a pre-existing bug on one line within a function:
std:;string x = y;
This code still compiles and has been working as expected.
The string definition works because this file is using namespace std;, so the std:: was unnecessary in the first place.
The question is, why is std:; compiling and what, if anything, is it doing?
std: its a label, usable as a target for goto.
As pointed by #Adam Rosenfield in a comment, it is a legal label name.
C++03 §6.1/1:
Labels have their own name space and do not interfere with other identifiers.
It's a label, followed by an empty statement, followed by the declaration of a string x.
Its a label which is followed by the string
(expression)std: (end of expression); (another expression)string x = y;
The compiler tells you what is going on:
#include <iostream>
using namespace std;
int main() {
std:;cout << "Hello!" << std::endl;
}
Both gcc and clang give a pretty clear warning:
std.cpp:4:3: warning: unused label 'std' [-Wunused-label]
std:;cout << "Hello!" << std::endl;
^~~~
1 warning generated.
The take away from this story: always compile your code with warnings enabled (e.g. -Wall).
I'm using _GLIBCXX_DEBUG mode to help find errors in my code but I'm having a problem which I think is an error in the library, but hopefully someone can tell me I'm just doing something wrong. Here is a short example which repro's the problem:
#define _GLIBCXX_DEBUG
#include <iostream>
#include <sstream>
int main (int argc, const char * argv[]) {
std::ostringstream ostr;
ostr << 1.2;
std::cout << "Result: " << ostr.str() << std::endl;
return 0;
}
If I comment out the #define then the output is (as expected):
Result: 1.2
With the _GLIBCXX_DEBUG define in place however the output is simply:
Result:
I've tracked this down to the _M_num_put field of the stream being left as NULL, which causes an exception to be thrown (and caught) in the stream and results in no output for the number. _M_num_put is supposed to be a std::num_put from the locale (I don't claim to understand how that's supposed to work, it's just what I've learned in my searching so far).
I'm running this on a Mac with XCode and have tried it with both "LLVM GCC 4.2" and "Apple LLVM Compiler 3.0" as the compiler with the same results.
I'd appreciate any help in solving this. I want to continue to run with _GLIBCXX_DEBUG mode on my code but this is interfering with that.
Someone else has seen this over at cplusplus.com
and here at stackoverflow, too.
Consensus is that it is a known bug in gcc 4.2 for Mac OS, and since that compiler is no longer being updated, it is unlikely to ever be fixed.
Seems to me that you can either (1) use LLVM, or (2) build your own GCC and use it.
I know there's been a handful of questions regarding std::ifstream::open(), but the answers didn't solve my problem. Most of them were specific to Win32, and I'm using SDL, not touching any OS-specific functionality (...that's not wrapped up into SDL).
The problem is: std::ifstream::open() doesn't seem to work anymore since I've switched from Dev-C++ to Code::Blocks (I've been using the same MinGW-GCC back-end with both), and from Windows XP to Vista. (It also works perfectly with OS X / xcode (GCC back-end).)
My project links against a static library which #includes <string>, <iostream>, <fstream> and <cassert>, then a call is made to functionality defined in the static library, which in turn calls std::ifstream::open() (this time, directly). Following this, the stream evaluates to false (with both the implicit bool conversion operator and the good() method).
Code:
#include "myStaticLibrary.hpp"
int main(int argc, char **argv)
{
std::string filename("D:/My projects/Test/test.cfg");
std::cout << "opening '" << filename << "'..." << std::endl;
bool success(false);
// call to functionality in the static library
{
std::ifstream infile(filename.c_str());
success = infile.good();
// ...
}
// success == false;
// ...
return 0;
}
stdcout.txt says:
opening 'D:/My projects/Test/test.cfg'...
When I open stdcout.txt, and copy-paste the path with the filename into Start menu / Run, the file is opened as should be (I'm not entirely sure how much of diagnostic value this is though; also, the address is converted to the following format: file:///D:/My%20projects/test/test.cfg).
I've also tried substituting '/'s with the double backslash escape sequence (again, slashes worked fine before), but the result was the same.
It is a debug version, but I'm using the whole, absolute path taken from main()'s argv[0].
Where am I going wrong and what do I need to do to fix it?
Please create a minimal set that recreates the problem. For example, in your code above there's parsing of argv and string concatentation, which do not seem like a necessary part of the question. A minimal set would help you (and us) see exactly what's going wrong, and not be distracted by questions like "what's GetPath()?".
Try to do this instead of assert(infile.good()):
assert(infile);
I have overseen the importance of the fact that the function in question has close()d the stream without checking if it is_open().
The fact that it will set the stream's fail_bit (causing it to evaluate to false) was entirely new to me (it's not that it's an excuse), and I still don't understand why did this code work before.
Anyway, the c++ reference is quite clear on it; the problem is now solved.
The following code:
#include <string>
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;;
int main(int argc, char **argv)
{
std::string filename("D:/My projects/Test/test.cfg");
std::cout << "opening '" << filename << "'..." << std::endl;
std::ifstream infile(filename.c_str());
assert(infile.good()); // fails
return 0;
}
works fine on my Windows system using MinGW g++ 4.4.0, if I create the required directory structure. Does the file test.cfg actually exist? If you are opening a stream for input, it wioll fail if the file is not there.
Edit: To remove any DevC++ to CB issues:
build using command line only
make sure you rebuild the static library too