2

I have an unsigned char* filled with characters not just ASCII for example: `

¤ÝkGòd–ùë$}ôKÿUãšj@Äö5ÕnE„_–Ċ畧-ö—RS^HÌVÄ¥U`  . 

If I reinterpret_cast, I'll lose characters if I'm not mistaken because they're not all ASCII. I've searched everywhere but all the solutions require some sort of casting or conversion that will alter the data. Here's what I have, which doesn't work.

unsigned char* cipherText = cipher->encrypt(stringTest);
string cipherString(reinterpret_cast<char*>(cipherText));  //<-- At this point data changes in debugger
outputfile.open(outfile);       
outputfile.close();             
Andrew Tsay
  • 1,543
  • 6
  • 18
  • 31
  • 2
    `encrypt` doesn't tell you the length of the encrypted output? What if a NUL character is part of the encrypted result? – Praetorian Apr 23 '15 at 03:17
  • 2
    You clearly misunderstand what `reinterpret_cast` actually does. A cast does not alter the data, it merely returns a pointer that is a different data type than the original but otherwise still points at the same memory address. Your problem has nothing to do with casting itself. When you assign `cipherText` to a `string` as a `char*` by itself, it gets truncated on the first null encountered. You need to pass the actual byte count of `cipherText` to the `string` constructor to avoid that. – Remy Lebeau Apr 23 '15 at 03:17
  • you just need to put the length of the data in the string constructor along with the pointer. – Galik Apr 23 '15 at 03:19
  • I added a comment in the code, if reinterpret_cast is fine, then how come the value inside the string is different from that of cipherText in the debugger – Andrew Tsay Apr 23 '15 at 03:22
  • @Praetorian I can get the length. How should I use that to my benefit? – Andrew Tsay Apr 23 '15 at 03:23
  • 1
    `std::string cipherString(reinterpret_cast(cipherText), the_length);` – Tony Delroy Apr 23 '15 at 03:29

1 Answers1

2

You're not calling the string constructor you should be calling. Instead of the one that takes a single char * argument, you should call the one that takes two arguments - a char * and length.

basic_string( const CharT* s,
              size_type count,
              const Allocator& alloc = Allocator() );

To use it in your example

unsigned char* cipherText = cipher->encrypt(stringTest);
size_t cipherTextLength = // retrieve this however the API allows you to
string cipherString(reinterpret_cast<char*>(cipherText), cipherTextLength);

outputfile.open(outfile);       
// assuming outputfile is an ofstream
outputfile << cipherString;
outputfile.close();  

Note that the debugger might still indicate a truncated string depending on how it's interpreting the string's contents. If you open the output file in an editor and inspect the bytes you should see the expected result.

As RemyLebeau mentions in the comments, if you don't need the std::string for any other purpose, you don't even need to create it, just write to the ofstream directly.

outputfile.open(outfile);       
outputfile.write(reinterpret_cast<char*>(cipherText), cipherTextLength);
outputfile.close(); 
Community
  • 1
  • 1
Praetorian
  • 100,267
  • 15
  • 224
  • 307
  • 1
    The alternative is to not create a `string` at all, but instead pass `cipherText` as-is to the `ofstream` directly: `outputFile.write(reinterpret_cast(cipherText), cipherTextLength);` – Remy Lebeau Apr 23 '15 at 03:33
  • @RemyLebeau Of course, that's a much better idea. I'm going to steal that :) – Praetorian Apr 23 '15 at 03:36
  • Wow, I was completely on the wrong tracks. Thanks a lot. One more thing if I could ask, how would you read from the file? – Andrew Tsay Apr 23 '15 at 03:40
  • @atsay714 `istream` has an analogous [`read`](http://en.cppreference.com/w/cpp/io/basic_istream/read) that performs unformatted input. – Praetorian Apr 23 '15 at 03:42
  • @atsay714, I suggest writing the length of the cipher text first before writing the cipher text. That will fix the problem of reading the text back. You read the length first and then the text. – R Sahu Apr 23 '15 at 03:42
  • @R Sahu Well, sometimes I'm given just the text file, and I have to read it in to decrypt it. – Andrew Tsay Apr 23 '15 at 03:43
  • @atsay714 If all that file contains is the encrypted data then you should be able to figure out the number of bytes by using `seekg`, `tellg` etc. – Praetorian Apr 23 '15 at 03:45
  • I'm still having trouble, so I made a new topic to continue if you would like to help http://stackoverflow.com/questions/29813644/how-to-read-non-ascii-characters-from-a-text-file – Andrew Tsay Apr 23 '15 at 04:25