ASCII string to hexadecimal integers conversion - c

I want to convert an ascii string of 16 bytes into 16 bytes hexadecimal integers. Kindly help. Here is my code:
uint stringToByteArray(char *str,uint **array)
{
uint i, len=strlen(str) >> 1;
*array=(uint *)malloc(len*sizeof(uint));
//Conversion of str (string) into *array (hexadecimal)
return len;
}

If you are looking for printing integer numbers in hexadecimal form, this might help:
#include <stdio.h>
int main() {
/* define ASCII string */
/* note that char is an integer number type */
char s[] = "Hello World";
/* iterate buffer */
char *p;
for (p = s; p != s+sizeof(s); p++) {
/* print each integer in its hex representation */
printf("%02X", (unsigned char)(*p));
}
printf("\n");
return 0;
}
If all you want is to turn a char array to an array of 1-byte integer numbers, then you are already done. char already is an integral number type. You can use the buffer you already have, or use malloc/memcpy to copy the data to a new one.
You might want to have a look at the explicit width integer types defined in stdint.h, e.g., uint8_t for a one byte unsigned integer.

A C-"string" of 16 characters length is 16bytes!
To have it converted to a "byte"-array (of 16 entries lenght) you might like to do the following:
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* Copies all characters of str into a freshly allocated array pointed to by *parray. */
/* Returns the number of characters bytes copied and -1 on error. Sets errno accordingly. */
size_t stringToByteArray(const char * str, uint8_t **parray)
{
if (NULL == str)
{
errno = EINVAL;
return -1;
}
{
size_t size = strlen(str);
*parray = malloc(size * sizeof(**parray));
if (NULL == *parray)
{
errno = ENOMEM;
return -size;
}
for (size_t s = 0; s < size; ++s)
{
(*parray)[s] = str[s];
}
return size;
}
}
int main()
{
char str[] = "this is 16 bytes";
uint8_t * array = NULL;
ssize_t size = stringToByteArray(str, &array);
if (-1 == size)
{
perror("stringToByteArray() failed");
return EXIT_FAILURE;
}
/* Do what you like with array. */
free(array);
return EXIT_SUCCESS;
}

Related

sprintf() function not giving the desired output

This is a small portion of code that splits variables into characters, all of the characters are then placed in sequence in a buffer. I have managed to get that part to work but I am having some issues with the sprintf function. The signed integer Cur_Scale is not outputting the correct characters.
I have tried modifying the formatting specifiers but always get a similar output. The only way I get the correct value is if I place a "-" in front of the argument / the variable.
I'm sure it's something very easy I'm overlooking but just can not spot it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
int32_t Seconds_Timer = 123456789;
int32_t Cur_Scale = -254123678;
uint8_t buffer[250];
uint8_t buffer_2[20];
int main()
{
memset(buffer, 0, sizeof buffer); // Set all buffer to zero
memset(buffer_2, 0, sizeof buffer_2); // Set all buffer_2 to zero
sprintf(buffer_2, "%ld", Seconds_Timer); // This will put up to 9 characters in buffer
//Split the variable into characters
uint8_t a;
uint8_t b;
for(a=0; a<=8; a++)
{
buffer[a]=buffer_2[a];
}
memset(buffer_2, 0, sizeof buffer_2); // Set all buffer_2 to zero
sprintf(buffer_2, "%ld", Cur_Scale); // This will put up to 10 characters in buffer
for(a=9,b=0; a<=18; a++,b++)
{
buffer[a]=buffer_2[b];
}
printf(buffer, 20); // Send confirmed value back in characters
}
Is this your expected output: 123456789-254123678
Then a code then works like this:
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int32_t Seconds_Timer = 123456789;
int32_t Cur_Scale = -254123678;
char buffer[250];
char buffer_2[20];
int main(int argc, char* argv[]) {
memset(buffer, 0, sizeof buffer); // Set all buffer to zero
memset(buffer_2, 0, sizeof buffer_2); // Set all buffer_2 to zero
sprintf(buffer_2, "%d",
Seconds_Timer); // This will put up to 9 characters in buffer
// Split the variable into characters
uint8_t a;
uint8_t b;
for (a = 0; a <= 8; a++) {
buffer[a] = buffer_2[a];
}
memset(buffer_2, 0, sizeof buffer_2); // Set all buffer_2 to zero
sprintf(buffer_2, "%d",
Cur_Scale); // This will put up to 10 characters in buffer
for (a = 9, b = 0; a <= 18; a++, b++) {
buffer[a] = buffer_2[b];
}
printf("%s\n", buffer); // Send confirmed value back in characters
return 0;
}
For your original code, the compiler warning gives many hints, fix them will correct the code.
uint8_t buffer[250]; should be char buffer[250];
sprintf(buffer_2, "%ld", Seconds_Timer); should be sprintf(buffer_2, "%d", Seconds_Timer);, ld is for long int type
printf(buffer, 20); should be printf("%s\n", buffer);, buffer is not a literal format string

copy a const char* into array of char (facing a bug)

I have following method
static void setName(const char* str, char buf[16])
{
int sz = MIN(strlen(str), 16);
for (int i = 0; i < sz; i++) buf[i] = str[i];
buf[sz] = 0;
}
int main()
{
const char* string1 = "I am getting bug for this long string greater than 16 lenght);
char mbuf[16];
setName(string,mybuf)
// if I use buf in my code it is leading to spurious characters since length is greater than 16 .
Please let me know what is the correct way to code above if the restriction for buf length is 16 in method static void setName(const char* str, char buf[16])
When passing an array as argument, array decays into the pointer of FIRST element of array. One must define a rule, to let the method know the number of elements.
You declare char mbuf[16], you pass it to setName(), setName() will not get char[], but will get char* instead.
So, the declaration should be
static void setName(const char* str, char* buf)
Next, char mbuf[16] can only store 15 chars, because the last char has to be 'null terminator', which is '\0'. Otherwise, the following situation will occur:
// if I use buf in my code it is leading to spurious characters since length is greater than 16 .
Perhaps this will help you understand:
char str[] = "foobar"; // = {'f','o','o','b','a','r','\0'};
So the code should be
static void setName(const char* str, char* buf)
{
int sz = MIN(strlen(str), 15); // not 16
for (int i = 0; i < sz; i++) buf[i] = str[i];
buf[sz] = '\0'; // assert that you're assigning 'null terminator'
}
Also, I would recommend you not to reinvent the wheel, why don't use strncpy instead?
char mbuf[16];
strncpy(mbuf, "12345678901234567890", 15);
The following code passes the size of the memory allocated to the buffer, to the setName function.
That way the setName function can ensure that it does not write outside the allocated memory.
Inside the function either a for loop or strncpy can be used. Both will be controlled by the size parameter sz and both will require that a null terminator character is placed after the copied characters. Again, sz will ensure that the null terminator is written within the memory allocated to the buffer.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void setName(const char *str, char *buf, int sz);
int main()
{
const int a_sz = 16;
char* string = "This bit is OK!! but any more than 15 characters are dropped";
/* allocate memory for a buffer & test successful allocation*/
char *mbuf = malloc(a_sz);
if (mbuf == NULL) {
printf("Out of memory!\n");
return(1);
}
/* call function and pass size of buffer */
setName(string, mbuf, a_sz);
/* print resulting buffer contents */
printf("%s\n", mbuf); // printed: This bit is OK!
/* free the memory allocated to the buffer */
free(mbuf);
return(0);
}
static void setName(const char *str, char *buf, int sz)
{
int i;
/* size of string or max 15 */
if (strlen(str) > sz - 1) {
sz--;
} else {
sz = strlen(str);
}
/* copy a maximum of 15 characters into buffer (0 to 14) */
for (i = 0; i < sz; i++) buf[i] = str[i];
/* null terminate the string - won't be more than buf[15]) */
buf[i] = '\0';
}
Changing one value const int a_sz allows different numbers of characters to be copied. There is no 'hard coding' of the size in the function, so reducing the risk of errors if the code is modified later on.
I replaced MIN with a simple if ... else structure so that I could test the code.

Assigning a char array to a char*

I'm trying to write a function that prefixes a string with its length. I can't seem to assign a char[] to a char *. Mysteriously, if I print out some debugging code before the assignment, it works.
char *prefixMsgWLength(char *msg){
char *msgWLength;
int msgLength = strlen(msg);
if (msgLength == 0){
msgWLength = "2|";
}
else{
int nDigits = floor(log10(abs(msgLength))) + 1;
int nDigits2 = floor(log10(abs(msgLength + nDigits + 1))) + 1;
if (nDigits2 > nDigits){
nDigits = nDigits2;
}
msgLength += nDigits + 1;
char prefix[msgLength];
sprintf(prefix, "%d|", msgLength);
strcat(prefix, msg);
// if I uncomment the below, msgWLength is returned correctly
// printf("msg: %s\n", prefix);
msgWLength = prefix;
}
return msgWLength;
}
The problem in your code is
msgWLength = prefix;
here, you're assigning the address of a local variable (prefix) to the pointer and you try to return it.
Once the function finishes execution, the local variables will go out of scope and the returned pointer will be invalid.
You need to make prefix as a pointer and allocate memory dynamically, if you want it to retain it's existence after returning from the function.
String reallocation to the exact length can be very cumbersome in C. You'd probably be much better off just using a sufficiently large buffer. Here, I use limits.h to determine the size of a line buffer according to the system (LINE_MAX):
#include <stdio.h>
#include <limits.h>
#include <string.h>
int main()
{
/* Our message */
char const msg[] = "Hello, world!";
/* Buffer to hold the result */
char buffer[LINE_MAX];
/* Prefix msg with length */
snprintf(buffer, LINE_MAX, "%lu|%s", strlen(msg)+1, msg);
/* Print result */
printf("%s\n", buffer);
return 0;
}

Printing out byte array as formatted text gives different outputs - C

I am trying to print out byte array as one byte at the time in hexadecimal format within for loop like this:
int my_function(void *data)
{
obuf = (str*)data;
int i;
for (i = 0; i < obuf->len; i++)
{
printf("%02X:", obuf->s[i]);
}
return 0;
}
str in this case is structure from Kamailio - review at http://www.asipto.com/pub/kamailio-devel-guide/#c05str
The expected output:
80:70:0F:80:00:00:96:00:1D:54:7D:7C:36:9D:1B:9A:20:BF:F9:68:E8:E8:E8:F8:68:98:E8:EE:E8:B4:7C:3C:34:74:74:64:74:69:2C:5A:3A:3A:3A:3A:3A:3A:32:24:43:AD:19:1D:1D:1D:1D:13:1D:1B:3B:60:AB:AB:AB:AB:AB:0A:BA:BA:BA:BA:B0:AB:AB:AB:AB:AB:0A:BA:BA:BA:BA:B9:3B:61:88:43:
What I am getting:
FFFFFF80:70:0F:FFFFFF80:00:00:FFFFFF96:00:1D:54:7D:7C:36:FFFFFF9D:1B:FFFFFF9A:20:FFFFFFBF:FFFFFFF9:68:FFFFFFE8:FFFFFFE8:FFFFFFE8:FFFFFFF8:68:FFFFFF98:FFFFFFE8:FFFFFFEE:FFFFFFE8:FFFFFFB4:7C:3C:34:74:74:64:74:69:2C:5A:3A:3A:3A:3A:3A:3A:32:24:43:FFFFFFAD:19:1D:1D:1D:1D:13:1D:1B:3B:60:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:0A:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFB0:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:0A:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFB9:3B:61:FFFFFF88:43:
Could someone please help me understand why there are some of bytes prefixed with FFFFFF and other aren't?
Thanks in advance
Looks like obuf->s[i] returns a signed value
You would need to cast it to a unsigned value to get rid of the FFF.. at start.
printf("%02X:", (unsigned char)(obuf->s[i]));
The problem appears with chars that have the most significant bit set (which are out of the proper pure ASCII set range 0-127). The key point is to consider chars as unsigned.
printf("%02X:", (unsigned char)(obuf->s[i]));
See this simple compilable repro C code:
#include <stdio.h>
#include <string.h>
struct _str {
char* s; /* pointer to the beginning of string (char array) */
int len; /* string length */
};
typedef struct _str str;
int my_function(void *data)
{
str* obuf;
int i;
obuf = (str*)data;
for (i = 0; i < obuf->len; i++) {
printf("%02X:", (unsigned char)(obuf->s[i]));
}
return 0;
}
int main(void)
{
char buf[2];
str s;
/* Test with ordinary ASCII string */
s.s = "Hello";
s.len = strlen(s.s);
my_function(&s);
printf("\n");
/* Test with char values with most significant bit set */
buf[0] = 0xF1;
buf[1] = 0x00;
s.s = buf;
s.len = 1;
my_function(&s);
return 0;
}
With MSVC, I get this output:
48:65:6C:6C:6F:
F1:

how to convert a value to integer type string?

we all know that to convert a value in a string we can do following
char* buffer = ... allocate a buffer ...
int value = 4564;
sprintf(buffer, "%d", value);
but what can we do if instead of character buffer i want to convert data to integer buffer, basically i want to do following
int* buffer = ... allocate a buffer ...
int value = 4564;
sprintf(buffer, "%d", value);
Thanks in advance
Be sure to define buffer as the value of 'value', and not a pointer to the address of 'value'. See below:
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
int main(int argc, char** argv)
{
/* Allocate memory. */
int* buffer = malloc(sizeof(int));
int value = 1000;
/* Sets the number stored in buffer equal to value. */
*buffer = value;
/* prints 1000 */
printf("%d\n", *buffer);
/* Change value to show buffer is not pointing to the address of 'value'. */
value = 500;
/* Still prints 1000. If we had used
int* buffer = &value, it would print 500. */
printf("%d\n", *buffer);
return 0;
}

Resources