3

I expected this to be straightforward using a for loop with replace(str.begin(), str.end(), "x", "y") but instead "x" and "y" are a certain character in an array, so: replace(str.begin(), str.end(), arrX[1], arrY[1]) in the loop:

for (int i = 0; i < arraySize; i++) {
    replace( str.begin(), str.end(), arrX[i], arrY[i]);
}

but in my code:

#include <iostream>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

string Caesar(string str) { 
  char alph[]   = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
  string caesar = "abcdefghijklmnopqrstuvwxyz";
  const int arraySize=sizeof(alph)/sizeof(alph[0]);
  rotate(caesar.begin(), caesar.begin()+3, caesar.end());
  for (int i = 0; i < arraySize; i++) {
    replace(str.begin(), str.end(), alph[i], caesar[i]);
  }
  return str; 
}
int main() {
  cout << Caesar("hello");
}

caeser string is alph rotated by three.

Outputting caesar gives expected results. (abcdef... becomes xyzabc... when just printing caesar.)

My loop seems to be the thing messing it up, when given hello it produces ccaaa. I tested replacing one letter and it worked but it seems my for loop is what the problem is, but I can't seem to find out what is wrong.

UPDATE:

I found out a way to do it that supports non alphabetical characters using a while loop that checks if it is alphabetical and then goes through the alphabet comparing each letter to a letter in the string until they match and than replace that with the rotated Caesar alphabet, if they don't match it goes to the next one and when found it resets 'j' to 0 so it can do it again for the next letter by increment 'i' this time, if the char is not a letter it just increases 'i' to the next char to just skip over it until it reaches the new letter or the end of the string.

#include <iostream>
#include <algorithm>

using namespace std;

bool IsInArray(string array, char element) {
  for(int i = 0; i < array.length(); i++){
     if(array[i] == element){
         break;
     }
  }
}
string rot(int n, string str) {
  transform(str.begin(), str.end(), str.begin(), ::tolower);
  string alph = "abcdefghijklmnopqrstuvwxyz";
  string ciph = alph;
  rotate(ciph.begin(), ciph.begin() + n, ciph.end());

  int i = 0;
  int j = 0;
  while (i < str.length()) {
    if (IsInArray(alph, str[i])) {
      if (str[i] == alph[j]) {
        str[i] = ciph[j];
        i++;
        j = 0;
      }
      else {
        j++;
      }
    }
    else {
      i++;
    }
  }
  return str;
}

int main() {
  cout << rot(2, "This cipher works with more than just alpha chars!");
  return 0;
}
3
  • 1
    I've verified that it works. -- This goes counter to what we would need -- an minimal reproducible example. Also: char caesar[arraySize]; This is not valid C++ syntax. Arrays must have compile-time bounds stated, not variable. Change arraySize to const int arraySize=...; And why not just use std::rotate instead of your leftRotate function, so that we are truly convinced "it works"? Commented Dec 29, 2016 at 22:09
  • 3
    Step through the loop. Say you replace 'e' with 'h'. Your string becomes 'hhllo'. But then you replace all the 'h' with 'k' you get 'kkllo', etc. You need to make sure a letter only gets replaced once. Commented Dec 29, 2016 at 22:26
  • @JohnnyMopp Oh yes obviously, many thanks, but how exactly would I go about doing this? Commented Dec 29, 2016 at 22:53

2 Answers 2

1

Here's one way to do it using standard functions and a lambda function:

string Caesar(std::string str) { 
    std::string caesar = "abcdefghijklmnopqrstuvwxyz";
    std::rotate(caesar.begin(), caesar.end()-3, caesar.end());
    std::transform(str.begin(), str.end(), str.begin(), 
        [caesar](char c) -> char { return caesar[c - 'a']; });
    return str; 
}

Note: it uses the char code to get the index, so it would have to be changed to handle anything other than "abc...xyz".

Sign up to request clarification or add additional context in comments.

Comments

1

As an optimization: if you're using just letters a-z lowercase, you can do it without using the two arrays and without using the function leftRotatebyOne. Instead use the ASCII values.

std::string Caesar(std::string str){
    int delta = 'z' - 'a' + 1;
    int rotateBy = 3;
    for(int i = 0; i < str.length(); i++){
        char c = str[i] - rotateBy;
        if(c < 'a')
            c += delta;
        str[i] = c;
    }
    return str;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.