Why does my regex work JavaScript but not in C++? - c++

My regex is supposed to capture the names of all function declarations:
([\w{1}][\w_]+)(?=\(.+{)
In JavaScript it works as expected:
'int main() {\r\nfunctionCall();\r\nfunctionDeclaration() {}\r\n}'.match(/([\w{1}][\w_]+)(?=\(.+{)/g);
// [ 'main', 'functionDeclaration' ]
In C++ Builder I get this error:
regex_error(error_badrepeat): One of *?+{ was not preceded by a valid
regular expression.
Minimal Reproducible Example:
#include <iostream>
#include <regex>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> matches;
string text = "int main() {\r\nfunctionCall();\r\nfunctionDeclaration() {}\r\n}";
try {
//regex myRegex("([\\w{1}][\\w_]+)(?=\\()"); works as intended
regex myRegex("([\\w{1}][\\w_]+)(?=\\(.+{)"); // throws error
sregex_iterator next(text.begin(), text.end(), myRegex);
sregex_iterator end;
while (next != end) {
smatch match = *next;
cout << match.str() << endl;
next++;
}
} catch (regex_error &e) {
cout << "([\\w{1}][\\w_]+)(?=\\(.+{)"
<< "\n"
<< e.what() << endl;
}
}
I used g++ to compile the above, instead of C++ Builder, and the error it gives is different: Unexpected character in brace expression.

The correct regex string literal for C++ is this:
"([\\w{1}][\\w_]+)(?=\\(.+\\{)"
The { must be escaped, unlike in JavaScript.

Related

how connect regex replace to function in c++

#include <iostream>
#include <iterator>
#include <regex>
#include <string>
std::string ty(std::string text){
if(text == "brown")
return "true";
else
return "qw";
}
int main()
{
std::string text = "Quick $brown fox";
std::cout << '\n' << std::regex_replace(text, std::regex(R"(\\$(.*))"), ty("$&")) << '\n';
}
i use c++11 . I try without if worked but with if don't work ? i don't know what to do
There's a lot of different things wrong with the original code.
Firstly here's some working code
#include <iostream>
#include <iterator>
#include <regex>
#include <string>
std::string ty(std::string text){
if(text == "brown")
return "true";
else
return "qw";
}
int main()
{
std::string text = "Quick $brown fox";
std::smatch m;
if (std::regex_search(text, m, std::regex(R"(\$([[:alpha:]][[:alnum:]]*))")))
{
std::cout << '\n' << ty(std::string(m[1].first, m[1].second)) << '\n';
}
else
{
std::cout << "\nno match\n";
}
}
Some things that were wrong with the original code
Firstly the function being called was wrong. Use std::regex_search to search for matches in a string. Capture the results in an std::smatch object and then use those results to call the ty function.
The regex was wrong in two different ways. Firstly \\ is wrong because you are using a raw string literal, so only a single backslash is required. Secondly (.*) is wrong because that will match the entire rest of the string. You only want to match the word following the dollar. I've used ([[:alpha:]][[:alnum:]]*) instead. That might not be exactly what you want but it works for this example. You can modify it if you want.

why is this regex in C++ throwing an invalid range in bracket expression exception?

I am playing around with C++ regular expression:
#include <iostream>
#include <regex>
using namespace std;
int main()
{
std::regex e("[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]");
std::string str = "¡";//u00A1, trying to match this character
bool match = std::regex_match(str, e);
cout << match << endl;
return 0;
}
The compilation failed with exception thrown:
terminate called after throwing an instance of 'std::regex_error'
what(): Invalid range in bracket expression.
I tested on regex101.com with:
[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]
and it gives me a match.
Also, is regex in C++ using the ECMAScript flavor? Thanks.
The problem is that you are using a char based regex but a 16 bit regular expression. Try switching to wchar_t as your character type.
#include <iostream>
#include <regex>
using namespace std;
int main()
{
std::wregex e(L"[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]");
std::wstring str = L"¡";//u00A1, trying to match this character
bool match = std::regex_match(str, e);
cout << match << endl;
return 0;
}

Boost regex cpp for finding strings between %% with output excluding the % character itself

I am having a problem with boost regex in cpp. I want to match a string like
"Hello %world% regex %cpp%" and expected string output is world, cpp
Can somebody suggest a regex for this
Thanks
Anil
I personally prefer "\\%([^\\%]*)\\%" (or as a raw string R"r(\%([^\%]*)\%)r")
It doesn't rely on non-greedy qualifiers
Which is essentially
one percent character \\%
any amount of non-percent characters [^\\%]*
one percent character \\%
I know this is tagged boost but here's a solution with std::regex
#include <string>
#include <regex>
#include <iostream>
int main()
{
using namespace std;
string source = "Hello %world%";
regex match_percent_enclosed (R"_(\%([^\%]*)\%)_");
smatch between_percent;
bool found_match = regex_search(source,between_percent,match_percent_enclosed);
if(found_match && between_percent.size()>1)
cout << "found: \"" << between_percent[1].str() << "\"." << endl;
else
cout << "no match found." << endl;
}
you may get some idea
%(.+?)%
Result:
Match 1
1. world
Match 2
1. cpp
You can use this regex \%(.*?)\%smallest group
Online regex: https://regex101.com/r/dSCE2a/2
And for the code with boost
#include <iostream>
#include <cstdlib>
#include <boost/regex.hpp>
using namespace std;
int main()
{
boost::cmatch mat;
boost::regex reg( "\\%(.*?)\\%" );
char szStr[] = "Hello %world% regex %cpp%";
char *where = szStr;
while (regex_search(where, mat, reg))
{
cout << mat[1] << endl; // 0 for whole match, 1 for sub
where = (char*)mat[0].second;
}
}

parse a date-time string into a time_t value with spirit

I need to parse a date-time string like 2012-12-21 12:10:35 into a time_t value using boost::spirit. here is my code snippet:
tc_ = lexeme[int_[phx::ref(tm_.tm_year)=(_1-1900)]>>'-'
>>int_[phx::ref(tm_.tm_mon)=(_1-1)]>>'-'
>>int_[phx::ref(tm_.tm_mday)=_1]>>+space
>>int_[phx::ref(tm_.tm_hour)=_1]>>':'
>>int_[phx::ref(tm_.tm_min)=_1]>>':'
>>int_[phx::ref(tm_.tm_sec)=_1]] [_val = (long)mktime(&tm_)];
where tc_ is a qi rule of type: qi::rule<Iterator, long(), Skipper>, tm_ is a member variable of type struct tm.
The code compiles, but doesn't work. it seems that mktime() didn't get called at all. what am I doing wrong?
you can do it in c++ 11 vi the regex.
This will be portable and standard, if your compiler is recent enough.
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
std::regex txt_regex("([0-9]{4})[-]([0-9]{2})[-]([0-9]{2})[ ]([0-9]{2})([:])([0-9]{2})([:])([0-9]{2})");//
string strTmp;
strTmp="2010-12-15 15:25:46";
std::smatch match;
std::regex_search( strTmp, match, txt_regex );
if(regex_match(strTmp,txt_regex))
cout<<"Ok"<<endl;
else
{
cout<<"Invalid input"<<endl;
return 0;
}
if ( match.empty() )
{
std::cout << "...no more matches" << std::endl;
return 0;
}
for ( auto x : match )
{
std::cout << "found: " << x << std::endl;
}
string str = match.suffix().str();
cout <<str <<std::endl;
return 0;
}
With this you can display the different parts of the string to display and then fill the structure.
Hope it helps and open for comments as usual (if something is not clear or incomplete).

Regex and Boost. Not working on a simple regex

Below is my following code
#include <iostream>
#include <stdlib.h>
#include <boost/regex.hpp>
#include <string>
using namespace std;
using namespace boost;
int main() {
std::string s = "Hello my name is bob";
boost::regex re("name");
boost::cmatch matches;
try{
// if (boost::regex_match(s.begin(), s.end(), re))
if (boost::regex_match(s.c_str(), matches, re)){
cout << matches.size();
// matches[0] contains the original string. matches[n]
// contains a sub_match object for each matching
// subexpression
for (int i = 1; i < matches.size(); i++){
// sub_match::first and sub_match::second are iterators that
// refer to the first and one past the last chars of the
// matching subexpression
string match(matches[i].first, matches[i].second);
cout << "\tmatches[" << i << "] = " << match << endl;
}
}
else{
cout << "No Matches(" << matches.size() << ")\n";
}
}
catch (boost::regex_error& e){
cout << "Error: " << e.what() << "\n";
}
}
It always outputs with no Matches.
Im sure that regex should work.
I used this example
http://onlamp.com/pub/a/onlamp/2006/04/06/boostregex.html?page=3
from boost regex:
Important
Note that the result is true only if the expression matches the whole of the input sequence. If you want to search for an expression somewhere within the sequence then use regex_search. If you want to match a prefix of the character string then use regex_search with the flag match_continuous set.
Try boost::regex re("(.*)name(.*)"); if you want to use the expression with regex_match.