C++ Breaking up a string using multiple delimiters [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Split a string into words by multiple delimiters in C++
I'm currently trying to read a file where each line has a variation of tabs and spaces separating key attributes that need to be inserted into a binary tree.
My question is: How do I split a line up using multiple delimiters using only the STL? I've been trying to wrap my head around this for the good part of the day to no avail.
Any advice would be very much appreciated.

Use std::string::find_first_of
vector<string> bits;
size_t pos = 0;
size_t newpos;
while(pos != string::npos) {
newpos = str.find_first_of(" \t", pos);
bits.push_back(str.substr(pos, newpos-pos));
if(pos != string::npos)
pos++;
}

Using string::find_first_of() [1]:
int main ()
{
string str("Replace the vowels in this sentence by asterisks.");
size_t found;
found = str.find_first_of("aeiou");
while (found != string::npos) {
str[found]='*';
found=str.find_first_of("aeiou", found + 1);
}
cout << str << endl;
return 0;
}

Related

Is there any way I could further optimize this program? [duplicate]

This question already has answers here:
read words from line in C++
(2 answers)
Right way to split an std::string into a vector<string>
(12 answers)
Closed 12 days ago.
I've been trying to learn how to optimize C++ in the context of low latency trading systems, and am wondering if this implementation could be improved. I would appreciate any insight, either specific or general.
// Code to add each word in string to vector
int main() {
std::string originalText = "Hello World!";
std::vector<std::string> words;
words.reserve(originalText.length()); // unsure if this could be more accurate
std::size_t wStart = 0;
std::size_t pos = originalText.find(" ");
while(pos != std::string::npos) {
words.emplace_back(&originalText[wStart], pos - wStart);
wStart = pos + 1;
pos = originalText.find(" ", wStart);
}
words.emplace_back(&originalText[wStart], originalText.size() - wStart);
return 0;
}
You still allocate and copy std::strings from the input that's not needed. You can use string_views. This is no way near optimized for a trading system though.
I still use a vector and the will reallocate while it grows.
When optimizing code there is two things, keep thinking/researching if there is another algorithm (that usually brings the biggest performance gain). Then keep profiling to find your (real) bottlenecks.
Anyway here is a split function that can split without making string copies and can split on multiple characters (you can still optimize that to only split on spaces if that is the only delimiter)
std::vector<std::string_view> split_string(std::string_view string, std::string_view delimiters)
{
std::vector<std::string_view> substrings;
if(delimiters.size() == 0ul)
{
substrings.emplace_back(string);
return substrings;
}
auto start_pos = string.find_first_not_of(delimiters);
auto end_pos = start_pos;
auto max_length = string.length();
while(start_pos < max_length)
{
end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));
if(end_pos != start_pos)
{
substrings.emplace_back(&string[start_pos], end_pos - start_pos);
start_pos = string.find_first_not_of(delimiters, end_pos);
}
}
return substrings;
}

Recursion to count words and redundant words in a sentence in c++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Hi i'm trying to count the words in a sentence that is input by the user and this is the code i've written
void Count_Words( )
{
int count=0;
for (i = 0; inserted_text[i] != '\0';i++)
{
if (inserted_text[i] == ' ')
count++;
}
cout << "Word Count: " << count + 1;
}
I need to write this using recursion but i can't figure out how.
Also i need to count the redundant words in the sentence using recursion how do i do that?
I can't use mapping i need to use basic logic to do this. Is there anyway i can do this only with basic logic?
I agree with Hatted Rooster (this is not a good fit for recursion). I guess it serves a teaching purpose. So here is another option.
countWords() returns the number of words for the given substring until its end. To calculate the words for substring 0..n, we can calculate the words for substring 1..n first. And if character 0 is a space, add 1 to that.
int countWords(const char* str)
{
if(*str == '\0')
return 1; // last word
return countWords(str + 1) // how many words are in the remaining substring?
+ (*str == ' ' ? 1 : 0); // count if the beginning of the current substring is a space
}
int main()
{
std::string input = "test test test";
std::cout << countWords(input.c_str()); // 3
}
It doesn't really make sense to use recursion here but anyway, this would be one way to do it:
void Count_Words(int& i, const std::string& inserted_text, int& count)
{
if (inserted_text[i] == '\0')
{
++count; // last word
return;
}
if (inserted_text[i] == ' ')
++count;
Count_Words(++i, inserted_text, count); //recurse
}
int main()
{
std::string input = "test test test";
int i = 0;
int count = 0;
Count_Words(i, input, count);
std::cout << count; // 3
}
The thing to take away from this code is that references are a powerful tool to achieve correct recursion as seen in the function parameters.
As the other answer stated, this is really not a problem that should be resolved using recursion. What if there are thousands of words? That would exhaust the stack memory at some point.
In any event, here is one way to do this recursively:
#include <sstream>
#include <string>
#include <iostream>
void Count_Words(std::istringstream& strm, int& count)
{
std::string word;
if ( strm >> word ) // if there is a word, then increment the count
{
++count;
Count_Words(strm, count); // go to next word recursively
}
}
int Count_Words(std::string inserted_text)
{
// This is the setup for the recursive calls
std::istringstream strm(inserted_text);
int count = 0;
// start the recursion
Count_Words(strm, count);
return count;
}
int main()
{
std::string test = "This has four words";
std::cout << Count_Words(test);
}
Output:
4

How to replace all occurrances of a substring with a space in c++ string [duplicate]

This question already has answers here:
Replace substring with another substring C++
(18 answers)
Closed 7 years ago.
I have a function that removes all occurrences of a sub-string from a c++ string. But I want it to insert spaces before or after removing every sub-string. My Function if given below:
void removeSubstrs(string& s, string& p) {
string::size_type n = p.length();
for (string::size_type i = s.find(p);
i != string::npos;
i = s.find(p))
s.erase(i, n);
}
For example if I input "AZAZBLACKAZAZBERRYAZ", I want the output "BLACK BERRY"....
if what you want is something like this:
assume "-" as space
input: "AZAZBLACKAZAZBERRYAZ" and "AZ"
output: "--BLACK--BERRY-"
then, this may help you:
void removeSubstrs(string& s, string& p) {
string::size_type n = p.length();
for (string::size_type i = s.find(p); i != string::npos; i = s.find(p))
{
s.replace(i, n, 1, ' ');
//OR
//s.erase(i, n);
//s.inset(i, ' '); //Add this line
}
}

need help on splitting a string in c++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Splitting a string in C++
i need a suggestion on how to take one string of text and split it up based on a certain character, in this case "," without the use of any outside libraries
the lines of text are:
Amadeus,Drama,160 Mins.,1984,14.83
As Good As It Gets,Drama,139 Mins.,1998,11.3
Batman,Action,126 Mins.,1989,10.15
Billy Elliot,Drama,111 Mins.,2001,10.23
BR,SF,117,1982,11.98
Shadowlands,Drama,133 Mins.,1993,9.89
Shrek,Animation,93 Mins,2001,15.99
Snatch,Action,103 Mins,2001,20.67
The Lord of the Rings,Fantasy,178 Mins,2001,25.87
If you don't want to resort to other libraries (Boost.Tokenizer is a good choice IMO), here is some simple code for doing that:
#include <string>
#include <vector>
using namespace std;
vector<string> tokenize(string const& s, string const& separator)
{
size_t start = 0;
size_t pos = s.find(separator);
vector<string> v;
while (pos != string::npos)
{
string sub = s.substr(start, pos - start);
v.push_back(sub);
start = pos + 1;
pos = s.find(separator, start);
}
string sub = s.substr(start, pos - start);
v.push_back(sub);
return v;
}
int main()
{
string s = "asfa,adf,daf,c";
vector<string> v = tokenize(s, ",");
// Do what you want with v...
return 0;
}
You could just find the indices of the commas and store them in a vector, then use string::substr (http://www.cplusplus.com/reference/string/string/substr/) to get the substrings between those indices.

Need help with my recursive program that reverses the input [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Write a recursive function that reverses the input
Recently, I've been reading the book C++ For Everyone and I've been having trouble putting together a recursive function (Confusing to think about...)
The question was: Write a recursive function string reverse(string str) that returns the reverse of str
This is what I have so far:
string reverse(string str)
{
string word = "";
if (str.length() <= 1)
{
return str;
}
else
{
string str_copy = str;
int n = str_copy.length() - 1;
string last_letter = str_copy.substr(n, 1);
str_copy = str_copy.substr(0, n);
word += reverse(str_copy);
return last_letter;
}
return word;
}
My problems now is:
If I enter wolf, it returns f
If I change return last_letter to return word, I get w
If I change to return str_copy, I get wol
You need to return the combination of the the last character (last_letter) and the reversal of the rest of the string, but you don't do that in any of your attempts. You only ever return one part or the other.
string reverse(string str)
{
int len = str.length();
if (len <= 1)
{
return str;
}
else
{
return str.substr(len-1, 1) + reverse( str.substr(0, len-1) );
}
}
This would do the work:
Delete return last_letter;
Change `
word += reverse(str_copy);
to
word = last_letter+reverse(str_copy);
I'll leave the thinking to you!
Best.