I have a string
"server ('m1.labs.teradata.com') username ('user5') password ('user)5') dbname ('default') "
I want to separate it as
string1 = server
string2 = 'm1.labs.teradata.com'
and password has a ')' in it.
Can anyone help me out in how to use it using regex.??
I only tested the regex to extract your items, but I think the following code snippet will work.
#include <regex>
#include <iostream>
int main()
{
const std::string s = "server ('m1.labs.teradata.com') username ('user5') password ('user)5') dbname ('default') ";
std::regex rgx("server\s+\(\'[^']+\'\)\s+username\s+(\'[^']+\'\)\s+password\s+\(\'[^']*\'\)\s+dbname\s+\(\'[^']+\'\)");
std::smatch match;
if (std::regex_search(s.begin(), s.end(), match, rgx)) {
std::cout << "match: " << match[1] << '\n';
std::cout << "match: " << match[2] << '\n';
....
}
}
In the following example you will iterate over all matches in the regular expression.
#include <iostream>
#include <string>
#include <regex>
int main()
{
std::string str("server ('m1.labs.teradata.com') username ('user5') password ('user)5') dbname ('default') ");
std::regex r("server\s+\(\'[^']+\'\)\s+username\s+(\'[^']+\'\)\s+password\s+\(\'[^']*\'\)\s+dbname\s+\(\'[^']+\'\)");
std::smatch m;
std::regex_search(str, m, r);
for(auto v: m) std::cout << v << std::endl; // Here you will iterate over all matches
}
For your other querstion with passing string to a function:
void print(const std::string& input)
{
cout << input << endl;
}
or a const char*:
void print(const char* input)
{
cout << input << endl;
}
Both ways allow you to call it like this:
print("Hello World!\n"); // A temporary is made
std::string someString = //...
print(someString); // No temporary is made
The second version does require c_str() to be called for std::strings:
print("Hello World!\n"); // No temporary is made
std::string someString = //...
print(someString.c_str()); // No temporary is made
Related
I have a string in C++ that looks like this:
string word = "substring"
I want to read through the word string using a for loop, and each time an s is found, print out "S found!". The end result should be:
S found!
S found!
Maybe you could utilize toupper:
#include <iostream>
#include <string>
void FindCharInString(const std::string &str, const char &search_ch) {
const char search_ch_upper = toupper(search_ch, std::locale());
for (const char &ch : str) {
if (toupper(ch, std::locale()) == search_ch_upper) {
std::cout << search_ch_upper << " found!\n";
}
}
}
int main() {
std::string word = "substring";
std::cout << word << '\n';
FindCharInString(word, 's');
return 0;
}
Output:
substring
S found!
S found!
Extraction Function
string extractStr(string str, string regExpStr) {
regex regexp(regExpStr);
smatch m;
regex_search(str, m, regexp);
string result = "";
for (string x : m)
result = result + x;
return result;
}
The Main Code
#include <iostream>
#include <regex>
using namespace std;
string extractStr(string, string);
int main(void) {
string test = "(1+1)*(n+n)";
cout << extractStr(test, "n\\+n") << endl;
cout << extractStr(test, "(\\d)\\+\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]\\1") << endl;
cout << extractStr(test, "([a-zA-Z])[+-/*]([a-zA-Z])") << endl;
return 0;
}
The Output
String = (1+1)*(n+n)
n\+n = n+n
(\d)\+\1 = 1+11
([a-zA-Z])[+-/*]\1 = n+nn
([a-zA-Z])[+-/*]([a-zA-Z]) = n+nnn
If anyone could kindly point the error I've done or point me to a similar question in SO that I've missed while searching, it would be greatly appreciated.
Regexes in C++ don't work quite like "normal" regexes. Specialy when you are looking for multiple groups later. I also have some C++ tips in here (constness and references).
#include <cassert>
#include <iostream>
#include <sstream>
#include <regex>
#include <string>
// using namespace std; don't do this!
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
// pass strings by const reference
// 1. const, you promise not to change them in this function
// 2. by reference, you avoid making copies
std::string extractStr(const std::string& str, const std::string& regExpStr)
{
std::regex regexp(regExpStr);
std::smatch m;
std::ostringstream os; // streams are more efficient for building up strings
auto begin = str.cbegin();
bool comma = false;
// C++ matches regexes in parts so work you need to loop
while (std::regex_search(begin, str.end(), m, regexp))
{
if (comma) os << ", ";
os << m[0];
comma = true;
begin = m.suffix().first;
}
return os.str();
}
// small helper function to produce nicer output for your tests.
void test(const std::string& input, const std::string& regex, const std::string& expected)
{
auto output = extractStr(input, regex);
if (output == expected)
{
std::cout << "test succeeded : output = " << output << "\n";
}
else
{
std::cout << "test failed : output = " << output << ", expected : " << expected << "\n";
}
}
int main(void)
{
std::string input = "(1+1)*(n+n)";
test(input, "n\\+n", "n+n");
test(input, "(\\d)\\+\\1", "1+1");
test(input, "([a-zA-Z])[+-/*]\\1", "n+n");
return 0;
}
here is my code, I get messy code if I extract boost::regex_search into function #match
boost::smatch match() {
std::string s = "foobar";
std::string re_s = "f(oo)(b)ar";
boost::regex re(re_s);
boost::smatch what;
if (boost::regex_search(s, what, re)) {
return what;
}
}
int main(int argc, char **argv) {
boost::smatch what = match();
std::cout << what.size() << std::endl;
std::cout << what[0] << std::endl;
std::cout << what[1] << std::endl;
std::cout << what[2] << std::endl;
return (0);
};
the output is:
3
\000\000\000\000\000
\000\000
\000
how to make what[n] return real string
boost::smatch contains string::iterator values for tracking the matches internally. You are matching against a string object that is on the stack. When the match() function returns, that string is destructed and the iterators become invalid. Try moving the string s to the main() function and passing it into match() as a reference.
In Boost, the operator[](int index) of smatch returns a const_reference which is a typedef for sub_match<BidirectionalIterator>. sub_match<BidirectionalIterator> has a cast operator to a string, but you must cast the match to a string, otherwise it calls the operator<<(basic_ostream,sub_match) function which returns the distance from the last match. If you cast the what[0] to a std::string, it will print out. (I tested it on my machine.)
This is the code I used:
#include <iostream>
#include <string>
#include <boost/regex.hpp>
boost::smatch match() {
std::string s = "foobar";
std::string re_s = "f(oo)(b)ar";
boost::regex re(re_s);
boost::smatch what;
if (boost::regex_search(s, what, re)) {
return what;
}
}
int main(int argc, char **argv) {
boost::smatch what = match();
std::cout << what.size() << std::endl;
std::string what0 = what[0];
std::cout << what0 << std::endl;
std::cout << what[1] << std::endl;
std::cout << what[2] << std::endl;
return (0);
};
If only wanna use regex, use std::regex_search instead of boost::regex_search is good, following work well.
#include "boost/regex.hpp"
#include "iostream"
#include "regex"
std::smatch match() {
std::string s = "foobar";
std::string re_s = "f(oo)(b)ar";
std::regex re(re_s);
std::smatch what;
if (std::regex_search(s, what, re)) {
return what;
}
}
int main(int argc, char **argv) {
std::smatch what = match();
std::cout << what.size() << std::endl;
std::cout << what[0].str() << std::endl;
std::cout << what[1].str() << std::endl;
std::cout << what[2].str() << std::endl;
return (0);
};
It is supposed to match "abababab" since "ab" is repeated more than two times consecutively but the code isn't printing any output.
Is there some other trick in using regex in C++.
I tried with other languages and it works just fine.
#include<bits/stdc++.h>
int main(){
std::string s ("xaxababababaxax");
std::smatch m;
std::regex e ("(.+)\1\1+");
while (std::regex_search (s,m,e)) {
for (auto x:m) std::cout << x << " ";
std::cout << std::endl;
s = m.suffix().str();
}
return 0;
}
Your problem is your backslashes are escaping the '1''s in your string. You need to inform std::regex to treat them as '\' 's. You can do this by using a raw string R"((.+)\1\1+)", or by escaping the slashes, as shown here:
#include <regex>
#include <string>
#include <iostream>
int main(){
std::string s ("xaxababababaxax");
std::smatch m;
std::regex e ("(.+)\\1\\1+");
while (std::regex_search (s,m,e)) {
for (auto x:m) std::cout << x << " ";
std::cout << std::endl;
s = m.suffix().str();
}
return 0;
}
Which produces the output
abababab ab
I would like to pass the variable from a function to the main scope which I'm calling, I'm trying to do like I use to do in C but it returns nothing.
I want to be able to output and deal with it after the return of the function
#include "StdAfx.h"
#include <regex>
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
std::tr1::match_results<std::string::const_iterator> match(std::string& regex, const std::string& ip,std::tr1::match_results<std::string::const_iterator> res)
{
const std::tr1::regex pattern(regex.c_str());
bool valid = std::tr1::regex_match(ip, res, pattern);
std::cout << ip << " \t: " << (valid ? "valid" : "invalid") << std::endl;
cout << "FIRST RES FOUND: " << res[1] << endl;
return res;
}
int main()
{
string regex = "(\\d{1,3}):(\\d{1,3}):(\\d{1,3}):(\\d{1,3})";
string ip = "49:22:33:444";
std::tr1::match_results<std::string::const_iterator> res;
match(regex,ip.c_str(), res);
cout << "Result >" << res[1] << "< " << endl;
_getch(); return 0;
}
When I compile and run, The output is: "FIRST RES FOUND: 49
Result ><"
It's probably a really simple solution but what do I have to do to set it for my main can read it correctly as in: "Result >49<"
Thanks in advance. :)
Option 1: Use references:
void match(string& regex, const string& ip, tr1::match_results<string::const_iterator> & res)
{
const tr1::regex pattern(regex.c_str());
bool valid = tr1::regex_match(ip, res, pattern);
cout << ip << " \t: " << (valid ? "valid" : "invalid") << endl;
cout << "FIRST RES FOUND: " << res[1] << endl;
}
Option 2: Return the result by value and store it:
tr1::match_results<string::const_iterator> match(string& regex, const string& ip)
{
tr1::match_results<string::const_iterator> res;
// ...
return res;
}
int main()
{
// ...
tr1::match_results<string::const_iterator> res = match(regex, ip);
}
On a separate note, there should be absolutely no need for all the c_str() calls, as <regex> has a perfectly functional std::string interface. Check the documentation for details, you just have to get a couple of typenames right.
Edit: Here are some basic examples on using std::string. There are equivalent constructions for std::wstring, char* and wchar_t*, but std::strings should be the most useful one.
Since <regex> support is still patchy, you should consider the TR1 and Boost alternatives, too; I provide all three and you can pick one:
namespace ns = std; // for <regex>
namespace ns = std::tr1; // for <tr1/regex>
namespace ns = boost; // for <boost/regex.hpp>
ns::regex r("");
ns::smatch rxres; // 's' for 'string'
std::string data = argv[1]; // the data to be matched
// Fun #1: Search once
if (!ns::regex_search(data, rxres, r))
{
std::cout << "No match." << std::endl;
return 0;
}
// Fun #2: Iterate over all matches
ns::sregex_iterator rt(data.begin(), data.end(), r), rend;
for ( ; rt != rend; ++rt)
{
// *rt is the entire match object
for (auto it = rt->begin(), end = rt->end(); it != end; ++it)
{
// *it is the current capture group; the first one is the entire match
std::cout << " Match[" << std::distance(rt->begin(), it) << "]: " << *it << ", length " << it->length() << std::endl;
}
}
Don't forget to handle exceptions of type ns::regex_error.
Pass in res by reference instead of by value. In other words, declare the parameter res as a reference instead of a value, i.e., type &res, not type res.