Replace 8 characters after finding 3 characters from a string - c++

Is it possible in C++ to replace 8 characters after finding 3 characters from a string
I tried below
Input:
txtvar = "This is for Testing Purpose line";
Expected should be output
txtvar = "This is for Testing XXXXXX line";
I tried below
std::string::size_type pos;
while (( pos = txtvar. find ("Testing")) ! = std::string::npos) {
txtvar.replace(pos, 9, XXXX);
}
After finding the Testing keyword next to that 9 characters should be replaced to "XXXXXXX"
Please help me on this

yes you can, the string class have methods for that, just look in the documentation for it:
//https://en.cppreference.com/w/cpp/string/basic_string
std::string txtvar {"This is for Testing Purpose line"};
//https://en.cppreference.com/w/cpp/string/basic_string/find
auto index {txtvar.find("Purpose")};
std::string t{"XXXXXXX"};
txtvar.replace(index, 7, t);
std::cout << txtvar << std::endl;

Related

Why is string.find_first_of behaving this way?

I am trying to make a (assembly) parser which uses a string as a guide for how to cut the text to get the tokens I want.
string s = "$t4,";
string guide = "$!,$!,$!";
int i = 1;
string test =s.substr(0, s.find_first_of(" ,.\t"+to_string(guide[i+1]) ));
cout << test << "\n";
if s = "$t4" then test = "$t"
what I am expecting it to do is test to be "$t4", this works for every other $tX except for specifically the number 4 even though it's not in the (" ,.\t"+to_string(guide[i+1])) string
s.find_first_of(" ,.\t" + std::to_string(guide[i + 1]))
Assuming ASCII, that string will be:
,.\t44
44 is the ASCII value of the , in guide[i + 1].
The first character in "$t4," that it'll find is 4 at position 2, and you then create a substring from 0 and length 2, that is $t.

How to name regex group matches in C++ the way python does (?P<name_of_regex>(.*))

I have a string in my program that contains certain values for parameters. I need to extract the values from the parameters using regex.
The regex looks like this:
std::smatch param;
std::string str = "--name=AName --age=AnAge --gender=AGender"
if (std::regex_match(str, param, std::regex(".*--name=(\\w+) .*--age=(\\d+) .*--gender=(\\w+) .*")))
{
//if it finds the order of the regex will come here and the values for each will be stored in param[1-3]
}
The problem is the order of the params can come in different orders, for example:
std::string str = "--gender=AGender --name=AName --age=AnAge"
std::string str = "--age=AnAge --gender=AGender --name=AName"
std::string str = "--name=AName --gender=AGender --age=AnAge "
Is there a way to express in a single regex expression to be able to capture values despite of the order instead of doing on regex per parameter I want to find? If so how can I access such value? In python is possible to add an <id> before the desired group to then later access it using same identifier. In my example code I do that using smatch type variable but the access to it depends on the order that the string has and I cannot rely on that.
Use this regex:
"^(?=.*--name=(\\w+))(?=.*--age=(\\d+))(?=.*--gender=(\\w+)).+"
The one problem you'll run into is the fact that params won't be able to determine which item belongs to which parameter.
The way I would solve this problem would be to use std::string::find.
For example:
std::string str = "--name=AName --age=AnAge --gender=AGender";
size_t namePos = str.find("--name=");
size_t agePos = str.find("--age=");
size_t genderPos = str.find("--gender=");
std::string name = "";
std::string gender = "";
std::string age = "";
if(namePos != std::string::npos)
{
// Add 7 to namePos since the size of "--name=" is 7.
// Assuming that the delimiter of the name is whitespace so find the first
// whitespace after --name=
name = str.substr(namePos + 7, str.find_first_of(" \n\r", namePos + 7) - (namePos + 7));
}
if(agePos != std::string::npos)
{
// Add 6 to agePos since the size of "--age=" is 6.
// Assuming that the delimiter of the age is whitepace so find the first
// whitespace after --age=
age = str.substr(agePos + 6, str.find_first_of(" \n\r", agePos + 6) - (agePos + 6));
}
if(genderPos != std::string::npos)
{
// Add 9 to genderPos since the size of "--gender=" is 9.
// Assuming that the delimiter of the gender is whitespace so find the first
// whitespace after --gender=
gender = str.substr(genderPos + 9, str.find_first_of(" \n\r", genderPos + 9) - (genderPos + 9));
std::cout << name << " " << gender << " " << age << std::endl;
}
Output:
AName AGender AnAge
There are better tools to parse commandlines, but if you really want to use regex, you will find that Boost::Regex makes this much easier than the std::regex.
In particular, it supports named groups (see e.g. Boost Regular Expression: Getting the Named Group) which is the feature you request in your question title.
You can combine that with BOOST_REGEX_MATCH_EXTRA to keep all matches for all named groups (by default, only the last match for each capture group is accessible after the search.)
Then you can just make a big disjunction ((?<group1>...)|(?<group2>...)|...) in your regex for all the groups you may encounter, and you will be able to get all values out regardless of their order.

How to get a substring from a found string to a character in C++?

For example I have a string:
int random_int = 123; // let's pretend this integer could have various values!!
std::string str = "part1 Hello : part2 " + std::to_string(random_int) + " : part3 World ";
All parts are divided by the characters :
Let's say I want to find a substring from "part2" to the next character :, which would return part2 123 in this case.
I know how to find the pos of "part2" by str.find("part2"), but I don't know how to determine the length to the next : from that "part2", because the length can be of various length.
For example, I know that part3 substring could be extracted with str.substr(str.find("part3"));, but only because it's at the end...
So, is there a subtle way to get the substring part2 123 from that string?

C++ RegExp and placeholders

I'm on C++11 MSVC2013, I need to extract a number from a file name, for example:
string filename = "s 027.wav";
If I were writing code in Perl, Java or Basic, I would use a regular expression and something like this would do the trick in Perl5:
filename ~= /(\d+)/g;
and I would have the number "027" in placeholder variable $1.
Can I do this in C++ as well? Or can you suggest a different method to extract the number 027 from that string? Also, I should convert the resulting numerical string into an integral scalar, I think atoi() is what I need, right?
You can do this in C++, as of C++11 with the collection of classes found in regex. It's pretty similar to other regular expressions you've used in other languages. Here's a no-frills example of how you might search for the number in the filename you posted:
const std::string filename = "s 027.wav";
std::regex re = std::regex("[0-9]+");
std::smatch matches;
if (std::regex_search(filename, matches, re)) {
std::cout << matches.size() << " matches." << std::endl;
for (auto &match : matches) {
std::cout << match << std::endl;
}
}
As far as converting 027 into a number, you could use atoi (from cstdlib) like you mentioned, but this will store the value 27, not 027. If you want to keep the 0 prefix, I believe you will need to keep this as a string. match above is a sub_match so, extract a string and convert to a const char* for atoi:
int value = atoi(match.str().c_str());
Ok, I solved using std::regex which for some reason I couldn't get to work properly when trying to modify the examples I found around the web. It was simpler than I thought. This is the code I wrote:
#include <regex>
#include <string>
string FileName = "s 027.wav";
// The search object
smatch m;
// The regexp /\d+/ works in Perl and Java but for some reason didn't work here.
// With this other variation I look for exactly a string of 1 to 3 characters
// containing only numbers from 0 to 9
regex re("[0-9]{1,3}");
// Do the search
regex_search (FileName, m, re);
// 'm' is actually an array where every index contains a match
// (equally to $1, $2, $2, etc. in Perl)
string sMidiNoteNum = m[0];
// This casts the string to an integer number
int MidiNote = atoi(sMidiNoteNum.c_str());
Here is an example using Boost, substitute the proper namespace and it should work.
typedef std::string::const_iterator SITR;
SITR start = str.begin();
SITR end = str.end();
boost::regex NumRx("\\d+");
boost::smatch m;
while ( boost::regex_search ( start, end, m, NumRx ) )
{
int val = atoi( m[0].str().c_str() )
start = m[0].second;
}

read and get value btw whitespace and another character

how to get the 1st name. here is the sample of data.. first name here is Owen, Florencio. I need to read and get the value frm whitespace to ; ??
Owen;Grzegorek;Howard Miller Co;15410 Minnetonka Industrial Rd;Minnetonka;Hennepin;MN;55345;952-939-2973;952-939-4663;owen#grzegorek.com;http://www.owengrzegorek.com
Florencio;Hollberg;Hellenic Museum & Cultural Ctr;2211 Kenmere Ave;Burbank;Los
Use string::find to find the first instance of semi-colon, and do a string::substr.
string str = "Florencio;Hollberg;Hellenic Museum & Cultural Ctr;2211 Kenmere Ave;Burbank;Los";
std::size_t pos = str.find(";");
str = str.substr(0, pos);
cout << str << endl;
Output:
Florencio
Of course, you have to modify the code to suit your needs.