Convert Hex to Byte in C++ - c++

How do you convert a hex string to short in c++?
Let's say you have
string hexByte = "7F";
How do you convert that to a byte? Which I assume it's a char or int8_t in c++
I tried:
wstring hexString = "7F";
unsigned char byte;
stringstream convert(hexString);
convert >> byte;

// converting from UTF-16 to UTF-8
#include <iostream> // std::cout, std::hex
#include <string> // std::string, std::u16string
#include <locale> // std::wstring_convert
#include <codecvt> // std::codecvt_utf8_utf16
int main ()
{
std::u16string str16 (u"\u3084\u3042"); // UTF-16 for YAA (やあ)
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> cv;
std::string str8 = cv.to_bytes(str16);
std::cout << std::hex;
std::cout << "UTF-8: ";
for (char c : str8)
std::cout << '[' << int(static_cast<unsigned char>(c)) << ']';
std::cout << '\n';
return 0;
}
http://www.cplusplus.com/reference/locale/wstring_convert/to_bytes/

Convert each character of hex input to integer type
int char2int(char input)
{
if(input >= '0' && input <= '9')
return input - '0';
if(input >= 'A' && input <= 'F')
return input - 'A' + 10;
if(input >= 'a' && input <= 'f')
return input - 'a' + 10;
throw std::invalid_argument("Invalid input string");
}
// This function assumes src to be a zero terminated sanitized string with
// an even number of [0-9a-f] characters, and target to be sufficiently large
void hex2bin(const char* src, char* target)
{
while(*src && src[1])
{
*(target++) = char2int(*src)*16 + char2int(src[1]);
src += 2;
}
}

Related

Hex_string to uint8_t msg[]

I want convert the characters in hex string
"0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98"
to uint8_t msg[] and do not understand how to do it.
It seems simple, but have been unable to figure it out. I want to convert each character to a uint8_t hex value. For example if I have
string result = "0123456789abcdef";
How do I convert the string to:
uint8_t msg[] = "0123456789abcdef";
This func (thanks Converting a hex string to a byte array )
vector<uint8_t> HexToBytes(const string& hex) {
vector<uint8_t> bytes;
for (unsigned int i = 0; i < hex.length(); i += 2) {
string byteString = hex.substr(i, 2);
uint8_t byte = (uint8_t) strtol(byteString.c_str(), nullptr, 16);
bytes.push_back(byte);
}
return bytes;
}
using the above function we get the vector of bytes and call the method data()
I want to thank the community now everything is working correctly. Thanks for the comments, I was already desperate that I could not do such a simple thing.
Special thanks to #johnny-mopp
Edit - Updated to ready bytes not characters
Rather than using .substr() and calling C strtol and casting to uint8_t, you can simply use an istringstream along with std::setbase(16) to read the bytes as unsigned values directly into your vector<uint8_t> msg. See std::setbase.
For instance you can create an istringstream from your string containing the hex characters, and then along with your vector of uint8_t and a temporary unsigned to read directly into before pushing back into your vector you could do, e.g.
std::string result ("0123456789abcdef"); /* input hex string */
std::string s2; /* string for 2-chars */
std::istringstream ss (result); /* stringstream of result */
std::vector<uint8_t> msg; /* vector of uint8_t */
while ((ss >> std::setw(2) >> s2)) { /* read 2-char at a time */
unsigned u; /* tmp unsigned value */
std::istringstream ss2 (s2); /* create 2-char stringstream */
ss2 >> std::setbase(16) >> u; /* convert hex to unsigned */
msg.push_back((uint8_t)u); /* add value as uint8_t */
}
In that way, each 2 characters in result read using std::setw(2) are used to create a 2-character stringstream that is then converted a an unsigned value using std::setbase(16). A complete example would be:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
int main (void) {
std::string result ("0123456789abcdef"); /* input hex string */
std::string s2; /* string for 2-chars */
std::istringstream ss (result); /* stringstream of result */
std::vector<uint8_t> msg; /* vector of uint8_t */
while ((ss >> std::setw(2) >> s2)) { /* read 2-char at a time */
unsigned u; /* tmp unsigned value */
std::istringstream ss2 (s2); /* create 2-char stringstream */
ss2 >> std::setbase(16) >> u; /* convert hex to unsigned */
msg.push_back((uint8_t)u); /* add value as uint8_t */
}
std::cout << "string: " << result << "\nmsg: \n";
for (auto& h : msg) /* for each element of msg, output hex value */
std::cout << "\t" << std::setfill('0') << std::hex << std::setw(2)
<< (uint32_t)h << '\n';;
}
(note the cast required in the output to explicitly tell cout to treat the uint8_t value as an unsigned value rather than a uint8_t value which defaults to an character type by default.
Example Use/Output
$ ./bin/hexstr2uint8_t
string: 0123456789abcdef
msg:
01
23
45
67
89
ab
cd
ef
(note there are 8 uint8_t ("byte") values stored this time instead of 16 character values)
It's just an alternative using the C++ iostream features which avoids the need to cast things around rather than calling strtol directly (which in your case should probably be strtoul to begin with).
Manual Hex Conversion
In your last comment you indicate that using iostream and stringstream for the conversion is slow. You can attempt to optimize a bit by eliminating the stringstream and using a string::iterator to step through the string manually converting each character and forming each uint8_t byte as you go (protecting against a final nibble or 1/2-byte), e.g.
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
/* simple manual conversion of hexchar to value */
uint8_t c2hex (const char c)
{
uint8_t u = 0;
if ('0' <= c && c <= '9')
u = c - '0';
else if ('a' <= c && c <= 'f')
u = c - 'W';
else if ('A' <= c && c <= 'F')
u = c - '7';
else
std::cerr << "error: invalid hex char '" << c << "'\n";
return u;
}
int main (void) {
std::string s ("0123456789abcdef");
std::vector<uint8_t> msg;
for (std::string::iterator n = s.begin(); n != s.end(); n += 2) {
uint8_t u = c2hex (*n); /* save high-nibble */
if (n + 1 != s.end()) /* if low-nibble available */
u = (u << 4) | c2hex (n[1]); /* shift high left 4 & or */
msg.push_back(u); /* store byte in msg */
}
std::cout << "string: " << s << "\nmsg:\n";
for (auto& h : msg)
std::cout << "\t" << std::setfill('0') << std::hex
<< std::setw(2) << (unsigned)h << '\n';
}
(output is the same as above)
If you can guarantee there will always be an even number of characters in your string (bytes only and no 1/2-byte as the final-odd character), you can further optimize by removing the conditional and simply using:
uint8_t u = c2hex (n[1]) | (c2hex (*n) << 4);
Make sure you are compiling with full optimization, e.g. -O3 (or -Ofast gcc version >= 4.6) on gcc/clang and /Ox with VS.
Give that a try and compare performance, you can additionally dump the differing versions to assembly and see if there are any additional hints there.

Scan string and store numbers and operations in different vectors C++

Suppose I have a string exp in the following format:
123+456*789-1011+1213
I want to store all the numbers in vector numbers, and all the operations in vector op.
vector<long long>numbers // {123, 456, 789, 1011, 1213}
vector<char>op // {+, *, -, +}
for (int i = 0; i < exp.size(); i++){
if (exp[i]=="+" || exp[i]=="-" || exp[i]=="*"){
op.push_back(exp[i]);
}else{
...
}
}
How do I store the numbers, and convert them from char to long long?
You will need to parse the input expression to extract the numbers and operator.
There are many ways by which this can be done, however following is my approach.
Traverse through all the character and push the values in Operator vector which is not a digit and replace it with space.
Now extract the numbers from the expression and convert it to numbers and push the values in Number vector.
To know how to split a string you can check the following links:
Split a string - Stack overflow
Split a string - cplusplus.com
Use stol or strtol or string stream to convert string to long value.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
int main()
{
std::string exp = "123+456*789-1011+1213";
std::vector<long> vecNums;
std::vector<char> vecOper;
for (decltype(exp.size()) i = 0; i < exp.size(); ++i) {
if (!isdigit(exp[i])) {
vecOper.push_back(exp[i]);
exp[i] = ' ';
}
}
std::istringstream iss(exp);
while (iss) {
std::string substr;
long num;
std::getline(iss, substr, ' ');
if (substr.size() != 0) {
// Using strtol function
// num = strtol(substr.c_str(), NULL, 10);
// Using stol function
num = stol(substr);
vecNums.push_back(num);
}
//
// Or use string stream to convert string to long
//
//long num;
//iss >> num;
//vecNums.push_back(num);
}
std::cout << "Numbers: " << std::endl;
for (auto &i : vecNums) {
std::cout << i << " ";
}
std::cout << "\nOperators: " << std::endl;
for (auto &i : vecOper)
std::cout << i << " ";
return 0;
}
If you're going to use iostreams:
void parse_string(const string& s) {
using num_t = long long;
using op_t = char;
istringstream sstr(s);
vector<num_t> numbers;
vector<op_t> ops;
(void)sstr.peek(); //set eofbit if s.empty()
while (!sstr.eof() && !sstr.fail()) {
num_t num;
sstr >> num;
if (!sstr.fail()) {
numbers.push_back(num);
if (!sstr.eof()) {
op_t op;
sstr >> op;
if (!sstr.fail()) {
ops.push_back(op);
}
}
}
}
//assert(ops.size() + 1 == numbers.size());
//copy(begin(numbers), end(numbers), ostream_iterator<num_t>(cout, " "));
//copy(begin(ops), end(ops), ostream_iterator<op_t>(cout, " "));
}
Error checking code as been removed (validate operators are correct, exceptions).

reading in ascii characters from a file and then turning them into a bit string c++

So i have ascii characters ãÅT on a file and I was trying to convert them back to a binary string (so the binary strings it should give back are (respectively): "11100011", "11000101", "01010100"). How would you read in unsigned char (bytes) and then convert them to a bitstring? Any detailed tutorial links and/or advice would help! Thank you!
---edit -----
so here is some code I'm playing with that gets the characters I was mentioning (part of a question I asked on c++ bitstring to byte).
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <bitset>
#include <vector>
#include <stdio.h>
using namespace std;
void main(){
ofstream outf;
outf.open("test.outf", std::ofstream::binary);
ifstream inf;
//given string of 1's and 0's, broke them down into substr
//of 8 and then used a bitset to convert them to a byte
//character on the output file
string bitstring = "11100011110001010101010";
unsigned char byte = 0;
cout << bitstring.length() << endl;
for (int i = 0 ; i < bitstring.length(); i += 8){
string stringof8 = "";
if (i + 8 < bitstring.length()){
stringof8 = bitstring.substr(i, 8);
cout << stringof8 << endl;
}
else
stringof8 = bitstring.substr(i);
if (stringof8.size() < 8){
stringof8 += "0";
cout << stringof8 << endl;
}
bitset<8> b(stringof8);
byte = (b.to_ulong()&0xFF);
outf.put(byte);
}
cout << endl;
system("pause");
}
i tried to get the bitstring back. When I look at the binary mode of notepad++ , it shows the same binary strings (if i broke them up into 8 pieces).
You can convert it bit by bit. Another approach is converting decimal number to binary number.
Updated:
string convert(unsigned char c){
string bitstr(8,'0');
int n = 7;
while(n >= 0){
bitstr[7-n] = (c >> n) & 1 ? '1' : '0';
--n;
}
return bitstr;
}
string convert10To2(unsigned char c){
string bitstr = "";
int val = c;
int base = 128;
int n = 8;
while(n-- > 0){
bitstr.append(1, (val/base + '0'));
val %= base;
base /= 2;
}
return bitstr;
}
int main() {
ofstream out;
out.open("data.txt");
char ccc = (char)227;
out << ccc;
out.close();
ifstream in;
in.open("data.txt");
int ival = in.get();
char c = ival;
cout<<convert(c)<<endl; //output: 11100011
cout<<convert10To2(c)<<endl; //output: 11100011
return 0;
}
Just store the characters in an a character array and use the bitset function like so.
#include <bitset>
char bbb[3] = {'b', 'f', 't'};
for (std::size_t i = 0; i < 3; ++i)
{
cout << bitset<8>(bbb[i]) << endl;
}
}

How do you parse a c-string?

Hi I'm trying to take a c-string from a user, input it into a queue, parse the data with a single space depending on its contents, and output the kind of data it is (int, float, word NOT string).
E.g. Bobby Joe is 12 in 3.5 months \n
Word: Bobby
Word: Joe
Word: is
Integer: 12
Word: in
Float: 3.5
Word: months
Here's my code so far:
int main()
{
const int maxSize = 100;
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
std::cin.getline(cstring, maxSize, '\n');
//Keyboard Buffer Function
buffer::keyboard_parser(cstring);
return EXIT_SUCCESS;
}
Function:
#include <queue>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
namespace buffer
{
std::string keyboard_parser(char* input)
{
//Declare Queue
std::queue<std::string> myQueue;
//Declare String
std::string str;
//Declare iStringStream
std::istringstream isstr(input);
//While Loop to Read iStringStream to Queue
while(isstr >> str)
{
//Push onto Queue
myQueue.push(str);
std::string foundDataType = " ";
//Determine if Int, Float, or Word
for(int index = 0; index < str.length(); index++)
{
if(str[index] >= '0' && str[index] <= '9')
{
foundDataType = "Integer";
}
else if(str[index] >= '0' && str[index] <= '9' || str[index] == '.')
{
foundDataType = "Float";
break;
}
else if(!(str[index] >= '0' && str[index] <= '9'))
{
foundDataType = "Word";
}
}
std::cout << "\n" << foundDataType << ": " << myQueue.front();
std::cout << "\n";
//Pop Off of Queue
myQueue.pop();
}
}
}
Right now with this code, it doesn't hit the cout statement, it dumps the core.
I've read about using the find member function and the substr member function, but I'm unsure of how exactly I need to implement it.
Note: This is homework.
Thanks in advance!
UPDATE: Okay everything seems to work! Fixed the float and integer issue with a break statement. Thanks to everyone for all the help!
Your queue is sensible: it contains std::strings. Unfortunately, each of those is initialised by you passing cstring in without any length information and, since you certainly aren't null-terminating the C-strings (in fact, you're going one-off-the-end of each one), that's seriously asking for trouble.
Read directly into a std::string.
std::istreams are very useful for parsing text in C++... often with an initial read of a line from a string, then further parsing from a std::istringstream constructed with the line content.
const char* token_type(const std::string& token)
{
// if I was really doing this, I'd use templates to avoid near-identical code
// but this is an easier-to-understand starting point...
{
std::istringstream iss(token);
int i;
char c;
if (iss >> i && !(iss >> c)) return "Integer";
}
{
std::istringstream iss(token);
float f;
char c; // used to check there's no trailing characters that aren't part
// of the float value... e.g. "1Q" is not a float (rather, "word").
if (iss >> f && !(iss >> c)) return "Float";
}
return "Word";
}
const int maxSize = 100; // Standard C++ won't let you create an array unless const
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
if (std::cin.getline(cstring, maxSize, '\n'))
{
std::istringstream iss(cstring);
std::string token;
while (iss >> token) // by default, streaming into std::string takes a space-...
token_queue.push(token); // ...separated word at a time
for (token_queue::const_iterator i = token_queue.begin();
i != token_queue.end(); ++i)
std::cout << token_type(*i) << ": " << *i << '\n';
}

What is simple way to read in randomly placed characters line by line?(C++)

It should ignore spaces and read in 2 characters.
My code to read it:
#include <iostream>
using namespace std ;
int main(){
char current_char1 ;
char current_char2 ;
//input comes from stdin
while(getc() != '\0'){
current_char1 = getc() ;
current_char2 = getc() ;
}
}
Can you show simpler way to do it?
To read two numbers from a single line, no matter the number of spaces, this will be fine:
std::string line;
std::getline(std::cin, line);
std::istringstream iss(line);
int a, b;
iss >> std::hex >> a >> b;
std::cout << "First value is " << a << ", the second value is " << b << '\n';
You are writing C++, but nonetheless, many tasks are easier with stdio.h than iostream, and this is one of them.
#include <ctype.h>
#include <stdio.h>
#include <string>
using std::string;
// Returns the next two non-`isspace` characters as a std::string.
// If there aren't that many before EOF, returns all that there are.
// Note: line boundaries ('\n') are ignored just like all other whitespace.
string
read_next_two_nonspace(FILE *fp)
{
string s;
int c;
do c = getc(fp);
while (c != EOF && isspace(c));
if (c != EOF) s.append(1, c);
do c = getc(fp);
while (c != EOF && isspace(c));
if (c != EOF) s.append(1, c);
return s;
}
EDIT: If what you actually want is to read two hexadecimal numbers from a line-oriented file that is supposed to have two such numbers per line and may have random amounts of whitespace around them, then this is my preferred method. Joachim's method is shorter, but less reliable; in particular, iostreams cannot be used safely for numeric input (!) owing to their being defined in terms of scanf, which provokes undefined behavior (!!) upon numeric overflow. This is more code but handles arbitrarily malformed input. Again, note free mixing of C++ and C library facilities -- there is no reason not to use the older library if it does what you need, as it does in this case.
Preamble:
#include <istream>
#include <stdexcept>
#include <string>
#include <vector>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
using std::getline;
using std::invalid_argument;
using std::istream;
using std::vector;
using std::string;
struct two_numbers { unsigned long a; unsigned long b; };
Parser:
#define isspace_or_eol(c) (isspace(c) || (c) == '\0')
// Parse a line consisting of two hexadecimal numbers, separated and surrounded
// by arbitrary whitespace.
two_numbers
parse_line(string const &s)
{
const char *p;
char *endp;
two_numbers val;
// N.B. strtoul skips *leading* whitespace.
errno = 0;
p = s.c_str();
val.a = strtoul(p, &endp, 16);
if (endp == p || !isspace_or_eol(*endp) || errno)
throw invalid_argument("first number is missing, malformed, or too large");
p = endp;
val.b = strtoul(p, &endp, 16);
if (endp == p || !isspace_or_eol(*endp) || errno)
throw invalid_argument("second number is missing, malformed, or too large");
// Verify only whitespace after the second number.
p = endp;
while (isspace(*p)) p++;
if (*p != '\0')
throw invalid_argument("junk on line after second number");
return val;
}
Example usage:
vector<two_numbers>
read_file(istream &fp, const char *fname)
{
string line;
unsigned int lineno = 0;
vector<two_numbers> contents;
bool erred = false;
while (getline(fp, line))
{
lineno++;
try
{
contents.append(parse_line(line));
}
catch (invalid_argument &e)
{
std::cerr << fname << ':' << lineno << ": parse error: "
<< e.what() << '\n';
erred = true;
}
}
if (erred)
throw invalid_argument("parse errors in file");
return contents;
}
You can try the code below, a small modification based on Zack's
#include "stdafx.h"
#include <iostream>
using namespace std;
bool read(FILE * fp, string * ps)
{
char c = fgetc(fp);
if(c == EOF)
return false;
if(isspace(c))
{
ps->clear();
return read(fp, ps);
}
if(isdigit(c))
{
ps->append(1, c);
if(ps->length() == 2)
return true;
}
return read(fp, ps);
}
int _tmain(int argc, _TCHAR* argv[])
{
FILE * file;
fopen_s(&file, "YOURFILE", "r");
string s;
while(read(file, &s))
{
cout<<s.c_str()<<endl;
s.clear();
}
return 0;
}