How to convert elements in const unsigned char array to char - arrays

I am trying to iterate over a single const unsigned char array and assign/convert each element to a new char array using typecasting, every thread I've read suggests using typecasting however it's not working for me, here's my attempt:
#include <stdio.h>
#include <stdlib.h>
char *create_phone_number(const unsigned char nums[10]) {
char *new = malloc(11);
int i = 0;
for (; i<10; i++)
new[i] = (char)nums[i];
new[i] = '\0';
return new;
}
int main(void) {
char *num = create_phone_number((const unsigned char[]){ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
printf("%s\n", num);
free(num);
return 0;
}
The above code's stdout:
Expected stdout:
1111111111
How do I convert the elements in nums to type char and assign/store the converted values in the new array (efficiently)?

Casting to char doesn't mean casting the integer value to the corresponding ASCII character; the numeric value 1 is the ASCII code SOH (start of heading) which has no printable representation, thus your empty output. If you know all the values will be in the range 0 to 9, you can add them to ASCII '0' to get the char value that produces the associated ASCII digit:
char *create_phone_number(const unsigned char nums[10]) {
char *new = malloc(11);
for (int i=0; i<10; i++)
new[i] = '0' + nums[i];
new[i] = '\0';
return new;
}
You don't actually need to cast it at all; the result of the + will be int and it will store back to a char that can fit it without issue (so just make sure they're really all 0-9 values, or you'll get weird results).

Related

How to count non-zero occurrences of a char in C?

I am new in C programming. I would like to ask how I can store a char in a char array? The reason why I want to do it is because I get a char from a computation I make. This computation returns a char consisting of 4. I want to look through every character of the 4 and check if they are "0". If not, then I will increment by one. This is an example of a substitution: "0xf3"- I am trying to compute the Hamming Weight of a substitution. This is how I try to count how many non-zero the char consists of:
#include <stdio.h>
int main()
{
char x = "0xf3";
char s[10] = x;
int lingh = strlen(s);
for (int i = 0; i<lingh;i++) {
printf("%c\n", s[i] );
}
return 0;
}
the output I expect is something like s[] = {0,x,f,3}
This computation returns a char consisting of 4.
You are saying your computation returns a character which consists of 4 characters. Is it possible???
I guess your computation returns a string that consists of 4 characters. Example 0xf3
You can not store a string literal in char type variable.
char x = "0xf3"; //<---------------------
You can store them in a character array like char x[] = "0xf3";
Here is the modified code
#include <stdio.h>
#include<string.h> //<---- for strlen() and strcpy()
int main()
{
char x[] = "0xf3"; //<----store in a char array
char s[10];
strcpy(s, x); //<----copy in another array
int lingh = strlen(s);
for (int i = 0; i<lingh;i++) {
printf("%c\n", s[i] );
}
return 0;
}

Unsigned char array concatenation in C

What's the best way to concatenate unsigned char arrays in C? Furthermore, is there a way to concatenate unsigned char arrays with char arrays? 2 of these unsigned char arrays are really just strings, but for simplicity, I'm treating them as unsigned char arrays.
The requirement is complex: there is a function that will take 1 (one) unsigned char array. That one unsigned char array is really 4 variables concatenated to make up that 1 unsigned char array. To add to the complexity, the first unsigned char array is really just a string of variable length, but its max length is 60 (i.e. sometimes it would have length = 15, other times = 60).
someFunctionAssignsFirst(unsigned char *first)
{
//it could be 15 or 60 chars long.
...
}
unsigned char first[60] = //someFunctionAssignsFirst() //This is a string i.e. "variable size string max size 60"
unsigned char second[8] = "always8."; //This is a string i.e. "01234567"
unsigned char third[32] = "always32"; //This is a cryptographic key
unsigned char fourth[32] = "always32"; //This is a cryptographic key
How would I go about getting:
unsigned char allstrings[sizeof(first)+sizeof(second)+sizeof(third)+sizeof(fourth)] = //all strings combined
?
I attempted some for loops, but the variable length first is disrupting the concatenation, and I'm sure there has to be a better way.
Full Disclosure: I'm not an expert, and I don't necessarily love C. Also for the requirement, not allowed C++ or any other language.
This is what I was trying to do, and (for clarification) I don't get a null character at the end so it's not really a string.
unsigned char *first = "this is a sample string, human readable";
unsigned char *second = "12345678" //always a number
//unsigned char third -> I have the value from before and it's a key
//unsigned char fourth -> I have the value from before and it's a key
unsigned char allstrings[sizeof(first) + sizeof(second) + sizeof(third) + sizeof(fourth)];
int counter = 0;
for (int i = 0; i <= sizeof(first); i++)
{
allstrings[counter] = first[i];
counter++;
}
for (int i = 0; i <= sizeof(second); i++)
{
allstrings[counter] = second[i];
counter++;
}
for (int i = 0; i <= sizeof(third); i++)
{
allstrings[counter] = third[i];
counter++;
}
for (int i = 0; i <= sizeof(fourth); i++)
{
allstrings[counter] = fourth[i];
counter++;
}
The allstrings variable, doesn't get anything beyond "readable" in my example above.
You need to use strcpy to copy over the first part, which is a string, then use memcpy to copy over the other 3, which are not strings but char arrays.
Note that the result is not a string but a char array, i.e. it is not null terminated.
unsigned char allstrings[strlen(first)+sizeof(second)+sizeof(third)+sizeof(fourth)];
strcpy(allstrings,first);
memcpy(allstrings+strlen(first),second,sizeof(second));
memcpy(allstrings+strlen(first)+sizeof(second),third,sizeof(third));
memcpy(allstrings+strlen(first)+sizeof(second)+sizeof(third),fourth,sizeof(fourth));
I guess you want to treat the array as buffer.
So it's fine to have the declarations,
but you don't need to define the content for this moment:
unsigned char first[60];
unsigned char second[8];
unsigned char third[32];
unsigned char fourth[32];
#define ALLSTRLEN sizeof(first) + sizeof(second) + sizeof(third) + sizeof(fourth)
unsigned char allstrings[ALLSTRLEN];
The code will keep the fixed size of arrays. and please notice that the arrays should be global or static for safety reasons.
Then you can copy the contents to arrays. I just put your code under main() to concatenate these arrays:
int main()
{
strcpy((char *)first, "this is a sample string, human readable");
// do something for second, third, fourth....
//
int counter = 0;
// first array is a normal string, we have to copy null character for it
for (int i = 0; i <= strlen((char *)first)+1; i++)
{
allstrings[counter] = first[i];
counter++;
}
for (int i = 0; i <= sizeof(second); i++)
{
allstrings[counter] = second[i];
counter++;
}
for (int i = 0; i <= sizeof(third); i++)
{
allstrings[counter] = third[i];
counter++;
}
for (int i = 0; i <= sizeof(fourth); i++)
{
allstrings[counter] = fourth[i];
counter++;
}
// allstrings is finished
}
Please notice this example just works in main() function; if you call a function to concatenate four arrays, the compiler has to pass the arrays as pointers, and the sizeof() will be wrong (equal to the pointer's size).
You can test the size by doing this:
printf("sizeof(second)=%d\n", sizeof(second));

How to convert a list to a string

Problem in C programming
I have following list:
int a[] = {0,0,1,0,0,1,0,2}
How do i convert following list items to char variable b?
Like this:
printf(%c, b)
OUTPUT: 00100102
I need this for printing the values of list in embedded system lcd screen where normal print options aren't available. Couldn't find similar example from www.stackoverflow.com. Vice versa there were many solutions to convert a string into a list.
#include <stdio.h>
#include <stdlib.h>
int main(){
int a[] = {0,0,1,0,0,1,0,2};
const char *table = "0123456789";
size_t size = sizeof(a)/sizeof(*a);
char *b = malloc(size+1);
int i;
for(i=0;i<size;++i)
b[i]=table[a[i]];
b[i]='\0';
printf("%s\n", b);
free(b);
return 0;
}
int a = [0,0,1,0,0,1,0,2]
That is not valid C. Perhaps you meant:
const int a[] = { 0, 0, 1, 0, 0, 1, 0, 2 };
Converting a decimal digit to a printable character in C is easy, just add '0':
printf("%c", '0' + a[0]);
will print 0.
You can iterate through the elements of your array, and printf() each one, considering it as an offset from '0':
/*
'0' + 0 = '0'
'0' + 1 = '1'
'0' + 2 = '2'
*/
const int a[] = {0,0,1,0,0,1,0,2};
const int count = sizeof(a) / sizeof(a[0]);
int i;
for (i = 0; i < count; i++) {
printf("%c", '0' + a[i]);
}
printf("\n");
When you convert each value in an array of int to a corresponding value in an array of char, you just have an array of char. When you append the null terminator \0 (or 0) to the array of char, it becomes a C string.
int a[] = {0,0,1,0,0,1,0,2}; //use curly braces to assign values to new array.
char b[sizeof(a)/sizeof(a[0])+1];//Accomodates any size of a. note extra space for terminating \0
int i;
//EDIT 5 following lines
b[0]=0; //ensure string is null terminated
for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
{
sprintf(b, "%s%d", b, a[i]);//copy one char per loop to concatenate string with all elements of `a`
}
Now you have a string, sized according to number of array elements in a that looks like:
"00100102"
In memory you would see |48|48|49|48|48|49|48|50|0|
(the integer values of each character representation of the integers 0, 1, & 2, with the null character 0 in the last position to mark the end of string.)
Note also, the phrase sizeof(array)/sizeof(array[0]) is used to get the number of elements in an array.

How to fill a string with random (hex) characters?

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

C Library function for converting a string of hex digits to ints?

I have a variable length string where each character represents a hex digit. I could iterate through the characters and use a case statement to convert it to hex but I feel like there has to be a standard library function that will handle this. Is there any such thing?
Example of what I want to do. "17bf59c" -> int intarray[7] = { 1, 7, 0xb, 0xf, 5, 9, 0xc}
No, there's no such function, probably because (and now I'm guessing, I'm not a C standard library architect by a long stretch) it's something that's quite easy to put together from existing functions. Here's one way of doing it decently:
int * string_to_int_array(const char *string, size_t length)
{
int *out = malloc(length * sizeof *out);
if(out != NULL)
{
size_t i;
for(i = 0; i < length; i++)
{
const char here = tolower(string[i]);
out[i] = (here <= '9') ? (here - '\0') : (10 + (here - 'a'));
}
}
return out;
}
Note: the above is untested.
Also note things that maybe aren't obvious, but still subtly important (in my opinion):
Use const for pointer arguments that are treated as "read only" by the function.
Don't repeat the type that out is pointing at, use sizeof *out.
Don't cast the return value of malloc() in C.
Check that malloc() succeeded before using the memory.
Don't hard-code ASCII values, use character constants.
The above still assumes an encoding where 'a'..'f' are contigous, and would likely break on e.g. EBCDIC. You get what you pay for, sometimes. :)
using strtol
void to_int_array (int *dst, const char *hexs)
{
char buf[2] = {0};
char c;
while ((c = *hexs++)) {
buf[0] = c;
*dst++ = strtol(buf,NULL,16);
}
}
Here's another version that allows you to pass in the output array. Most of the time, you don't need to malloc, and that's expensive. A stack variable is typically fine, and you know the output is never going to be bigger than your input. You can still pass in an allocated array, if it's too big, or you need to pass it back up.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* str of length len is parsed to individual ints into output
* length of output needs to be at least len.
* returns number of parsed elements. Maybe shorter if there
* are invalid characters in str.
*/
int string_to_array(const char *str, int *output)
{
int *out = output;
for (; *str; str++) {
if (isxdigit(*str & 0xff)) {
char ch = tolower(*str & 0xff);
*out++ = (ch >= 'a' && ch <= 'z') ? ch - 'a' + 10 : ch - '0';
}
}
return out - output;
}
int main(void)
{
int values[10];
int len = string_to_array("17bzzf59c", values);
int i = 0;
for (i = 0; i < len; i++)
printf("%x ", values[i]);
printf("\n");
return EXIT_SUCCESS;
}
#include <stdio.h>
int main(){
char data[] = "17bf59c";
const int len = sizeof(data)/sizeof(char)-1;
int i,value[sizeof(data)/sizeof(char)-1];
for(i=0;i<len;++i)
sscanf(data+i, "%1x",value + i);
for(i=0;i<len;++i)
printf("0x%x\n", value[i]);
return 0;
}

Resources