mthe25
mthe25

Reputation: 51

shuffle letters in a string c++

I'm meant to write a function that keeps the first and last letter of a string the same and ignores any non-letters after the last letter. I'm supposed to use the std::random_shuffle(). I read the documentation however I don't seem to grasp the concept of this function. This is my code:

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

edit: Now however I keep getting the error: segmentation fault(core dumped). ANyone got an idea why? Can't seem to find the problem.

Upvotes: 0

Views: 3029

Answers (3)

Escualo
Escualo

Reputation: 42082

Something to get you started. It has at least one corner case that you'll have to fix. Visit cppreference.com to understand how the algorithms work.

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

Compile and run:

$ 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

Upvotes: 0

paulsm4
paulsm4

Reputation: 121649

  1. You'll need to find the leftmost "non-letter" in the right side of your string.

  2. One place to the left of this is the position of the last letter.

  3. One place to the right is your first letter.

  4. Simply invoke random_shuffle with your "first" and "last".

Here are some useful links:

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

Remember that "begin" is inclusive, "end" is exclusive"

Upvotes: 1

Sam Varshavchik
Sam Varshavchik

Reputation: 118340

std::random_shuffle takes iterators or pointers, as arguments, not values in the array/container to be sorted. Your call to std::random_shuffle should probably be:

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

Note that the second parameter is the ending iterator value. The ending iterator doesn't point to the last value to sort, but the one after that.

This is not the only problem with the shown code. You'll need to fix several bugs in your code that precedes the call to std::random_shuffle. For example:

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

s.size() gives you the size of the string. On the first iteration, i will be equal to its size(), but accessing s[i] will now result in undefined behavior, and a bug, since s[i] obviously does not exist. In a string that contains n characters, the characters are s[0] through s[n-1], of course.

You will need to fix your algorithm so that last_char ends up being the index of the next character after the one you want to shuffle, and then use the fixed std::random_shuffle call, above.

Or, alternatively, compute last_char to be the index of the last character to sort, and call

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

Either approach will be fine.

Upvotes: 3

Related Questions