【问题标题】:shuffle letters in a string c++随机播放字符串中的字母 c++
【发布时间】:2017-04-11 00:30:53
【问题描述】:

我打算编写一个函数,使字符串的第一个和最后一个字母保持相同,并忽略最后一个字母之后的任何非字母。我应该使用 std::random_shuffle()。我阅读了文档,但是我似乎没有掌握此功能的概念。这是我的代码:

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

std::string mix(std::string s){
    int last_char;
    if(std::isalpha(s[s.size()-1]) == true){
        last_char = s.size()-1;
    } else {
     for(int i=s.size()-1 ; i>0; --i){
        if((std::isalpha(s[i]) == false) && (std::isalpha(s[i-1])==true)){
            last_char = i -1;
            break;
        }
      }
    }
    std::random_shuffle(&s[1],&s[last_char]);
    return s;

}

int main(){
    std::string test = "Hello";
    std::cout << mix(test) << std::endl;
}

编辑:但是现在我不断收到错误:分段错误(核心转储)。有人知道为什么吗?似乎找不到问题。

【问题讨论】:

  • 它随机打乱你提供的参数之间的内容
  • 您需要学习如何使用调试器。同时回答这些问题:last_letter 的最终值是多少?分配在哪一行?

标签: c++ string random shuffle


【解决方案1】:

让你开始的东西。它至少有一个你必须修复的角落案例。访问 cppreference.com 了解算法的工作原理。

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

std::string
special_shuffle(std::string s)
{
  if (s.size() < 3) return s;
  auto begin = std::find_if(s.begin(), s.end(), ::isalpha);
  auto end = std::find_if(s.rbegin(), s.rend(), ::isalpha).base();
  std::random_shuffle(++begin, --end);
  return s;
}

int
main()
{
  std::string s1 = "Hello World!";
  std::string s2 = "AB";
  std::string s3 = "A";
  std::string s4 = "";
  std::string s5 = "a string going from a to z";

  std::cout << s1 << " --> " << special_shuffle(s1) << "\n"
            << s2 << " --> " << special_shuffle(s2) << "\n"
            << s3 << " --> " << special_shuffle(s3) << "\n"
            << s4 << " --> " << special_shuffle(s4) << "\n"
            << s5 << " --> " << special_shuffle(s5) << "\n";
}

编译运行:

$ g++ example.cpp -std=c++14 -Wall -Wextra
$ ./a.out
Hello World! --> Hooll eWlrd!
AB --> AB
A --> A
 --> 
a string going from a to z --> aarfritomgi  nnso t  g goz

【讨论】:

    【解决方案2】:
    1. 您需要在字符串的右侧找到最左边的“非字母”。

    2. 这个左边的一个位置是最后一个字母的位置。

    3. 右边的一个地方是你的第一个字母。

    4. 只需使用“first”和“last”调用 random_shuffle。

    这里有一些有用的链接:

    http://www.cplusplus.com/reference/algorithm/random_shuffle/

    记住“开始”是包容的,“结束”是排斥的”

    【讨论】:

      【解决方案3】:

      std::random_shuffle 将迭代器或指针作为参数,而不是要排序的数组/容器中的值。您对std::random_shuffle 的电话应该是:

      std::random_shuffle(&s[1],&s[last_char]);
      

      注意第二个参数是结束迭代器的值。结束迭代器不指向要排序的最后一个值,而是指向之后的值。

      这不是所示代码的唯一问题。在调用std::random_shuffle 之前,您需要修复代码中的几个错误。例如:

       for(int i=s.size() ; i>0; --i){
          if((std::isalpha(s[i]) == false) && (std::isalpha(s[i-1])==true)){
      

      s.size() 为您提供字符串的大小。在第一次迭代中,i 将等于它的size(),但现在访问s[i] 将导致未定义的行为和一个错误,因为s[i] 显然不存在。在包含n 字符的字符串中,字符当然是s[0]s[n-1]

      您需要修正您的算法,以便 last_char 最终成为您要随机播放的字符之后的下一个字符的索引,然后使用修复了上面的std::random_shuffle 电话。

      或者,或者,计算 last_char 作为要排序的最后一个字符的索引,然后调用

      std::random_shuffle(&s[1],&s[last_char+1]);
      

      任何一种方法都可以。

      【讨论】:

      • 感谢您的回答!非常有用和有用,我们还没有涵盖指针,所以分发这样的练习很奇怪。我想我修复了我的代码(它被编译了)但是现在我不断收到错误:分段错误(核心转储),我似乎找不到问题。我在帖子中修复了我的代码。
      • 我最初指出的相同错误。你的数学是关闭的。你在很多地方都落后 1 分。我指出了s.size() 的问题,但您在其他几个地方也有同样的错误。此外,您没有正确实现结束迭代器值的计算。查看我对结束迭代器值的解释,然后使用调试器单步执行您的代码,一次一行。
      猜你喜欢
      • 2016-04-28
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多