简体   繁体   中英

C++ ::toupper not allowing equality comparison?

I am trying to convert a string to uppercase so I can manipulate it, but while I can successfully manipulate natural uppercase strings, as well as convert lowercase to uppercase, using this method of conversion fails to allow the manipulation.

For example, if I pass "hello" through the encryption, my encrypted string becomes "HELLO", but when I pass "HELLO" through (naturally capitalized), it correctly shifts.

Is there a different way of forcing uppercase that I need to be using or am I doing something wrong?

int Caesar::encrypt (const std::string &message, std::string &emessage) {
  int count = 0;
  emessage = message;
  std::transform(emessage.begin(), emessage.end(), emessage.begin(), ::toupper);
  for (std::string::size_type i = 0; i < message.size(); i++) {
    for (int j = 0; j < 26; j++) {
      if (emessage[i] == std_alphabet[j]) {
        std::replace(emessage.begin(), emessage.end(), message[i], c_alphabet[j]);
      }
    }
    count++;
  }
  return count;
}

constructor:

Caesar::Caesar (int shift) {
    // loop to populate vector with 26 letters of English alphabet
    // using ASCII uppcase letter codes
  for (int i = 0; i < 26; i++) {
    std_alphabet.push_back(i + 65);
  }
    // fills Caesar alphabet with standard generated alphabet
  c_alphabet = std_alphabet;
    // shifts Caesar alphabet based off the constructor parameter
  std::rotate(c_alphabet.begin(), c_alphabet.begin() + shift, c_alphabet.end());
}

test file:

void testCaesar() {
  Caesar test(4);
  std::string original = "HELLO";
  std::string encrypted = "";
  test.encrypt(original,encrypted);
  std::cout << encrypted << std::endl;
  std::cout << original << std::endl;
}

int main() {
  testCaesar();
  return 0;
}

Obviously there is a header and includes and stuff but that is the basic code

the header file includes the two private vectors

The specific issue you are seeing is that you're replacing the wrong thing here:

std::replace(emessage.begin(), emessage.end(), message[i], c_alphabet[j]);

If message was lowercase, then emessage will be all upper-case letters - none of which will be message[i] . so that replacement won't do anything. You meant:

std::replace(emessage.begin(), emessage.end(), emessage[i], c_alphabet[j]);
                                               ^^^^^^^^^^^

That said, your algorithm is totally wrong as HELLO encrypts as BCBBA with a shift of 4. There is a 1-1 mapping on letters, so H and L cannot both go to B . What you want to do is shift each letter as you go by just replacing it with what its next letter should be. That is:

for (std::string::size_type i = 0; i < emessage.size(); ++i) {
    emessage[i] = c_alphabet[emessage[i] - 'A'];
}

With which you don't actually need the initial transformation step:

emessage = message;
for (std::string::size_type i = 0; i < emessage.size(); ++i) {
    emessage[i] = c_alphabet[::toupper(emessage[i]) - 'A'];
}

The whole thing can be abridged quite a bit by just dropping your count (which is just the size anyway, so is redundant) and taking the message by-value:

std::string encrypt(std::string from) { // intentionally copying
    for (char& c : from) {
        c = c_alphabet[::toupper(c) - 'A'];
    }
    return from;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM