【问题标题】:Capitalizing letters大写字母
【发布时间】:2020-10-17 19:37:59
【问题描述】:

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

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

我做错了什么?

【问题讨论】:

    标签: c++ algorithm loops iterator stdstring


    【解决方案1】:

    你有几个问题。

    首先,你的函数承诺返回std::string::iterator

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

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

    为了得到一个定义好的行为,你应该从函数中返回

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

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

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

    *a = toupper(*a);
    

    第三,你应该小心在你的函数的for循环中这样做

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

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

    在这种情况下,您可以使用 &lt;iterator&gt; 标头中的 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,它可能会很方便地进行这种转换。

    【讨论】:

      【解决方案2】:

      答案已经给出。我还想根据现有的 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 循环中调用此函数,直到找不到更多重复项。

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-10-24
          • 1970-01-01
          • 1970-01-01
          • 2013-02-04
          • 1970-01-01
          • 2019-08-08
          • 2013-06-25
          • 2015-07-28
          相关资源
          最近更新 更多