1

It's been a long time since I've touched C++ and I've never been quite fluent in the language, so forgive my ignorance.

I've written the following little program to mess around with XOR encryption:

#include <iostream>
#include <iomanip>
#include "string.h"

using std::cout;
using std::endl;
using std::hex;
using std::string;

string cipher(string msg, char key);

int main(void)
{
    string msg = "Now is the winter of our discontent, made glorious summer by this sun of York.";
    char key = 's';  // ASCII 115

    string ctext = cipher(msg, key);

    cout << "Plaintext:  " << msg << endl;
    cout << "Ciphertext (hex):  ";
    for (int i = 0; i < ctext.size(); i++)
        cout << hex << ctext[i];

    return 0;
}

string cipher(string msg, char key)
/*
    Symmetric XOR cipher
*/
{
    for(int i = 0; i < msg.size(); i++)
        msg[i] ^= key;

    return msg;
}

This code outputs the following:

Plaintext:  Now is the winter of our discontent, made glorious summer by this sun of York.
Ciphertext (hex):  =SSSSSS_SSSS
SSSS*]

Why can I not get the hex values to output? What am I doing wrong?

Also, any general advice is appreciated.

Louis Thibault
  • 20,240
  • 25
  • 83
  • 152
  • 1
    You don't have to loop through a string to print it. `cout << ctext;` prints the string. – chris Nov 04 '12 at 19:01

1 Answers1

2

Hex applies to integers. A char is streamed as a character regardless of what the base is set in the stream. If you want the ACSII code of the character to be printed in hex, use

 cout << hex << static_cast<int>(ctext[i]);
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Thanks! Out of curiosity, why static_cast? How is this different from `(int)ctext[i]` ? – Louis Thibault Nov 04 '12 at 19:04
  • 1
    @blz, Because it's explicit and will fail if it can't do the cast through a normal conversion, as opposed to `(int)`, which would have the same effect as `reinterpret_cast` if it failed, which sucks. Also, it's easier to find and replace than C style casts. – chris Nov 04 '12 at 19:05
  • @blz http://stackoverflow.com/questions/103512/in-c-why-use-static-castintx-instead-of-intx – David G Nov 04 '12 at 19:05
  • @blz: Read this here: http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used – Armen Tsirunyan Nov 04 '12 at 19:05
  • In this case I'd just write `cout << hex << +ctext[i];`. You know `ctext[i]` is a `char` and that `+` will thus promote it to `int` with a minimum of fuss. – Lightness Races in Orbit Nov 04 '12 at 19:05
  • 1
    @LightnessRacesinOrbit: I wouldn't do that in production code. +ctext[i] is just being fancy, IMO – Armen Tsirunyan Nov 04 '12 at 19:06
  • 1
    @ArmenTsirunyan: What do you mean "just being fancy"? And why wouldn't you write it in the production code? It has well-defined semantics and is clear to anyone who knows the language... which is a pre-requisite for anyone playing with _my_ code. – Lightness Races in Orbit Nov 04 '12 at 19:06
  • @LightnessRacesinOrbit, I take it that the `+` operator implicitly converts `ctext[i]` to an int? – Louis Thibault Nov 04 '12 at 19:07
  • 1
    @blz: In case of many operators (including +), first the arguments are promoted (in case of char, it gets promoted to int) and only then does the evaluation take place – Armen Tsirunyan Nov 04 '12 at 19:07
  • @blz: Yes, unary `+` performs integral promotion. c.f. unary `-` which performs integral promotion then multiplies by `-1`. – Lightness Races in Orbit Nov 04 '12 at 19:08
  • 1
    @LightnessRacesinOrbit: It's not easily noticable, unlike static_cast. – Armen Tsirunyan Nov 04 '12 at 19:08
  • @ArmenTsirunyan, ok that makes sense. Out of curiosity, is `promoted` a technical term? I keep (naively) using the word `convert`. Is there a difference? – Louis Thibault Nov 04 '12 at 19:09
  • @ArmenTsirunyan: \*shrug\* I disagree-ish. If you know the language, you know what this code does. Each to their own, though; it's hard to disagree that `static_cast(...)` looks more explicit. – Lightness Races in Orbit Nov 04 '12 at 19:09
  • @blz, Promoted implies there's no data loss. You can promote an `int` to a `long long`, but not the other way around. – chris Nov 04 '12 at 19:09
  • @bz: Yes, it is. Integral promotion is a phrase from the standard. Just do a quick grep and you'll see! – Lightness Races in Orbit Nov 04 '12 at 19:09
  • C++11 5.3.1/7: `The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument. Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand.` I won't quote all of 4.5, which defines integral promotion. – Lightness Races in Orbit Nov 04 '12 at 19:11
  • @chris: Actually, int to long long is a conversion, not a promotion – Armen Tsirunyan Nov 04 '12 at 19:11
  • @ArmenTsirunyan, Oh, it's been too long since I've dealt with it I guess. The fact still remains that nothing will ever be promoted to a smaller-width type. – chris Nov 04 '12 at 19:15
  • @chris: Yes, that part is true. – Armen Tsirunyan Nov 04 '12 at 19:16