Convert a string variable of two chars to hex - c++

I have code where the user inputs two chars into a string variable. I have a function that verifies that the user input is only two chars long, and that it only contains valid hexadecimal digits.
I want to write these digits to a binary file that's 32 bytes long. I tried:
outFile.write((char*)&string[0], 1);
In a loop that runs 32 times (I want to write one byte at a time) to test, but it just writes the ascii code for the char, not the actual char itself. I expected it to write a nybble and skip a nybble, but it wrote a full byte of ascii information instead. So I tried:
outFile.write((unsigned char*)&string[0], 1);
But my compiler complains about it being an invalid cast.
I want to solve this problem without converting the string into a c-style string. In other words, I want string to contain two chars and represent one byte of information. Not four (plus null characters).

You have a string that represents an integer. So convert the string to an integer:
unsigned char byte = (unsigned char)std::stoi(string, 0, 16);
outFile:write(static_cast<const char*>(&byte), 1);

As a workaround for your missing stoi you can do this:
#include <iostream>
#include <sstream>
#include <ios>
char hexnum[]{"2F"}; // or whatever, upper or lowercase hex digits allowed.
std::istringstream input(hexnum);
int num=0;
input >> std::hex >> num;
unsigned char byte = num;
outFile.write(static_cast<const char*>(&byte), 1);

Related

How to convert an array of ASCII codes to int C++

First of all, i would like to read from plain text, i read hundreds of webpages about it and i just can't make it. I want to read every byte of the file and every two byte is a number what i want to store.
I want to read: 10 20.
I get: ASCII code of 1, ASCII code of 0, ASCII code of space etc. etc.
I tried several things, like stream.get, or stream.read, tried to convert with atoi but then i can't concatenate the two digits, i tried sprintf but all of them failed.
Array of ASCII codes:
char ASCII[] = "10 20";
Convert to integer variables:
std::istringstream iss(ASCII);
int x,y;
iss >> x >> y;
Done.
Here's the working sample: http://ideone.com/y8ZRGs
If you want to do this with your own code, there are only two things you need to be able to do.
First, you need to convert from the ASCII code of a digit to the number it represents. This is as simple as subtracting '0'.
Second, you need to convert from the numerical value of each digit of a two digit number to the number that represents. This is simple -- if T is the tens place and U is the units, it's 10T + U.
So, for example:
int twoDigitNumber (char tens, char units)
{
return 10 * (tens - '0') + (units - '0');
}

How to read a binary number as input?

Is there a way for the user to input a binary number in C or C++?
If we write something like
int a = 0b1010;
std::cout << a << std::endl
Then the output comes out to be 10 (when using the appropriate compiler extensions).
but when we try to write
int n;
std::cin >> n;
int t = 0bn;
It gives us an error so can anyone suggest that how can we directly read binary number as input rather than using string to store input?
There is a bit of confusion here, let's disentangle it a bit.
0b1010 is an integer literal, a constant, compile-time integer value written in base 2. Likewise, 0xA is a literal in base 16 and 10 is in base 10. All of these refer to the same integer, it is just a different way of telling the compiler which number you mean. At runtime, in memory, this integer is always represented as a base-2 number.
std::cout << a; takes the integer value of a and outputs a string representation of it. By default it outputs it in base 10, but you can i.e use the std::hex modifier to have it output it in base 16. There is no predefined modifier to print in binary. So you need to do that on your own (or google it, it is a common question).
0b at last, is only used to define integer literals. It is not a runtime operator. Recall, all ints are represented as base 2 numbers in memory. Other bases do not exist from a machine point of view, int is int, so there is nothing to convert. If you need to read a binary number from a string, you would roll the reverse code to what you do to print it (std::cin >> n assumes that the input is a base 10 number, so it reads a wrong number if the input is actually intended to be in base 2).
While there is no function to read binary numbers directly, there are functions, strtox (where x represents the data type) to convert a string containing a binary number (or a number of any other base) to a numeric value.
So the solution is to first read the number as a string and then convert it.
Example:
char input[100];
char *endpointer;
<read input using either C or C++ syntax>
int n = (int) strtol(input, &endpointer, 2);
To take a binary number as input, there are two ways I use frequently:
(Keynote: Take the input as string!!! use: #include <string>)
The to_ulong() method of the bitset template of the bitset library
for this you need to include the bitset library using #include <bitset>
Example:
string s;
cin>>s; // Suppose s = "100100101"
int n = (int) bitset<64>(s).to_ulong();
cout<<n; // 293
Explore more about bitset here and about to_ulong() here.
The stoi() method of the string library
for this you need to include the string library using #include <string>
Example:
string s;
cin>>s; // Suppose s = "100100101"
int n = stoi(s, 0, 2);
cout<<n; // 293
Explore the format of stoi() here.
rather do it yourself:
uint32_t a = 0;
char c;
while ((c = getchar()) != '\n') { // read a line char by char
a <<= 1; // shift the uint32 a bit left
a += (c - '0') & 1; // convert the char to 0/1 and put it at the end of the binary
}
printf("%u\n", a);

Regarding conversion of text to hex via ASCII in C++

So, I've looked up how to do conversion from text to hexadecimal according to ASCII, and I have a working solution (proposed on here). My problem is that I don't understand why it works. Here's my code:
#include <string>
#include <iostream>
int main()
{
std::string str1 = "0123456789ABCDEF";
std::string output[2];
std::string input;
std::getline(std::cin, input);
output[0] = str1[input[0] & 15];
output[1] = str1[input[0] >> 4];
std::cout << output[1] << output[0] << std::endl;
}
Which is all well and good - it returns the hexadecimal value for single characters, however, what I don't understand is this:
input[0] & 15
input[0] >> 4
How can you perform bitwise operations on a character from a string? And why does it oh-so-nicely return the exact values we're after?
Thanks for any help! :)
In C++ a character is 8 bits long.
If you '&' it with 15 (binary 1111), then the least significant 4 bits are outputted to the first digit.
When you apply right shift by 4, then it is equivalent of dividing the character value by 16. This gives you the most significant 4 bits for second digit.
Once the above digit values are calculated, the required character is picked up from the constant string str1 having all the characters in their respective positions.
"Characters in a string" are not characters (individual strings of one character only). In some programming languages they are. In Javascript, for example,
var string = "testing 1,2,3";
var character = string[0];
returns "t".
In C and C++, however, 'strings' are arrays of 8-bit characters; each element of the array is an 8-bit number from 0..255.
Characters are just integers. In ASCII the character '0' is the integer 48. C++ makes this conversion implicitly in many contexts, including the one in your code.

convert char[] of hexadecimal numbers to char[] of letters corresponding to the hexadecimal numbers in ascii table and reversing it

I have a char a[] of hexadecimal characters like this:
"315c4eeaa8b5f8aaf9174145bf43e1784b8fa00dc71d885a804e5ee9fa40b16349c146fb778cdf2d3aff021dfff5b403b510d0d0455468aeb98622b137dae857553ccd8883a7bc37520e06e515d22c954eba5025b8cc57ee59418ce7dc6bc41556bdb36bbca3e8774301fbcaa3b83b220809560987815f65286764703de0f3d524400a19b159610b11ef3e"
I want to convert it to letters corresponding to each hexadecimal number like this:
68656c6c6f = hello
and store it in char b[] and then do the reverse
I don't want a block of code please, I want explanation and what libraries was used and how to use it.
Thanks
Assuming you are talking about ASCII codes. Well, first step is to find the size of b. Assuming you have all characters by 2 hexadecimal digits (for example, a tab would be 09), then size of b is simply strlen(a) / 2 + 1.
That done, you need to go through letters of a, 2 by 2, convert them to their integer value and store it as a string. Written as a formula you have:
b[i] = (to_digit(a[2*i]) << 4) + to_digit(a[2*i+1]))
where to_digit(x) converts '0'-'9' to 0-9 and 'a'-'z' or 'A'-'Z' to 10-15.
Note that if characters below 0x10 are shown with only one character (the only one I can think of is tab, then instead of using 2*i as index to a, you should keep a next_index in your loop which is either added by 2, if a[next_index] < '8' or added by 1 otherwise. In the later case, b[i] = to_digit(a[next_index]).
The reverse of this operation is very similar. Each character b[i] is written as:
a[2*i] = to_char(b[i] >> 4)
a[2*i+1] = to_char(b[i] & 0xf)
where to_char is the opposite of to_digit.
Converting the hexadecimal string to a character string can be done by using std::substr to get the next two characters of the hex string, then using std::stoi to convert the substring to an integer. This can be casted to a character that is added to a std::string. The std::stoi function is C++11 only, and if you don't have it you can use e.g. std::strtol.
To do the opposite you loop over each character in the input string, cast it to an integer and put it in an std::ostringstream preceded by manipulators to have it presented as a two-digit, zero-prefixed hexadecimal number. Append to the output string.
Use std::string::c_str to get an old-style C char pointer if needed.
No external library, only using the C++ standard library.
Forward:
Read two hex chars from input.
Convert to int (0..255). (hint: sscanf is one way)
Append int to output char array
Repeat 1-3 until out of chars.
Null terminate the array
Reverse:
Read single char from array
Convert to 2 hexidecimal chars (hint: sprintf is one way).
Concat buffer from (2) to final output string buffer.
Repeat 1-3 until out of chars.
Almost forgot to mention. stdio.h and the regular C-runtime required only-assuming you're using sscanf and sprintf. You could alternatively create a a pair of conversion tables that would radically speed up the conversions.
Here's a simple piece of code to do the trick:
unsigned int hex_digit_value(char c)
{
if ('0' <= c && c <= '9') { return c - '0'; }
if ('a' <= c && c <= 'f') { return c + 10 - 'a'; }
if ('A' <= c && c <= 'F') { return c + 10 - 'A'; }
return -1;
}
std::string dehexify(std::string const & s)
{
std::string result(s.size() / 2);
for (std::size_t i = 0; i != s.size(); ++i)
{
result[i] = hex_digit_value(s[2 * i]) * 16
+ hex_digit_value(s[2 * i + 1]);
}
return result;
}
Usage:
char const a[] = "12AB";
std::string s = dehexify(a);
Notes:
A proper implementation would add checks that the input string length is even and that each digit is in fact a valid hex numeral.
Dehexifying has nothing to do with ASCII. It just turns any hexified sequence of nibbles into a sequence of bytes. I just use std::string as a convenient "container of bytes", which is exactly what it is.
There are dozens of answers on SO showing you how to go the other way; just search for "hexify".
Each hexadecimal digit corresponds to 4 bits, because 4 bits has 16 possible bit patterns (and there are 16 possible hex digits, each standing for a unique 4-bit pattern).
So, two hexadecimal digits correspond to 8 bits.
And on most computers nowadays (some Texas Instruments digital signal processors are an exception) a C++ char is 8 bits.
This means that each C++ char is represented by 2 hex digits.
So, simply read two hex digits at a time, convert to int using e.g. an istringstream, convert that to char, and append each char value to a std::string.
The other direction is just opposite, but with a twist.
Because char is signed on most systems, you need to convert to unsigned char before converting that value again to hex digits.
Conversion to and from hexadecimal can be done using hex, like e.g.
cout << hex << x;
cin >> hex >> x;
for a suitable definition of x, e.g. int x
This should work for string streams as well.

Converting an unsigned char* to readable string & whats this function doing

I have googled alot to learn how to convert my unsigned char* to a printable hex string. So far I am slightly understanding how it all works & the difference between signed & unsigned chars.
Can you tell me what this function I found does? And help me devlop a function that converts a unsigned char*(which is a hashed string) to a printable string?
Does the following function do this:
- it iterates over every second character of the char array string
- on each loop it reads the char at the position string[x], converts it to an unsigned number(with a precision of 2 decimal places) then copies that converted char(number?) to the variables uChar.
- finally it stores the unsigned char uChar in hexstring
void AppManager :: stringToHex( unsigned char* hexString, char* string, int stringLength )
{
// Post:
unsigned char uChar = 0;
for ( int x = 0; x<stringLength; x+=2 )
{
sscanf_s(&string[x], "%02x", &uChar);
hexString[x] = uChar;
}
}
So I guess that means that it converts the character in string to unsigned(& 2dcp) to ensure that it can be correctly stored the hexstring. Why to 2 decimal places, & wont a simple conversion from signed(if that character is signed) to unsigned result in a completely different string?
If I have a unsigned char* how can I go about converting it to something that will let me print it out on screen?
Those aren't decimal places, they're digits. You're saying "don't give me a string shorter than 2; if it's shorter than 2 digits, then pad it with a zero."
This is so that if you have a hex sequence 0x0A it'll actually print 0A and not just A.
Also, there is no signed/unsigned conversion here. Hex strings are hex strings - they don't have a sign. They're a binary representation of the data, and depending on how they're interpreted may be read as two's complement signed integers, unsigned integers, strings, or anything else.