Hex to String Conversion C++/C/Qt? - c++

I am interfacing with an external device which is sending data in hex format. It is of form
> %abcdefg,+xxx.x,T,+yy.yy,T,+zz.zz,T,A*hhCRLF
CR LF is carriage return line feed
hh->checksum
%abcdefg -> header
Each character in above packet is sent as a hex representation (the xx,yy,abcd etc are replaced with actual numbers). The problem is at my end I store it in a const char* and during the implicit conversion the checksum say 0x05 is converted to \0x05. Here \0 being null character terminates my string. This is perceived as incorrect frames when it is not. Though I can change the implementation to processing raw bytes (in hex form) but I was just wondering whether there is another way out, because it greatly simplifies processing of bytes. And this is what programmers are meant to do.
Also in cutecom (on LINUX RHEL 4) I checked the data on serial port and there also we noticed \0x05 instead of 5 for checksum.
Note that for storing incoming data I am using
//store data from serial here
unsigned char Buffer[SIZE];
//convert to a QString, here is where problem arises
QString str((const char*)Buffer); of \0
QString is "string" clone of Qt. Library is not an issue here I could use STL also, but C++ string library is also doing the same thing. Has somebody tried this type of experiment before? Do share your views.
EDIT
This is the sample code you can check for yourself also:
#include <iostream>
#include <string>
#include <QString>
#include <QApplication>
#include <QByteArray>
using std::cout;
using std::string;
using std::endl;
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
int x = 0x05;
const char mydata[] = {
0x00, 0x00, 0x03, 0x84, 0x78, 0x9c, 0x3b, 0x76,
0xec, 0x18, 0xc3, 0x31, 0x0a, 0xf1, 0xcc, 0x99};
QByteArray data = QByteArray::fromRawData(mydata, sizeof(mydata));
printf("Hello %s\n",data.data());
string str("Hello ");
unsigned char ch[]={22,5,6,7,4};
QString s((const char*)ch);
qDebug("Hello %s",qPrintable(s));
cout << str << x ;
cout << "\nHello I am \0x05";
cout << "\nHello I am " << "0x05";
return app.exec();
}

QByteArray text = QByteArray::fromHex("517420697320677265617421");
text.data(); // returns "Qt is great!"

If your 0x05 is converted to the char '\x05', then you're not having hexadecimal values (that only makes sense if you have numbers as strings anyway), but binary ones. In C and C++, a char is basically just another integer type with very little added magic. So if you have a 5 and assign this to a char, what you get is whatever character your system's encoding defines as the fifth character. (In ASCII, that would be the ENQ char, whatever that means nowadays.)
If what you want instead is the char '5', then you need to convert the binary value into its string representation. In C++, this is usually done using streams:
const char ch = 5; // '\0x5'
std::ostringstream oss;
oss << static_cast<int>(ch);
const std::string& str = oss.str(); // str now contains "5"
Of course, the C std library also provides functions for this conversion. If streaming is too slow for you, you might try those.

I think c++ string classes are usually designed to handle zero-terminated char sequences. If your data is of known length (as it appears to be) then you could use a std::vector. This will provide some of the functionality of a string class, whilst ignoring nulls within data.

As I see you want to eliminate control ASCII symbols. You could do it in the following way:
#include <iostream>
#include <string>
#include <QtCore/QString>
#include <QtCore/QByteArray>
using namespace std;
// test data from your comment
char data[] = { 0x49, 0x46, 0x50, 0x4a, 0x4b, 0x51, 0x52, 0x43, 0x2c, 0x31,
0x32, 0x33, 0x2e, 0x34, 0x2c, 0x54, 0x2c, 0x41, 0x2c, 0x2b,
0x33, 0x30, 0x2e, 0x30, 0x30, 0x2c, 0x41, 0x2c, 0x2d, 0x33,
0x30, 0x2e, 0x30, 0x30, 0x2c, 0x41, 0x2a, 0x05, 0x0d, 0x0a };
// functor to remove control characters
struct toAscii
{
// values >127 will be eliminated too
char operator ()( char value ) const { if ( value < 32 && value != 0x0d && value != 0x0a ) return '.'; else return value; }
};
int main(int argc,char* argv[])
{
string s;
transform( &data[0], &data[sizeof(data)], back_inserter(s), toAscii() );
cout << s; // STL string
// convert to QString ( if necessary )
QString str = QString::fromStdString( s );
QByteArray d = str.toAscii();
cout << d.data(); // QString
return 0;
}
The code above prints the following in console:
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
If you have continuous stream of data you'll get something like:
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.
IFPJKQRC,123.4,T,A,+30.00,A,-30.00,A*.

Related

Char array from cin

I have a function in c++ that accepts
char[] arg. If char[] is hardcode like
char t[] = { 0x41, 0x54, 0x2b, 0x4d,
0x53, 0x4c, 0x53, 0x45, 0x43, 0x55,
0x52, 0x3d, 0x31, 0x2c, 0x30 }
it works. I need to be able to get the char[] from cin, the data from cin will be ascii AT+MSLSECUR=1,0 and need to convert it to equivalent of the hardcoded char[] i show above
I dont know where to start i tried simply making cin read to char[] but doesnt seem to work char[] data is wrong
I am new to this so please forgive my lack of knowledge
I guess that's that what you are asking for :
std::string input ;
std::cin << input ;
char *YourCharArray = new char [ input.size() + 1 ] ;
strcpy(YourCharArray , input.c_str());

I'm getting odd output from XOR. Can someone tell me what I'm doing wrong?

I'm working on a basic encryption program (New in programming). At this very moment, I'm trying to XOR 2 hex values to create a cipher text. The problem is, my output is giving me odd data.
For example 0x61 XOR 0x2a should give me 4b according to an online xor calculator, but in my program I get odd outputs. Can some one explain why my output is not 4b and etc and how to properly fix it?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
char my_string[5]="0x61, 0x6e, 0x74, 0x69, 0x64";
char my_key[5]= "0x2a, 0x44, 0x23, 0x01, 0x46";
char cText;
int main()
{
int i;
for( i = 0; i<5; i++)
{
cText = my_string[i]^my_key[i];
printf(" %i . The Cipher Text is %0x \n", i + 1, cText);
}
return;
}
Your string initializations are invalid — you are initializing the strings with the literal text "0x61, 0x6e…", not with the hexadecimal values 0x61, 0x6e, etc.
To initialize a character array with numeric values, use curly braces instead of quotation marks:
char my_string[5]= { 0x61, 0x6e, 0x74, 0x69, 0x64 };

I wrote this Hamming Encoding code for class. Why is it so slow?

I wrote this for my OS class:
#include <iostream>
#include <fstream>
//encodes a file using the (8,4) Hamming Code.
//usage : HammingEncode.out < inputFile > outputFile
int main() {
unsigned char const codebook[] = {0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78, 0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF};
unsigned char in, nextByte;
unsigned char const leftMask = 0xF0, rightMask = 0x0F;
in = std::cin.get();
while (!std::cin.eof()) {
nextByte = (in & leftMask) >> 4;
std::cout << codebook[nextByte];
nextByte = in & rightMask;
std::cout << codebook[nextByte];
in = std::cin.get();
}
}
I then decided to test its speed (just to see) on the Old Testamenet form the King James Bible. This was our standard test file for a Data Structures Class which was taught in Java, and we could sort it and Huffman Encode it in basically no time, yet this takes quite a long time to encode. What is going on?
std::cin is open in text-mode, and as such it is constantly on the lookout for all kinds of things to watch for (like newlines, etc).
Given the constant character sniffing by the std::cin input stream, i'm not surprised it takes longer, but it does seem a little excessive. the following, bypassing iostream and using FILE stream directly will probably do what you were expecting:
#include <cstdlib>
#include <cstdio>
int main(int argc, char *argv[])
{
static unsigned char const codebook[] =
{
0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78,
0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF
};
for (int c = std::fgetc(stdin); c!=EOF; c=std::fgetc(stdin))
{
std::fputc(codebook[c >> 4], stdout);
std::fputc(codebook[c & 0x0F], stdout);
}
return EXIT_SUCCESS;
}
I tested the exact code above on an 10MB random file loaded with chars ranging from a to z, and the results were ridiculously long when using std::cin and std::cout. Using the FILE streams directly, the difference was enormous. All of the code in this answer was tested with Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn) using -O3 optimization.
Using FILE streams
time ./hamming < bigfile.txt > bigfile.ham
real 0m1.855s
user 0m1.812s
sys 0m0.041s
Using std::cin and std::cout
time ./hamming < bigfile.txt > bigfile.ham
real 0m23.819s
user 0m7.416s
sys 0m16.377s
Using std::cin and std::cout with std::cout.sync_with_stdio(false);
time ./hamming < bigfile.txt > bigfile.ham
real 0m24.867s
user 0m7.705s
sys 0m17.118s
In summary, ouch. Of note is the time spent in system. If I get a chance to update this with the std::istream::get() and put() methods I will, but honestly I don't expect any miracles on that. Unless there is some magic (to me, not to others) way of turning off io xlat from std::cin the FILE streams may be a reasonable alternative. I haven't yet investigated whether slurping std::cin's rdbuf() is a viable option either, but it may too have promise.
Edit: Using std::istreambuf_iterator<char>
Using the streambuf iterator class has a significant improvement, as it essentially bypasses all the inline slat junk, but it still isn't as efficient as FILE streams:
#include <iostream>
#include <cstdlib>
#include <cstdio>
int main(int argc, char *argv[])
{
static unsigned char const codebook[] =
{
0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78,
0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF
};
std::istreambuf_iterator<char> cin_it(std::cin), cin_eof;
std::for_each(cin_it, cin_eof, [](char c)
{
std::cout.put(static_cast<char>(codebook[static_cast<unsigned char>(c) >> 4]));
std::cout.put(static_cast<char>(codebook[static_cast<unsigned char>(c) & 0x0F]));
});
return EXIT_SUCCESS;
}
Results:
time ./hamming < bigfile.txt > bigfile.ham
real 0m6.062s
user 0m5.795s
sys 0m0.053s
Note that system is now comparable to the FILE stream results, but the overhead from rest of the iostream templates in user seems a sore point (but still better than the other iostream attempts). You win some, you lose some =P
Edit: Unbuffered System IO
In effort to be completely fair, bypassing all runtime buffering and relying solely on the system calls to do this madness, the following is also worth noting:
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
int main(int argc, char *argv[])
{
static unsigned char const codebook[] =
{
0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78,
0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF
};
unsigned char c;
while (read(STDIN_FILENO, &c, 1)> 0)
{
unsigned char duo[2] =
{
codebook[ c >> 4 ],
codebook[ c & 0x0F ]
};
write(STDOUT_FILENO, duo, sizeof(duo));
}
return EXIT_SUCCESS;
}
The results, as you would expect, were dreadful:
time ./hamming < bigfile.txt > bigfile.ham
real 0m26.509s
user 0m2.370s
sys 0m24.087s
I got close to an order of magnitude improvement by making 2 small changes.
Adding std::ios_base::synch_with_stdio(false) (no noticeable difference, though the impact is often implementation specific)
Buffering the output before writing (this made the most difference)
The updated code looks like this:
int main()
{
//encodes a file using the (8,4) Hamming Code.
//usage : HammingEncode.out < inputFile > outputFile
unsigned char const codebook[] = { 0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78, 0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF };
unsigned char in, nextByte;
unsigned char const leftMask = 0xF0, rightMask = 0x0F;
std::stringstream os;
std::ios_base::sync_with_stdio(false);
in = std::cin.get();
while (std::cin) {
nextByte = (in & leftMask) >> 4;
os.put(codebook[nextByte]);
nextByte = in & rightMask;
os.put(codebook[nextByte]);
in = std::cin.get();
}
std::cout << os.rdbuf();
}
Update
I tried one more implementation - using the underlying std::streambuf.
On my system the original code was taking around 14 seconds to process the full King James Bible - around 4.3 MB
The code in my original attempt took around 2.1 seconds to process.
This new implementation took 0.71 seconds to process the same document.
int main()
{
//encodes a file using the (8,4) Hamming Code.
//usage : HammingEncode.out < inputFile > outputFile
unsigned char const codebook[] = { 0x00, 0x1E, 0x2D, 0x33, 0x4B, 0x55, 0x66, 0x78, 0x87, 0x99, 0xAA, 0xB4, 0xCC, 0xD2, 0xE1, 0xFF };
unsigned char in, nextByte;
unsigned char const leftMask = 0xF0, rightMask = 0x0F;
std::stringstream os;
std::ios_base::sync_with_stdio(false);
std::streambuf * pbuf = std::cin.rdbuf();
do {
in = pbuf->sgetc();
nextByte = (in & leftMask) >> 4;
os << codebook[nextByte];
nextByte = in & rightMask;
os << codebook[nextByte];
} while (pbuf->snextc() != EOF);
std::cout << os.rdbuf();
}
C++ iostreams has bad opinion for being rather inefficient, although different numbers suggest that it's rather quality-of-implementation issue, rather than iostream disadvantage.
Anyway, just to be sure that it's not anything like slow hdd you might compare execution time to e.g.
cat file1 > file2
Of cource cat will be a bit quicker, as it doesn't double the size of your data.
Then try to compare efficieny of your code with following:
#include <stdio.h>
#include <unistd.h>
int main()
{
unsigned char buffer[1024*1024]; // 1MB buffer should be enough
while (!eof(STDIN_FILENO)){
size_t len = read(STDIN_FILENO, &buffer[0], 1024*1024);
write(STDOUT_FILENO, &buffer[0], len);
write(STDOUT_FILENO, &buffer[0], len);
}
return 0;
}
EDIT:
Sorry, my bad. Try
#include <stdio.h>
#include <unistd.h>
int main()
{
unsigned char buffer[1024*1024]; // 1MB buffer should be enough
size_t len = read(STDIN_FILENO, &buffer[0], 1024*1024);
while(len > 0){
write(STDOUT_FILENO, &buffer[0], len);
write(STDOUT_FILENO, &buffer[0], len);
len = read(STDIN_FILENO, &buffer[0], 1024*1024);
}
return 0;
}
If I understand correctly, for each byte you read, you then write 2 bytes. So output file will be double size of the input. If your input is big enough - total IO (read + 2 * write) time will be significant.
In Huffman coding this is not the case - since you usually write less than you read, and total IO time will be much lower.
EDIT:
As Blorgbeard said, it can be the difference in buffering. C++ also does buffering, but may be default buffers are much smaller than in Java. Also the fact that the HDD head should constantly jump between reading file in one location and then writing in another - significantly impacts overall IO performance.
In any case, encoding should be done in chunks in order to ensure sequential read and write of large blocks

Output is not what it should be

So there is a program that I am working on, that requires me to access data from a char array containing hex values. I have to use a function called func(), in this example, in order to do access the data structure. Func() contains 3 pointer variables, each of different types, and I can use any of them to access the data in the array. Whichever datatype I choose will affect what values will be stored to the pointer. Soo heres the code:
unsigned char data[]
{
0xBA, 0xDA, 0x69, 0x50,
0x33, 0xFF, 0x33, 0x40,
0x20, 0x10, 0x03, 0x30,
0x66, 0x03, 0x33, 0x40,
}
func()
{
unsigned char *ch;
unsigned int i*;
unsigned short* s;
unsigned int v;
s = (unsigned short*)&data[0];
v = s[6];
printf("val:0x%x \n",v);
}
Output:
Val:0x366
The problem with this output is that it should be 0x0366 with the zero in front of the 3, but it gets cut off at the printf statement, and I'm not allowed to modify that. How else could I fix this?
Use a format that specifies leading zeros: %04x.
Without changing the format passed to printf or replacing it entirely I'm afraid there's no way to affect the output.

Error when passing arguments and convert it to hexadecimal

How could insert text by argument and automatically transform it to hex?
I tried with:
unsigned char aesKey[32] = argv[1];
but get errors
The output would be like this:
unsigned char aesKey[32] = {
0x53, 0x28, 0x40, 0x6e, 0x2f, 0x64, 0x63, 0x5d, 0x2d, 0x61, 0x77, 0x40, 0x76, 0x71, 0x77, 0x28,
0x74, 0x61, 0x7d, 0x66, 0x61, 0x73, 0x3b, 0x5d, 0x66, 0x6d, 0x3c, 0x3f, 0x7b, 0x66, 0x72, 0x36
};
unsigned char *buf;
aes256_context ctx;
aes256_init(&ctx, aesKey);
for (unsigned long i = 0; i < lSize/16; i++) {
buf = text + (i * 16);
aes256_encrypt_ecb(&ctx, buf);
}
aes256_done(&ctx);
Thanks in advance
In C and C++, when you have code like
char name[]="John Smith";
The compiler knows at compile time what the size of that char array, and all the values will be. So it can allocate it on the stack frame and assign it the value.
When you have code like
char * strptr = foo();
char str[] = strptr;
The compiler doesn't know what the size and value of the string pointed by strptr is. That is why this is not allowed in C/C++.
In other words, only string literals can be assigned to char arrays, and that too only at the time of declaration.
So
char name[] = "John Smith";
is allowed.
char name[32];
name = "John Smith";
is not allowed.
Use memcpy
So you could use memcpy. (Or use c++ alternative that others have alluded to)
unsigned char *aesKey;
size_t len = (strlen(argv[1])+1)*sizeof(unsigned char);
aesKey = malloc(len);
memcpy(aesKey, argv[1], len);
The old solution
(here is my previous answer, the answer above is better)
So you need to use strncpy.
unsigned char aesKey[32];
strncpy((char *) aesKey, argv[1], 32);
Notice the routine is strncpy not strcpy. strcpy is unsafe. (Thanks PRouleau for the arg fix)
If strncpy is not available in Visual Studio then you may have to try strcpy_s (Thanks Google: user:427390)
In C/C++, the compiler does not automatically manipulate the arrays. You have to specify how to copy them.
The good old way is with memcpy(). A more modern way is with std::copy(). In any case, you have to validate the length of argv[1] before copying into aesKey.
For the conversion into hex, you probably have to transform a string like "AAEE3311" (up to 2*32 chars) into bytes. You should use std::istringstream and fill your aesKey position by position.
Ex:
std::istringstream Input(argv[1]);
Input >> std::hex >> aesKey[0];
I would imagine a program being called as below -
myprog 0x53 0x28 0x40 0x6e 0x2f 0x64 0x63
Inside the program I would have a loop to assign the arguments to the array -
const int size = 32;
unsigned char aesKey[size];
char* p;
for (int i = 1; i < argc || i < size; ++i)
{
aesKey[i] = (unsigned char)strtol(argv[i], &p, 16);
}