I know there's other posts like this but I think mine is different. I have a group of numbers I wish to display. However, it's saved as unsigned short. As it's given to me from a network buffer, all my data is unsigned short format. So for a serial number starting with "ABC-" the two unsigned shorts will be holding 0x4142 and 0x432D (Already in ASCII format). I need to convert those to type char to display using printf and %s, but for the rest of my system, they need to remain as an unsigned short. This is what I've tried so far, but the output is blank:
unsigned char * num[3];
num[0] = (unsigned char*)(SYSTEM_N >> 8);
num[1] = (unsigned char*)(SYSTEM_N & 0x00FF);
printf("System Number: %s \r\n", num);
Can anyone shed some light on this for me? Thanks!
There are several errors: 1) array is too short, 2) defining the array as an array of pointers and 3) not terminating the string.
#include <stdio.h>
int main (void)
{
unsigned short system_m = 0x4142;
unsigned short system_n = 0x432D;
unsigned char num[5];
num[0] = system_m >> 8;
num[1] = system_m & 0xFF;
num[2] = system_n >> 8;
num[3] = system_n & 0xFF;
num[4] = '\0';
printf("System Number: %s \r\n", num);
return 0;
}
EDIT alternatively if you don't want to keep the string, just display the information with this:
#include <stdio.h>
int main (void)
{
unsigned short system_m = 0x4142;
unsigned short system_n = 0x432D;
printf("System Number: %c%c%c%c \r\n",
system_m >> 8, system_m & 0xFF, system_n >> 8, system_n & 0xFF);
return 0;
}
Program output:
System Number: ABC-
You probably meant to write
unsigned char num[3];
as you have it, you declare an array holding three char* pointers.
Also don't forget to set the closing NUL character, before printing:
num[2] = '\0';
A general solution might be something like this, assuming ushort_arr contains the unsigned shorts in an array and ushort_arr_size indicates its size.
char *str = malloc(ushort_arr_size * 2 + 1);
// check if str == NULL
int j = 0;
for (int i = 0; i < ushort_arr_size; i++) {
str[j++] = ushort_arr[i] >> 8;
str[j++] = ushort_arr[i];
}
str[j] = '\0';
printf("string is: %s\n", str);
free(str);
Though perhaps this might be more effective without the memory management, if you only want to print it once:
for (int i = 0, j = 0; i < ushort_arr_size; i++) {
putchar(ushort_arr[i] >> 8);
putchar(ushort_arr[i] & 0xFF);
}
Related
I want to convert the hexadecimal string value 0x1B6 to unsigned char - where it will store the value in the format 0x1B, 0x60 We had achieved the scenarios in C++, but C doesn't support std::stringstream.
The following code is C++, how do I achieve similar behavior in C?
char byte[2];
std::string hexa;
std::string str = "0x1B6" // directly assigned the char* value in to string here
int index =0;
unsigned int i;
for(i = 2; i < str.length(); i++) {
hexa = "0x"
if(str[i + 1] !NULL) {
hexa = hexa + str[i] + str[i + 1];
short temp;
std::istringstream(hexa) >> std::hex >> temp;
byte[index] = static_cast<BYTE>(temp);
} else {
hexa = hexa+ str[i] + "0";
short temp;
std::istringstream(hexa) >> std::hex >> temp;
byte[index] = static_cast<BYTE>(temp);
}
}
output:
byte[0] --> 0x1B
byte[1]--> 0x60
I don't think your solution is very efficient. But disregarding that, with C you would use strtol. This is an example of how to achieve something similar:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void) {
const char *hex_string = "0x1B60";
long hex_as_long = strtol(hex_string, NULL, 16);
printf("%lx\n", hex_as_long);
// From right to left
for(int i = 0; i < strlen(&hex_string[2]); i += 2) {
printf("%x\n", (hex_as_long >> (i * 4)) & 0xff);
}
printf("---\n");
// From left to right
for(int i = strlen(&hex_string[2]) - 2; i >= 0; i -= 2) {
printf("%x\n", (hex_as_long >> (i * 4)) & 0xff);
}
}
So here we get the full value as a long inside hex_as_long. We then print the whole long with the first print and the individual bytes inside the second for loop. We are shifting multiples of 4 bits because one hex digit (0xf) covers exactly 4 bits of data.
To get the bytes or the long printed to a string rather than to stdout (if that is what you want to achieve), you can use strprintf or strnprintf in a similar way to how printf is used, but with a variable or array as destination.
This solution scans whole bytes (0xff) at a time. If you need to handle one hex digit (0xf) at a time you can divide all the operations by two and mask with 0xf instead of 0xff.
How can I convert an unsigned char array that contains letters into an integer. I have tried this so for but it only converts up to four bytes. I also need a way to convert the integer back into the unsigned char array .
int buffToInteger(char * buffer)
{
int a = static_cast<int>(static_cast<unsigned char>(buffer[0]) << 24 |
static_cast<unsigned char>(buffer[1]) << 16 |
static_cast<unsigned char>(buffer[2]) << 8 |
static_cast<unsigned char>(buffer[3]));
return a;
}
It looks like you're trying to use a for loop, i.e. repeating a task over and over again, for an in-determinant amount of steps.
unsigned int buffToInteger(char * buffer, unsigned int size)
{
// assert(size <= sizeof(int));
unsigned int ret = 0;
int shift = 0;
for( int i = size - 1; i >= 0, i-- ) {
ret |= static_cast<unsigned int>(buffer[i]) << shift;
shift += 8;
}
return ret;
}
What I think you are going for is called a hash -- converting an object to a unique integer. The problem is a hash IS NOT REVERSIBLE. This hash will produce different results for hash("WXYZABCD", 8) and hash("ABCD", 4). The answer by #Nicholas Pipitone DOES NOT produce different outputs for these different inputs.
Once you compute this hash, there is no way to get the original string back. If you want to keep knowledge of the original string, you MUST keep the original string as a variable.
int hash(char* buffer, size_t size) {
int res = 0;
for (size_t i = 0; i < size; ++i) {
res += buffer[i];
res *= 31;
}
return res;
}
Here's how to convert the first sizeof(int) bytes of the char array to an int:
int val = *(unsigned int *)buffer;
and to convert in back:
*(unsigned int *)buffer = val;
Note that your buffer must be at least the length of your int type size. You should check for this.
I'm trying to figure out how to most efficiently parse the following into Hex segments with c++ 98.
//One lump, no delemiters
char hexData[] = "50FFFEF080";
and want parse out 50 FF FE & F080 (assuming I know hexData will be in this format every time) into base 10. Yielding something like:
var1=80
var2=255
var3=254
var4=61568
Here's one strategy.
Copy the necessary characters one at a time to a temporary string.
Use strtol to extract the numbers.
Program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char hexData[] = "50FFFEF080";
int i = 0;
int var[4];
char temp[5] = {};
char* end = NULL;
for ( i = 0; i < 3; ++i )
{
temp[0] = hexData[i*2];
temp[1] = hexData[i*2+1];
var[i] = (int)strtol(temp, &end, 16);
printf("var[%d]: %d\n", i, var[i]);
}
// The last number.
temp[0] = hexData[3*2];
temp[1] = hexData[3*2+1];
temp[2] = hexData[3*2+2];
temp[3] = hexData[3*2+3];
var[3] = (int)strtol(temp, &end, 16);
printf("var[3]: %d\n", var[3]);
return 0;
}
Output:
var[0]: 80
var[1]: 255
var[2]: 254
var[3]: 61568
You can convert all string to number and then use bitwise operations to get any bytes or bits. Try this
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char hexData[] = "50FFFEF080";
uint64_t number; // 64bit number
// conversion from char-string to one big number
sscanf(hexData, "%llx", &number); // read as a hex number
uint64_t tmp = number; // just a copy of initial number to make bitwise operations
// use masks to get particular bytes
printf("%lld \n", tmp & 0xFFFF); // prints last two bytes as decimal number: 61568
// or copy to some other memory
unsigned int lastValue = tmp & 0xFFFF; // now lastValue has 61568 (0xF080)
tmp >>= 16; // remove last two bytes with right shift
printf("%lld \n", tmp & 0xFF); // prints the last byte 254
tmp >>= 8; // remove lass byte with right shift
printf("%lld \n", tmp & 0xFF); // prints 255
tmp >>= 8; // remove lass byte with right shift
printf("%lld \n", tmp & 0xFF); // prints 80
return 0;
}
#include <iostream>
#include <string>
int main() {
std::istringstream buffer("50FFFEF080");
unsigned long long value;
buffer >> std::hex >> value;
int var1 = value & 0xFFFF;
int var2 = (value >> 16) & 0xFF;
int var3 = (value >> 24) & 0xFF;
int var4 = (value >> 32) & 0xFF;
return 0;
}
Code Taken From: Bytes to Binary in C Credit: BSchlinker
The following code I modified to take more than 1 Byte at a time. I modified it, and got it half working and then got really confused on my loops. :( Ive spent the last day and a half trying to figure it out... but my C++ skills are not really that good (still learning!)
#include <iostream>
using namespace std;
char show_binary(unsigned char u, unsigned char *result,int len);
int main()
{
unsigned char p40[3] = {0x40, 0x00, 0x0a};
unsigned char bits[8*(sizeof(p40))];
int c;
c=sizeof(p40);
show_binary(*p40, bits, 3);
cout << "\n\n";
cout << "BIN = ";
do{
for (int i = 0; i < 8; i++)
printf("%d",bits[i+(8*c)]);
c++;
}while(c < 3);
cout << "\n";
int a;
cin >> a;
return 0;
}
char show_binary(unsigned char u, unsigned char *result, int len)
{
unsigned char mask = 1;
unsigned char bits[8*sizeof(result)];
int a,b,c;
a=0;
b=0;
c=len;
do{
for (int i = 0; i < 8; i++)
bits[i+(8*a)] = (u[&a] & (mask << i)) != 0;
a++;
}while(a < len);
//Need to reverse it?
do{
for (int i = 8; i != -1; i--)
result[i+(8*c)] = bits[i+(8*c)];
b++;
c--;
}while(b < len);
return *result;
}
After I spit out:
cout << "BIN = ";
do{
for (int i = 0; i < 8; i++)
printf("%d",bits[i+(8*c)]);
c++;
}while(c < 3);
Id like to take bit[11] ~ bit[the end] and compute a BYTE every 8 bits. If that makes sense. But first the function should work. Any pro tips on how this should be done? And of course, rip my code apart. I like to learn.
Man, there is a lot going on in this code, so it's hard to know where to start. Suffice to say, you're trying a bit too hard. It sounds like you are trying to 1) pass in a byte array; 2) turn those bytes into a string representation of the binary; and 3) turn that string representation back into a value?
It just so happens I recently did something similar to this in C, which should still work using a C++ compiler.
#include <stdio.h>
#include <string.h>
/* A macro to get a substring */
#define substr(dest, src, dest_size, startPos, strLen) snprintf(dest, dest_size, "%.*s", strLen, src+startPos)
/* Pass in char* array of bytes, get binary representation as string in bitStr */
void str2bs(const char *bytes, size_t len, char *bitStr) {
size_t i;
char buffer[9] = "";
for(i = 0; i < len; i++) {
sprintf(buffer,
"%c%c%c%c%c%c%c%c",
(bytes[i] & 0x80) ? '1':'0',
(bytes[i] & 0x40) ? '1':'0',
(bytes[i] & 0x20) ? '1':'0',
(bytes[i] & 0x10) ? '1':'0',
(bytes[i] & 0x08) ? '1':'0',
(bytes[i] & 0x04) ? '1':'0',
(bytes[i] & 0x02) ? '1':'0',
(bytes[i] & 0x01) ? '1':'0');
strncat(bitStr, buffer, 8);
buffer[0] = '\0';
}
}
To get the string of binary back into a value it can by done with bit shifting:
unsigned char bs2uc(char *bitStr) {
unsigned char val = 0;
int toShift = 0;
int i;
for(i = strlen(bitStr)-1; i >= 0; i--) {
if(bitStr[i] == '1') {
val = (1 << toShift) | val;
}
toShift++;
}
return val;
}
Once you had a binary string you could then take substrings of any arbitrary 8 bits (or less, I guess) and turn them back into bytes.
char *bitStr; /* Let's pretend this is populated with a valid string */
char byte[9] = "";
substr(byte, bitStr, 9, 4, 8);
/* This would create a substring of length 8 starting from index 4 of bitStr */
unsigned char b = bs2uc(byte);
I've actually created a whole suite of value -> binary string -> value functions if you'd like to take a look at them. GitHub - binstr
I am trying to implement the algorithm of a CRC check, which basically created a value, based on an input message.
So, consider I have a hex message 3F214365876616AB15387D5D59, and I want to obtain the CRC24Q value of the message.
The algorithm that I found to do this is the following:
typedef unsigned long crc24;
crc24 crc_check(unsigned char *input) {
unsigned char *octets;
crc24 crc = 0xb704ce; // CRC24_INIT;
int i;
int len = strlen(input);
octets = input;
while (len--) {
crc ^= ((*octets++) << 16);
for (i = 0; i < 8; i++) {
crc <<= 1;
if (crc & 0x1000000)
crc ^= CRC24_POLY;
}
}
return crc & 0xFFFFFF;
}
where *input=3F214365876616AB15387D5D59.
The problem is that ((*octets++) << 16) will shift by 16 bits the ascii value of the hex character and not the character itself.
So, I made a function to convert the hex numbers to characters.
I know the implementation looks weird, and I wouldn't be surprised if it were wrong.
This is the convert function:
char* convert(unsigned char* message) {
unsigned char* input;
input = message;
int p;
char *xxxx[20];
xxxx[0]="";
for (p = 0; p < length(message) - 1; p = p + 2) {
char* pp[20];
pp[0] = input[0];
char *c[20];
*input++;
c[0]= input[0];
*input++;
strcat(pp,c);
char cc;
char tt[2];
cc = (char ) strtol(pp, &pp, 16);
tt[0]=cc;
strcat(xxxx,tt);
}
return xxxx;
}
SO:
unsigned char *msg_hex="3F214365876616AB15387D5D59";
crc_sum = crc_check(convert((msg_hex)));
printf("CRC-sum: %x\n", crc_sum);
Thank you very much for any suggestions.
Shouldn't the if (crc & 0x8000000) be if (crc & 0x1000000) otherwise you're testing the 28th bit not the 25th for 24-bit overflow