1

Kindly assist to make this code insert ob after every vowel in a string entered by the user in C++. The code is adding a double ob before only the first vowel. Thanks.

#include <iostream> #include <string> #include <algorithm> int main() { std::string s; std::cin >> s; std::string o ="ob"; for (char& v: s) { if (v == 'a' || v=='e' || v == 'i' || v == 'o' || v == 'u') s = s.insert(s.find(v),o); } std::cout << s << std::endl; } 
6
  • 1
    One problem is that you use s.find(v) : this will return the same location for every vowel of the string. Instead, you should iterate using iterators, and then you don't need s.find(v)because you have the iterator. Does it make sense? Commented Jul 2, 2018 at 23:59
  • 1
    Note that using iterators will also fix another issue in your code, which is that you modify the string while iterating on it using a range-based for loop (it is undefined behavouir, read this : stackoverflow.com/questions/17076672/…) Commented Jul 3, 2018 at 0:01
  • After inserting "ob", you'll need to advance the starting search position by the length of "ob". Commented Jul 3, 2018 at 0:02
  • 2
    There is no need to store the input string. Just use cin.get to get the next character and output it as is or replace it. Commented Jul 3, 2018 at 0:03
  • 2
    You should put the vowels into a string and search the vowel string for the character; this eliminates the long if statement. Commented Jul 3, 2018 at 0:04

3 Answers 3

1

I'm not going to mention the bugs mentioned in the comments.

I would avoid trying to manipulate the same string being searched.

Particularly with a range-based for loop which will use iterators. Iterators may be invalidated by altering the underlying collection, often coinciding with dynamic memory (re)allocation. I don't know how string iterators work off the top of my head, but I would guess that as you grow the string you're invalidating your iterators.

I would create a second string, scan the first string to determine how many vowels there are, and reserve that much space immediately. This requires iterating over the first string twice, but you should only invoke heap allocation at most once.

Then simply iterate over the first string and populate the second.

#include <iostream> #include <string> #include <algorithm> bool is_vowel(char c) { return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'; } int main() { const std::string vowel_postfix = "ob"; std::string in, out; std::cin >> in; auto vowel_count = std::count_if(in.begin(), in.end(), is_vowel); out.reserve(in.length() + vowel_count * 2); for (char c : in) { out.push_back(c); if (is_vowel(c)) out.insert(out.length(), vowel_postfix); } std::cout << out << std::endl; } 
Sign up to request clarification or add additional context in comments.

2 Comments

Now when I use 'push_front' it returns an error, is it because the reserved space is after the vowel. Because I've tried in latest c++ 11 compiler to rule out compiler problems.
No, std::vector::reserve does not prevent reallocation. Your error is hopefully because std::vector does not define a push_front member function. cppreference.com is a great resource for STL containers, and everything else C++.
0

I would do:

bool is_vowel(char cc) { const char c = tolower(cc); return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == ä || c == ö; } 

... and all other possible vowels with accent marks. Then:

int main() { std::string s; std::cin >> s; std::string ss; for (const char c: s) { ss += c; if (is_vowel(c)) ss += "ob"; } std::cout << ss << std::endl } 

Comments

0

Try something more like this instead. It uses indexes instead of iterators, and lets the std::string handle the searching and comparisons for you instead of you doing them manually:

#include <iostream> #include <string> int main() { const std::string vowels = "aAeEiIoOuU"; const std::string o = "ob"; std::string s; std::cin >> s; auto i = s.find_first_of(vowels); while (i != std::string::npos) { s.insert(++i, o); i = s.find_first_of(vowels, i + o.size()); } std::cout << s << std::endl; } 

Live Demo

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.