大写字母

Capitalizing letters

我有个小问题。我想利用字符串中的双字母。我成功编译了一个程序,但是没有成功

#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;
}

我做错了什么?

您的函数表现出未定义的行为,因为它从来没有 returns 值。请使用 -Wall -Wextra 编译以启用所有编译器警告以避免此类不必要的错误。

你有几个问题。

首先,您的函数承诺 return std::string::iterator

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

而且你没有遵守诺言。这将导致undefined behaviour。例如,在你的情况下,它只是编译而不给出输出。

为了获得定义的行为,您应该 return 从函数

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

其次,你要修改字符串的字符,这需要一个可修改的迭代器而不是std::string::const_iterator

然后在循环中,您需要通过重新分配给大写的 charector 来改变它。例如:

*a = toupper(*a);

第三,在函数 for-loop 中执行此操作时要小心

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

a== str.end()-1的情况下会发生什么,你仍然会做增量(即*(a + 1)),对吧?。再次递增结束迭代器 leads you Undefined behaviour.

在这种情况下,您可以使用 <iterator> header 中的 std::next 来安全地检查它。

下面是解决上述问题的演示代码:

#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
}

现在打印:https://godbolt.org/z/ZsLHxw

pePPermint 1001 buBBles baLLOOn gum

我假设您希望以某种方式将输出输出到第三个函数参数 std::string::iterator e。我会让那部分让你弄清楚。同时,看看标准算法函数std::transform,做这种转换可能很方便。

答案已经给出。我还想根据现有的 C++ 功能显示一个答案。对于给定的任务,C++ 标准算法库中存在一个函数。它被称为std::adjacent_find。请参阅 here

有了它,您可以将代码简单地重写为:

#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;
}

我们在一个简单的 for 循环中调用此函数,直到找不到更多重复项。

也许它可以给你一个更简单的实现的想法。