std::string replace not retaining the end? - c++

I want to replace a string within a string with *, using this code to replace everything between he and ld in helloworld:
#include <string>
#include <iostream>
int main()
{
const std::string msg = "helloworld";
const std::string from = "he";
const std::string to = "ld";
std::string s = msg;
std::size_t startpos = s.find(from);
std::size_t endpos = s.find(to);
unsigned int l = endpos-startpos-2;
s.replace(startpos+2, endpos, l, '*');
std::cout << s;
}
The output I got is He*****, but I wanted and expected He*****ld.
What did I get wrong?

You are replacing all the characters after index two. Count the indexes and replace only the range you want.
Try this:
#include <iostream>
#include <string>
int main ()
{
//this one for replace
string str="Hello World";
// replace string added to this one
string str2=str;
// You can use string position.
str2.replace(2,6,"******");
cout << str2 << '\n';
return 0;
}
First parameter for starting character
Second parameter for ending character
And Third parameter for string
There is a several ways you can do this. This is a one simple method.
UPDATE(After added your code):
Change:
unsigned int l=endpos-startpos-2;
s.replace(startpos+2,endpos,l,'*');
To:
unsigned int l=endpos-3;
s.replace(startpos+2,l,l,'*');
Because your endpos store position of character d. You need to substract 3 by endpos then l variable value become 7. After that in replace() change second parameter to l.
read more about replace().

Related

Replacing even digits in string with given string

I know how to replace all occurrences of a character with another character in string (How to replace all occurrences of a character in string?)
But what if I want to replace all even numbers in string with given string? I am confused between replace, replace_if and member replace/find functions of basic_string class, because signature of functions require old_val and new_val to be same type. But old_val is char, and new_val is string. Is there any effective way to do this, not using multiple loops?
e.g. if the input string is
"asjkdn3vhsjdvcn2asjnbd2vd"
and the replacement text is
"whatever"
, the result should be
"asjkdn3vhsjdvcnwhateverasjnbdwhatevervd"
You can use std::string::replace() to replace a character with a string. A working example is below:
#include <string>
#include <algorithm>
#include <iostream>
#include <string_view>
void replace_even_with_string(std::string &inout)
{
auto is_even = [](char ch)
{
return std::isdigit(static_cast<unsigned char>(ch)) && ((ch - '0') % 2) == 0;
};
std::string_view replacement_str = "whatever";
auto top = std::find_if(inout.begin(), inout.end(), is_even) - inout.begin();
for (std::string::size_type pos{};
(pos = (std::find_if(inout.begin() + pos, inout.end(), is_even) - inout.begin())) < inout.length();
pos += replacement_str.length() - 1)
{
inout.replace(pos, 1, replacement_str.data());
}
}
int main()
{
std::string test = "asjkdn3vhsjdvcn2asjnbd2vd";
std::cout << test << std::endl;
replace_even_with_string(test);
std::cout << test << std::endl;
}
While using a regex can add unnecessary complexity in many cases, here it's actually simple to read and write:
std::string str = /* ... some text ... */
std::regex r{R"~~([02468])~~"}; // this will match even digits
str = std::regex_replace(str, r, "rep"); // replace with the needed text
// and overwrite string
Here's a demo.

Is this a function or variable definition in c++ code?

I am reading a piece of c++ code in which ids, curi and len are integer, content are string. I don't understand what's match_word() part. Is it a function or variable? I can't find its definition in all header files.
if(-1!=ids)
{
len = ids - curi;
string match_word(content, curi, len);
bool rejudge = false;
...
}
From std::string documentation
string match_word(content, curi, len);
This is/uses a substring constructor which
Copies the portion of content that begins at the character position curi and spans len characters (or until the end of content, if either content is too short or if len is string::npos).
So for example
std::string s = "Hello World";
string match_word(s, 2, 7);
std::cout<<match_word<<std::endl; //prints llo Wor
The above will print llo Wor
Now coming to your question:
Is this a function or variable definition in c++ code?
Basically this is a variable definition using the substring constructor. So in your case match_word is a variable of type std::string.
string match_word(content, curi, len);
match_word is a string. This is a declaration. Looks like you want to call this constructor:
string (const string& str, size_t pos, size_t len = npos);
Here is an example from cplusplus
#include <iostream>
#include <string>
int main()
{
std::string s0 ("Initial string");
std::string s3 (s0, 8, 3);
std::cout << s3;
}
This will print:
str

Extracting all words separated by non-alphabetical characters

Given a string such as:
std::string word = "Hello World!it's#.-/sunday";
I want to extract all the words which are separated by non-alphabetical letters stored in a container like a vector, so for this case it would be:
Hello, World, it, s, sunday
My initial try was to use isalpha() along with an index count to substr() accordingly like so:
std::string word = "Hello World!it's#.-/sunday";
int count = 0, index = 0;
std::string temp;
for (; count < word.length();count++){
if (!isalpha(word[count])){
temp = word.substr(index,count);
index = count;
}
}
But this does not work as I thought it would as the index does not update fast enough resulting in words mixed with non-alphabetical characters. Is there perhaps a function or a better way to extract said words?
You can try the following code. It constructs the words char by char.
#include <string>
#include <iostream>
#include <vector>
int main()
{
std::string phrase = "Hello World!it's#.-/sunday";
std::vector<std::string> words;
std::string tmp;
for (const char &c:phrase)
{
if (isalpha(c))
{
tmp.push_back(c);
}
else
{
words.push_back(tmp);
tmp = "";
}
}
if (!tmp.empty())
{
words.push_back(tmp);
}
for (const auto w : words)
{
std::cout << w << std::endl;
}
return 0;
}
one easy way is that replace all the non-alphabetical char to space than
split around space.

Is there a way to erase two given values with loop?

How do I erase if string sdl1 holds two values like "37". Considering that are two different values 3 and 7. Do I need some sort of list or only loop? Thank you
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <vector>
#include <conio.h>
#include <sstream>
#include <stdio.h>
#include <iterator>
using namespace std;
void eraseAllSubStr(std::string & mainStr, const std::string & toErase)
{
size_t pos = std::string::npos;
while ((pos = mainStr.find(toErase)) != std::string::npos)
{
mainStr.erase(pos, toErase.length());
}
}
int main()
{
std::string str = "123456789";
//Let's Say I want to delete 5 and 8 and string sdl1 = "58".
string sdl1 = "5";
eraseAllSubStr(str, sdl1);
std::cout << str << std::endl;
return 0;
}
The output of the minimal reprod. example:
12346789
5 was erased.
But I would like to erase two values like 5 and 8 where string sdl1 = "58"
If I understand your actual question:
"What If I want to remove "58" like 5 and 8?"
and you want to provide std::string sdl1 = "58"; and have both 5 and 8 removed from std::string str = "123456789"; in a single loop, then you can simply use std::basic_string::find_first_of to locate the position of either 5 or 8 and then use std::basic_string::erase to remove the character. The only constraint is you only want to attempt the removal of characters while str.find_first_of (sdl1) != std::basic::npos).
A for loop is tailor made for the implementation, e.g.:
std::string str = "123456789";
//Let's Say I want to delete 5 and 8 and string sdl1 = "58".
std::string sdl1 = "58";
for (size_t pos = str.find_first_of (sdl1);
pos != std::string::npos;
pos = str.find_first_of (sdl1))
str.erase (pos, 1);
Putting it altogether in a short example, you could do:
#include <iostream>
#include <string>
int main (void) {
std::string str = "123456789";
//Let's Say I want to delete 5 and 8 and string sdl1 = "58".
std::string sdl1 = "58";
for (size_t pos = str.find_first_of (sdl1);
pos != std::string::npos;
pos = str.find_first_of (sdl1))
str.erase (pos, 1);
std::cout << "str: " << str << '\n';
}
Example Use/Output
$ ./bin/erasechars
str: 1234679
Erase as substring
If you want to erase as a substring, the code you wrote is solution to your problem. Run again your code by putting
std::string str = "123456789";
string sdl1 = "56";
You will get your ouput 1234789.
Once again set the inputs
std::string str = "12345678956123";
string sdl1 = "56";
You will get your output 1234789123
So you've successfully removed all the occurrences of 56 from your main string str.
The way std::string::find() works, it searches the string for the first occurrence of the sequence specified by its arguments. So it will work same for a substring as it works for a single character.
Similarly std::string::erase() erases a part of the string, reducing its length. All you need is to specify the starting index and the length of the substring (i.e. string ::erase (size_type idx, size_type len )) you would like to remove.
So, your code will work for removing all the occurrences of a given substring.
Erase as character
If you want to remove one or more characters from a string like you mentioned 5 and 8. You can use your code with simple modification to your eraseAllSubStr function.
void eraseAllSubStr(std::string & mainStr, const std::string & toErase)
{
size_t pos = std::string::npos;
// erase all the occurrences of the characters that are
// given through toErase string
// and obviously the length of a char is 1
for( int id = 0; id < toErase.size(); id++)
{
while ((pos = mainStr.find(toErase[id])) != std::string::npos)
{
mainStr.erase(pos,1);
}
}
}

A function to find how many times string 1 contains string 2 c++

I want to check how many times my first string contains the second string.
I read about it in the internet, and i found a function name std::find, i tried to use it and i failed...
std::string Str1 = "Hello Hello";
std::string Str2 = "ll";
Now what?
I tried to use
std::count
as well but i found out that its work just on a letters.
counter = std::count(Str1.begin(), Str2.end(), Str2); // dident work
Help??
Edit:
Thats what i am trying to do:
unsigned int Nucleus::get_num_of_codon_appearances(const std::string& codon) const
{
unsigned int counter = 0;
counter = std::count(this->_DNA_strand.begin(), this->_DNA_strand.end(), codon);
return counter;
}
You could do this quite easily with std::regex if you are using c++11 or greater.
Something like,
#include <regex>
#include <iterator>
#include <iostream>
#include <string>
using namespace std;
int main()
{
const string str = "one two hello three four hello five hello";
regex re("hello");
cout << "Number of hellos : " <<
distance(sregex_iterator(str.begin(),str.end(), re),sregex_iterator());
}
Demo
You can use std::string::find.
#include <string>
using namespace std;
size_t count (const string & src, const string & str) {
size_t cnt = 0, fnd = 0;
while (fnd = (src.find(str, fnd)) != string::npos) {
cnt++; fnd++;
}
return cnt;
}
...
count("Hello, world!", "ll");
As paxbun stated the string::find method is used there and that is a built-in function of the string class.
Reference of the .find() Method string::find ~ C++ Reference
As another approach including a class corresponding to your code above:
#include <iostream>
#include <string>
using namespace std;
//class declaration
class Nucleus{
private:
string _DNA_strand{"ABCADDASDASABCAFGDACCACABCDA"};
public:
const string get_codon(){return _DNA_strand;} //accessor of private variable
unsigned int get_num_of_codon_appearances(const string& _DNA_strand, const string& ) const;
};
//Function to return the number of times a string is found within another string.
unsigned int Nucleus::get_num_of_codon_appearances(const string& codon, const string& c) const
{
unsigned int count = 0; //sets count
size_t counter = 0; //sets counter
while (counter != string::npos) // if counter does not equal string no position
{
size_t i = counter + c.length(); // sets i to counter + length of searched for object
counter = codon.find(c, i); // .find() method
count++;
}
return count;
}
//Main Function
int main()
{
Nucleus temp; //sets the object temp of the class Nucleus
const string codon = temp.get_codon();
const string c = "ABC";
cout << "The Number of times " << c << " is found in "
<< temp.get_codon() << " is: " << temp.get_num_of_codon_appearances(codon, c) << endl;
return 0;
}
Example output:
The Number of times ABC is found in ABCADDASDASABCAFGDACCACABCDA is: 3
DEMO