LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-01-2015, 08:26 PM   #1
teapottwo
Member
 
Registered: Sep 2013
Posts: 52

Rep: Reputation: Disabled
C++ bin array to hex string and back


Hi, I feel totally lost round about now lol...

In reality, I'm starting with an array of bytes (unsigned chars), I require to convert them to hex (which seems fine here), and then convert back. I'm not sure if its just late but I'm struggling to copy the vector of bytes to an array of bytes, also I'm wondering if there's a better way without the intermediary vector...? Any help cheers!

Code:
#include <iostream>

#include <vector>
#include <cstdlib>

#include <sstream>
#include <iomanip>
#include <string>

using namespace std;


typedef unsigned char byte;


std::string ToHex(const byte* buffer, size_t size){
	std::stringstream str;
	str.setf(std::ios_base::hex, std::ios::basefield);
	//str.unsetf(std::ios::showbase);
	//str.setf(std::ios::showbase);
	str.setf(std::ios_base::uppercase);
	str.fill('0');
	//str.width(2);
	
	for(size_t i=0; i<size; ++i){
		str << std::setw(2) << (unsigned short)(byte)buffer[i];
	}
	return str.str();
}

unsigned char* shex2bytes(string hex_chars){
	std::istringstream hex_chars_stream(hex_chars);
	std::vector<unsigned char> v;

	unsigned int c;
	while(hex_chars_stream >> std::hex >> c){
		v.push_back(c);
	}
	
	//unsigned char *bytes = new unsigned char[v.size()];
	//std::copy(v.begin(), v.end(), bytes);
	
	unsigned char *bytes;
	for (int i = 0; i < v.size(); i++){
		*bytes = v[i];
		bytes++;
	}
	
	return bytes;
}

int main(){
	
	size_t size = 256;
	byte buffer[size];
	for(int i=0; i<size; ++i){
		buffer[i] = i;
	}
	const std::string hex = ToHex(buffer, size);	//, true);
	std::cout << hex.c_str() << std::endl;
	
	cout << endl;
	
	
	unsigned char* sa = shex2bytes(hex);
	cout << sa << endl;
	
}

EDIT:
If I return the vector I can print out the values, but when I put to an array or recast I get nothing...?
Code:
unsigned char* shex2bytes3(std::string hex_chars){
	std::istringstream hex_chars_stream(hex_chars);
	std::vector<unsigned char> v;

	unsigned int c;
	while(hex_chars_stream >> std::hex >> c){
		v.push_back(c);
	}
	
	//return reinterpret_cast<unsigned char*> (&v[0]);
	//unsigned char* cc = reinterpret_cast<unsigned char*> (&v[0]);
	unsigned char* cc = reinterpret_cast<unsigned char*> (v.data());
	
	return cc;
}
or

Code:
byte* HexToBytes(const std::string& hex){
	//std::vector<char> bytes;
	
	size_t size = hex.size();
	byte *bytes = (byte*)malloc(sizeof(byte) * ((size/2)+1)); 
	
	int j=0;
	for (unsigned int i = 0; i < hex.length(); i += 2){
		std::string byteString = hex.substr(i, 2);
		unsigned char b = (unsigned char) strtol(byteString.c_str(), NULL, 16);
		//bytes.push_back(byte);
		bytes[j] = b;
		j++;
	}
	bytes[j] = '\0';
	
	return bytes;
}

Last edited by teapottwo; 12-01-2015 at 09:57 PM.
 
Old 12-02-2015, 03:13 PM   #2
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by teapottwo View Post
If I return the vector I can print out the values, but when I put to an array or recast I get nothing...?
When you print the vector, the runtime is converting the byte values inside the vector to a decimal string. If you print a byte array directly, it will be interpreted as a C string. Since the 0 byte at the front indicates end-of-string, none of the other bytes will ever be printed (and many of them are not printable characters anyway).
 
Old 12-02-2015, 03:22 PM   #3
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
Well, I was waiting till tomorrow to chime in because I largely only had to say the following.

I compiled the original program. It converts to hex. The second part doesn't work. I observed it in the debugger and the converted output data is NOT 00, 01, 02, ... it's more like random bad data. So the shex2bytes() function does need to be fixed. A point I was also going to make was to state that one should realize that hex-ascii, if that's what it sees the input as, is actually two characters in an array and therefore one has to take like { 0x30, 0x31 } to be interpreted as "01", the 0x30 representing the upper nibble of the binary result. Not sure if that's part of the problem, but clearly sure that something further is wrong because the output data was no where near the correct values, again it was purely random stuff. I just don't have the time to look further today, and will look at it in the morning.

I also wanted to encourage the OP to post more updates if they go further and have some more success. And I also was going to suggest that the OP use a debugger, like GDB to break and observe the variables directly in memory, because that, to me, is definitive. So if you happen to "print" incorrectly, or use the wrong function to get your output, knowing that you did the conversion fully correctly is helpful so you know where to concentrate your efforts. My take is that the conversion is not working, but haven't looked enough on my part to understand yet why that is the case.

Good work thus far, though!

Last edited by rtmistler; 12-02-2015 at 03:23 PM.
 
Old 12-02-2015, 09:07 PM   #4
teapottwo
Member
 
Registered: Sep 2013
Posts: 52

Original Poster
Rep: Reputation: Disabled
Here's where I got to earlier,but it still needs testing in situ...
Code:
std::vector<unsigned char> HexToBytes(const std::string& hex){
	std::vector<unsigned char> bytes;
	
	for (unsigned int i = 0; i < hex.length(); i += 2){
		std::string byteString = hex.substr(i, 2);
		unsigned char byte = (char) strtol(byteString.c_str(), NULL, 16);
		bytes.push_back(byte);
	}
	
	return bytes;
}

std::string ToHex(const byte* buffer, size_t size){
	std::stringstream str;
	str.setf(std::ios_base::hex, std::ios::basefield);
	//str.unsetf(std::ios::showbase);
	//str.setf(std::ios::showbase);
	str.setf(std::ios_base::uppercase);
	str.fill('0');
	//str.width(2);
	
	for(size_t i=0; i<size; ++i){
		//str << std::hex << std::setw(2) << (unsigned short)(unsigned char)buffer[i];
		//str << (unsigned short)(unsigned char)buffer[i];
		str << std::setw(2) << (unsigned short)(byte)buffer[i];
	}
	return str.str();
}


int main(){
	
	std::string s = "4C494E5558";
	vector<unsigned char> v = HexToBytes(s);
	//cout << "b: " << (int)b << endl;
	
	
	//	CONVERT VECTOR INTO STRING
	string ss = "";
	for(std::vector<unsigned char>::size_type i = 0; i != v.size(); i++) {
		ss+=v[i];
	}
	//	AND TO CHAR*
	size_t tot = ss.size();
	unsigned char *a=new unsigned char[tot+1];
	a[tot]=0;
	memcpy(a,ss.c_str(),tot);
	
	
	ss = ToHex(a,tot);
	cout << "test: " << ss << endl;
	

}
 
Old 12-03-2015, 07:59 AM   #5
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
That works. I suppose a full test would be what you've done before, which is to take an array from 0x00 through 0xFF and convert that from pure binary to a HEX string using your toHex() function, validate that you did it all, and then convert the HEX string back to binary bytes and validate that this worked. However what you wrote here does work for the test pattern you put in, "LINUX", and I'm fairly sure it will just work for all data. As ntubski points out, many of the characters in the full ASCII set of available patterns will be non-printable. Therefore I look at things like that in the debugger. Otherwise you'd have to use a convert function not of your own manufacture to make then ASCII printable.

Good job!
 
Old 12-03-2015, 06:43 PM   #6
teapottwo
Member
 
Registered: Sep 2013
Posts: 52

Original Poster
Rep: Reputation: Disabled
I'm not going for the credit here, hence why I've left the original function names as found.

I'd have done this in a very manual way, which would have probably been quicker (to do), but was looking for common practice when using C++. As I was thinking today, I've spent too long in the world of Lua and PHP and my C / C++ knowledge has gone to mush, a visit to my parents for my old books is in order...

Not yet proved as solved...
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
hex string to char[] retroCheck Programming 3 05-15-2015 04:41 PM
How to get hex offset of string otaku2k2 Linux - Software 6 01-30-2012 06:06 AM
[SOLVED] string to hex parser avee137 Programming 5 09-10-2011 04:41 PM
Hex String to ttysX digmeupnow Linux - Newbie 1 11-25-2008 03:33 AM
Hex output of a hex/ascii input string mlewis Programming 35 04-10-2008 12:05 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:04 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration