Are there any possibilities to put "%X" in write() function to get hex number of ascii characters?
Like in printf("Hex number of .. : %X").
Thank you in advance!
Are there any possibilities to put "%X" in write() function to get hex number of ascii characters?
Like in printf("Hex number of .. : %X").
Thank you in advance!
Are there any possibilities to put "%X" in write() function to get hex number of ascii characters?
No. The %X
is a specific characteristic of the printf
family of formatted output functions. (The 'f' is mnemonic for "formatted".) write()
performs raw output -- exactly the bytes you specify. If you want to use write()
then you will have to perform the formatting yourself, which I suppose is a large part of the point of the assignment.
You need to write your own function.
char toHexDigit(int x)
{
char result;
if(x > 15) x = 0;
if((x >= 0 && x < 10)) result = '0' + x;
else result = 'A' + x - 10;
return result;
}
char *tohex(unsigned x)
{
static char buff[sizeof(x)*2];
for(ssize_t i = 0; i < sizeof(x) * 2; i++)
{
int shift = (sizeof(x) * 2 - i - 1) * 4;
buff[i] = toHexDigit((x & (0xf << shift)) >> shift);
}
return buff;
}
int main(void)
{
write(1, tohex(0xD2A45678), sizeof(unsigned)*2);
}
Since write
does not take format string and additional arguments, you have to either use printf
, or implement your own function that takes an integer and translates it into the hex representation.
Below I describe how to write your own %X
-like output and how it works.
You can convert an integer (and therefore the hex code of a character) into a hex string by dividing the number by 16 and taking the modulo of it repeatedly.
For example, let's consider the value of 'A'
, which is 41
in hex. The remainder of division of that number by 16 is equal to the value of its last digit -- 1
. Then if we divide the value 0x41
by 16, we get the same number without the last digit -- 0x4
.
One can think of a step of such iteration:
int valueToConvert = 'A';
int lastHexDigit = valueToConvert % 16; // get the value of the last hex digit
valueToConvert = valueToConvert / 16; // save the remainder of the number
That gets us the value of the last hex digit (as integer).
Now we want to convert the integer value of this digit to char
, i.e. converting the value 0
to '0'
. Since characters in ASCII are stored consecutively we can get the value of digit by adding '0'
to the integer value we wish to convert.
char charDigit = '0' + digitValue;
The code snippet above will work only for digitValue
less or equal to 9
. For digits A
through F
we need to add a condition and if digitValue
is bigger than 9
we are going to (using the same logic), subtract 10
from digitValue and then add 'A'
to it. Since alphabetical characters are also consecutive in ASCII codes we can freely use digitValue-10
as an offset from 'A'
character.
char charDigit;
if (digitValue < 10) {
charDigit = '0' + digitValue;
}
else {
charDigit = 'A' + (digitValue-10);
}
So if digitValue
is 0xA (10), then digitValue-10
is 0
, and adding 0
to 'A'
just leaves us with 'A'
.
By taking modulo of division by 16, we get the least significant (right most) hexadecimal digit. However printing the string is done from left to right, not from right to left.
So in order to print a string representation we would need to have some sort of buffer to store all of our right most characters. Just remember this -- no int
value will have more than 8 hexadecimal digits, so we can freely allocate an array of 8 chars.
char digits[8];
int digitIndex = 8;
The digitIndex
will keep track of which array slot we write in. Note that it is set to 8
, not 7
, this is for a reason I will explain later.
Now let us put back the code from before -- we will use a do/while
to "put the last digit into the last spot of the array until the remainder is zero".
int valueToConvert = ...; // leaving the declaration here for clarity
do {
// Get the value of the last digit
int lastDigit = valueToConvert % 16;
// Convert the last digit to char
char charDigit;
if (lastDigit < 10) {
charDigit = '0' + lastDigit;
}
else {
charDigit = 'A' + (lastDigit-10);
}
// Put the last digit into the array
digitIndex -= 1;
digits[digitIndex] = charDigit;
valueToConvert /= 16;
} while(valueToConvert != 0);
This should produce the hex value corresponding to a given int
, assuming valueToConvert
is not negative.
Now let me explain why I'm subtracting the index first: we will use the value of digits+digitIndex
(which is a char *
) as the starting point of our array of digits. If I subtract first and then put the digit at that spot, that guarantees that when the loop exits, digitIndex
is over the first digit, which is very convenient.
Now let us get the length of the array:
unsigned count = 8 - digitIndex;
Which is simply the size of our buffer minus the index of the first digit of the number in the array.
After converting the value to our digit array we simply call write
:
write(handle, digits+digitIndex, count);
void write_hex_of_int(int handle, int number)
{
char digits[8];
int digitIndex = 8;
// Fill the `digits` array with the digits of the number
int valueToConvert = number;
do {
// Get the value of the last digit
int lastDigit = valueToConvert % 16;
// Convert the last digit to char
char charDigit;
if (lastDigit < 10) {
charDigit = '0' + lastDigit;
}
else {
charDigit = 'A' + (lastDigit-10);
}
// Put the last digit into the array
digitIndex -= 1;
digits[digitIndex] = charDigit;
valueToConvert /= 16;
} while(valueToConvert != 0);
// Get the actual width of the number and print it.
unsigned count = 8 - digitIndex;
write(handle, digits+digitIndex, count);
}