I have a query. I have a string of ascii value . which i am reading from Hex file. consider the string is "0004EB9C" . which is copied in unsigned char buffer.
unsigned char buff[8] = {'0','0','0','4','E','B','9','C'}
unsigned int j = 0;
Now this string or information has to be transmitted through UART communication. consider this represents my RAM address for Execution. I need to store this 8 byte ascii value in in an unsigned int . I am not finding a way can some one please focus on this.
the output after copying/converting this string should be like
printf("%x",j);
this should print
Output : 0x0004EB9C
thanks in advance!!
set answer to 0
for each character
left-shift answer by 4
if the character is between '0' and '9' inclusive
subtract '0' from it
else
subtract 'A' from it and add 10
bitwise-or this into answer
#include <stdio.h>
int main(){
char data[] = "004EB59C";
const int len = sizeof(data)/sizeof(char)-1;
int i,value[sizeof(data)/sizeof(char)-1];
unsigned int j = 0;
for(i=0;i<len;++i)
sscanf(data+i, "%1x",value + i);
for(i=0;i<len;i++)
{
j <<= 4;
j |= (0x0f & value[i]);
printf("%x\n",j);
}
return 0;
}
Corrected Code. I would request to improvise this answer if possible.
To store as unsigned j
unsigned char buff[8] = {'0','0','0','4','E','B','9','C'}
unsigned char buff2[sizeof buff + 1];
memcpy(buff2, buff, sizeof buff);
buff2[sizeof buff] = '\0';
unsigned int j = (unsigned) strtoul(buff2, 0, 16);
To print via j
printf("%#08x",j);
To print via directly via buff
fputs("0x", stdout);
for (size_t i = 0; i < sizeof buff; i++)
fputc(tolower(buff[i]), stdout);
Related
unsigned short num = 258;
//How can i read the byte value as on how this num 258 is getting store (by default is stored as litle indian right?) so the value should be something like this [ 2, 1 ]or [0x02,0x01] <- as litle endian
how do i printf it out?
A pointer to an unsigned char can be used to read the byte representation of an object.
unsigned char *p = (unsigned char *)#
int i;
for (i=0; i<sizeof num; i++) {
printf("%02x ", p[i]);
}
I have a unsigned char array containing the following value : "\x00\x91\x12\x34\x56\x78\x90";
That is number being sent in Hexadecimal format.
Additionally, it is in BCD format : 00 in byte, 91 in another byte (8 bits)
On the other side I require to decode this value as 0091234567890.
I'm using the following code:
unsigned int conver_bcd(char *p,size_t length)
{
unsigned int convert =0;
while (length--)
{
convert = convert * 100 + (*p >> 4) * 10 + (*p & 15);
++p
}
return convert;
}
However, the result which I get is 1430637214.
What I understood was that I'm sending hexadecimal values (\x00\x91\x12\x34\x56\x78\x90) and my bcd conversion is acting upon the decimal values.
Can you please help me so that I can receive the output as 00911234567890 in Char
Regards
Karan
It looks like you are simply overflowing your unsigned int, which is presumably 32 bits on your system. Change:
unsigned int convert =0;
to:
uint64_t convert = 0;
in order to guarantee a 64 bit quantity for convert.
Make sure you add:
#include <stdint.h>
Cast char to unsigned char, then print it with %02x.
#include <stdio.h>
int main(void)
{
char array[] = "\x00\x91\x12\x34\x56\x78\x90";
int size = sizeof(array) - 1;
int i;
for(i = 0; i < size; i++){
printf("%02x", (unsigned char )array[i]);
}
return 0;
}
Change return type to unsigned long long to insure you have a large enough integer.
Change p type to an unsigned type.
Print value with leading zeros.
unsigned long long conver_bcd(const char *p, size_t length) {
const unsigned char *up = (const unsigned char*) p;
unsigned long long convert =0;
while (length--) {
convert = convert * 100 + (*up >> 4) * 10 + (*up & 15);
++up;
}
return convert;
}
const char *p = "\x00\x91\x12\x34\x56\x78\x90";
size_t length = 7;
printf( "%0*llu\n", (int) (length*2), conver_bcd(p, length));
// 00911234567890
I need some help in cutting a string into a pair of characters and then converting it to HEX format.
eg. char *ADDRESS = "0011AABB";
I want the above address to be split "00", "11", "AA" and "BB" and after that is split converting it to 0x00, 0x11, 0xAA and 0xBB which will be stored in an unsigned char.
Thanks
You suggest that your address-strings are of type char *, but I assume you
want a solution that gaurantees not to trash them, i.e. one that takes them
as type char const *.
I assume also that the addresses they can represent are 32-bit, as per the
example char *ADDRESS = "0011AABB".
In that case a solution that does exactly what you ask for in an obvious
way is:
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define ADDRESS_BYTES 4 // Bytes in an address
/* Convert a hex numeral encoding an address to the unsigned chars that it
encodes
`addr_str` - in: a hex numeral encoding an address
`bytes` - out: The unsigned char bytes of the address, high-byte first.
return - The number of bytes output: ADDRESS_BYTES if `addr_str` is a
valid hex numeral, otherwise 0.
*/
unsigned address_bytes(char const *addr_str, unsigned char bytes[ADDRESS_BYTES])
{
char buf[3] = {0}; // 3-bytes of 0-filled working space.
char *endp;
unsigned i = 0;
unsigned j = 0;
assert(strlen(addr_str) == 2 * ADDRESS_BYTES); // Insist on 8-char string
for ( ;i < 2 * ADDRESS_BYTES; ++j) { // Take chars 2 at a time
buf[i % 2] = addr_str[i]; ++i; // Next char to buf[0]
buf[i % 2] = addr_str[i]; ++i; // Next + 1 char to buf[1]
// Convert buffer from hex numeral to unsigned char in next byte.
bytes[j] = (unsigned char)strtoul(buf,&endp,16);
if (*endp) { // Check for invalid hex.
return 0; // Failure
}
}
return j; // = 4
}
// A test program...
#include <stdio.h>
int main(void)
{
unsigned char bytes[ADDRESS_BYTES];
char const * address = "0011AABB";
unsigned done_bytes = address_bytes(address,bytes);
printf("The %d valid address bytes are (hex):",done_bytes);
unsigned i = 0;
for ( ;i < done_bytes; ++i) {
printf(" %02x",(unsigned)bytes[i]);
}
putchar('\n');
return 0;
}
However, exactly what you ask for is not an efficient solution.
You can accomplish your goal by simply converting an 8-char hex-numeral encoding
a 32-bit address into the encoded 32-bit unsigned integer, and then getting the
4 unsigned char bytes that compose this unsigned integer in high-byte-first order.
Converting the hex numeral to a uint32_t can be done with a single call to
strtoul. Then getting the unsigned char bytes of this uint32_t in
high-byte-first order is simply a matter of knowing whether that uint32_t is
big-endian or little-endian. So here is a better solution:
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
unsigned address_bytes(char const *address, unsigned char bytes[ADDRESS_BYTES])
{
union {
uint32_t i;
char c[ADDRESS_BYTES];
} endian_tester = {0x01020304};
int big_endian = endian_tester.c[0] == 1;
uint32_t addr = 1;
char *endp;
assert(strlen(address) == 2 * ADDRESS_BYTES);
addr = (uint32_t)strtoul(address,&endp,16);
if (*endp) {
return 0;
}
endp = (char *)&addr;
if (big_endian) {
// The least significant byte is highest in memory
bytes[0] = endp[0];
bytes[1] = endp[1];
bytes[2] = endp[2];
bytes[3] = endp[3];
} else {
// The least significant byte is lowest in memory
bytes[0] = endp[3];
bytes[1] = endp[2];
bytes[2] = endp[1];
bytes[3] = endp[0];
}
return ADDRESS_BYTES;
}
And if you are able and willing to make the non-portable assumption that
the address-strings are encoded in ASCII, then you could avoid calling
strtoul entirely and compute the output bytes directly from the input
chars, using the characters' positions in the ASCII collating sequence
to get the unsigned char values that they encode:
#include <assert.h>
#include <string.h>
#include <ctype.h>
unsigned address_bytes(char const *address, unsigned char bytes[ADDRESS_BYTES])
{
unsigned i = 0;
unsigned j = 0;
assert(strlen(address) == 2 * ADDRESS_BYTES);
for ( ; i < 2 * ADDRESS_BYTES; ++i,++j) {
// First character of a pair..
if (isdigit(address[i])) {
// A decimal digit encodes its ASCII value - '0'
bytes[j] = address[i] - '0';
} else if (isxdigit(address[i])) {
// A hex digit encodes 10 + its ASCII value - 'A'
bytes[j] = 10 + address[i] - 'A';
} else {
return 0; // Invalid hex
}
++i; // Second character of a pair...
bytes[j] <<= 4; // Shift the 1st character's value 1 nibble high
// OR the 2nd character's value into the low nibble of the byte...
if (isdigit(address[i])) {
bytes[j] |= address[i] - '0';
} else if (isxdigit(address[i])) {
bytes[j] |= 10 + address[i] - 'A';
} else {
return 0; // Invalid hex
}
}
return ADDRESS_BYTES;
}
The last might be the fastest if that matters.
Built and tested with GCC 4.7.2 and clang 3.2
I have a string (unsigned char) and i want to fill it with only hex characters.
my code is
unsigned char str[STR_LEN] = {0};
for(i = 0;i<STR_LEN;i++) {
sprintf(str[i],"%x",rand()%16);
}
Of course, when running this I get segfaulted
string is an array of char-s not unsigned char-s
you are using str[i] (which is of type unsigned char) as a 1st argument to sprintf, but it requires type char * (pointer).
This should be a little better:
char str[STR_LEN + 1];
for(i = 0; i < STR_LEN; i++) {
sprintf(str + i, "%x", rand() % 16);
}
The first argument to sprintf() should be a char*, but str[i] is a char: this is the cause of the segmentation fault. The compiler should have emitted a warning about this. gcc main.c, without specifying a high warning level, emitted the following:
warning: passing argument 1 of sprintf makes pointer from integer without a cast
A hex representation of a character can be 1 or 2 characters (9 or AB for example). For formatting, set the precision to 2 and the fill character to 0. Also need to add one character for the terminating null to str and set the step of the for loop to 2 instead of 1 (to prevent overwriting previous value):
unsigned char str[STR_LEN + 1] = {0};
int i;
for (i = 0; i < STR_LEN; i += 2)
{
sprintf(&str[i], "%02X", rand() % 16);
}
You could try something like this:
#include <stdio.h>
#include <stdlib.h>
#define STR_LEN 20
int main(void)
{
unsigned char str[STR_LEN + 1] = {0};
const char *hex_digits = "0123456789ABCDEF";
int i;
for( i = 0 ; i < STR_LEN; i++ ) {
str[i] = hex_digits[ ( rand() % 16 ) ];
}
printf( "%s\n", str );
return 0;
}
There are several unclarities and problems in your code. I interpret "hex character" to mean "hex digit", i.e. a symbol from {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}, not "the hexadecimal value of an ascii character's code point". This might or might not be what you meant.
This should do it:
void hex_fill(char *buf, size_t max)
{
static const char hexdigit[16] = "0123456789abcdef";
if(max < 1)
return;
--max;
for(i = 0; i < max; ++i)
buf[i] = hexdigit[rand() % sizeof hexdigit];
buf[max] = '\0';
}
The above will always 0-terminate the string, so there's no requirement that you do so in advance. It will properly handle all buffer sizes.
My variation on some of answers below; note the time seeded rand function and instead of a char using a const size, I use a vector that is then converted to a string array.
Boost variate generator docs
std::string GetRandomHexString(unsigned int count)
{
std::vector<char> charVect = std::vector<char>(count);
//Rand generator
typedef boost::random::mt19937 RNGType;
RNGType rng(std::time(nullptr) + (unsigned int)clock());
//seeding rng
uniform_int<> range(0, 15); //Setting min max
boost::variate_generator<RNGType, boost::uniform_int<> >generate(rng, range); //Creating our generator
//Explicit chars to sample from
const char hexChars[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
//
for (int i = 0; i < count; i++)
{
charVect[i] = hexChars[generate()];
}
//
return std::string(charVect.begin(), charVect.end());;
}
Examples (count = 32):
1B62C49C416A623398B89A55EBD3E9AC
26CFD2D1C14B9F475BF99E4D537E2283
B8709C1E87F673957927A7F752D0B82A
DFED20E9C957C4EEBF4661E7F7A58460
4F86A631AE5A05467BA416C4854609F8
So for some reason, all these UNICODE characters appear to have the same value when i print them out in C Does anyone have any idea why?
char input[8] = {'⺖', '⺓', '⺄', '⺑', '⻣', '⺽', '', '⺽'};
for( i = 0; i < 9; i++)
{
printf("Input number equivelents in hex %x, in int %i\nj", input[i], (int)input[i]);
}
This is what the UNICODE corresponds to in C#. in C they print out as 0x3f.
C#
[0x00000000] 0x2e96 '⺖' char
[0x00000001] 0x2e93 '⺓' char
[0x00000002] 0x2e84 '⺄' char
[0x00000003] 0x2e91 '⺑' char
[0x00000004] 0x2ee3 '⻣' char
[0x00000005] 0x2ebd '⺽' char
[0x00000006] 0x2efb '' char
[0x00000007] 0x2ebd '⺽' char
You also need to precede each constant with L:
wchar_t input[8] = {L'⺖', L'⺓', L'⺄', L'⺑', L'⻣', L'⺽', L'', L'⺽'};
for( i = 0; i < 9; i++)
{
printf("Hex: %x, Int: %i\n", input[i], (int)input[i]);
}
You need another data structure to hold those characters, as one char (which is traditionally 8 bits, or 0x00 - 0xFF) cannot contain them.
Thus, use a data-structre like int or short to hold them, and use the L specifier before the literal:
int input[8] = { L'⺖', L'⺓', L'⺄', L'⺑', L'⻣', L'⺽', L'', L'⺽' };
And your code will work properly.