2

I have got a small problem. I want to capitalize on doubled letters in a string. I managed to compile a program, but not successfully.

#include <iostream>
#include <cctype>
#include <string>

std::string::iterator function(
   std::string::const_iterator a, 
   std::string::const_iterator b,
   std::string::const_iterator e)
{
   for (; a < b; a++) 
   {
      if (*a == *(a + 1)) 
      {
         toupper(*a);
         toupper(*(a + 1));
      }
   }
}

int main()
{
   std::string in = "peppermint 1001 bubbles balloon gum", out(100, '*');
   auto e = function(in.cbegin(), in.cend(), out.begin());

   int n = e - out.begin();
   std::string s = out.substr(0, n);
   bool b = (s == "pePPermint 1001 buBBles baLLOOn gum");
   std::cout << std::boolalpha << b << std::endl;
}

What do I do wrong?

JeJo
  • 30,635
  • 6
  • 49
  • 88
AmateurOne
  • 23
  • 2

3 Answers3

5

You have a couple of issues there.

Firstly, your function promised to return std::string::iterator

std::string::iterator function(....)
{
  //... return statement is missing here!
}

and you are not keeping the promise. This will leads to undefined behaviour. For example, in your case, it just compiles and does not give the output.

In order to get a defined behaviour, you should return from the function

std::string::iterator function(...)
{
   // ... code
   return {}; // return appropriately iterator of std::string
}

Secondly, you want to modify the characters of the string, which requires a modifiable iterator rather than std::string::const_iterator.

Then in the loop, you need to alter the capitalized charector by reassigning to it. For example:

*a = toupper(*a);

Thirdly, you should be careful about doing this in the for-loop of your function

 for(; a < b; a++)
 {
     if(*a == *(a + 1))  // --->here
     // ... code
 }

What would happen for the case when a== str.end()-1, you still would do the increment(i.e. *(a + 1)), right?. Incrementing the end iterator again leads you Undefined behaviour.

In that case, you could use std::next from <iterator> header to safely check this.

Following is the demonstrative code which clears the issues mentioned above:

#include <iostream>
#include <string>
#include <iterator>  // std::next

std::string::iterator function(
   std::string::iterator a, 
   std::string::iterator b, 
   std::string::iterator e)
{
   auto beg = a;
   for (; a < b; a++)
   {
      if (std::next(a) != b && *a == *std::next(a)) {
         *a = toupper(*a);
         *std::next(a) = toupper(*std::next(a));
      }
   }
   std::cout << std::string{ beg, b };
   return {}; // return appropriately iterator of std::string
}

prints for now: https://godbolt.org/z/ZsLHxw

pePPermint 1001 buBBles baLLOOn gum

I assume that you want somehow to get the output to the third function parameter std::string::iterator e. I will let that part for you to figure it out. Meanwhile, have a look at the standard algorithm function std::transform, which might be handy to do such kind of transformation.

JeJo
  • 30,635
  • 6
  • 49
  • 88
1

Answers are already given. I want additionally to show an answer based on existing C++ functionality. For your given task there is a function existing in the C++ standard algorithm library. It is called std::adjacent_find. Please see here.

With that you could rewrite your code simply to:

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

int main() {
    std::string test{ "peppermint 1001 bubbles balloon gum" };

    // Find all duplicates
    for (auto il = std::adjacent_find(test.begin(), test.end()); il != test.end(); il = std::adjacent_find(il+1, test.end())) {
        
        // If duplicate found, then convert both to uppercase
        *il = std::toupper(*il);
        *(il + 1) = std::toupper(*(il+1));
    }
    std::cout << test << '\n';
    return 0;
}

We call this function in a simple for loop, until no more duplicates could be found.

Maybe it can give you an idea for a more simple implementation.

A M
  • 14,694
  • 5
  • 19
  • 44
0

Your function exhibits undefined behavior because it never returns a value. Please compile with -Wall -Wextra to enable all compiler warnings to avoid such unnecessary bugs.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436