Convert ASCII string array into its hex value array - c

I have a char array which contains ASCII characters. I need to know how to get the hex value of each character and save it in a uint8_t array.
E.g. if I have
array[5] = "ABCDE"
The output should be
output[5] = {0x41, 0x42, 0x43, 0x44, 0x45}
I tried using strtol but didn't work.
for(unsigned i = 0; i < 32; i++) {
message[i] = (uint8_t)strtol(&incoming_message[i], NULL, 16);
}
Output:
A 0 0 0 0 0 0 0 0 0 F 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Update: This is for a program I'm writing for a Cortex-M0+ processor. I'm not just viewing incoming data, I'm processing this data in the next step. Therefore, no use of printf

First of all, strtol like all other string functions expects a null-terminated byte string, not single characters.
Secondly, the characters encoded value is the actual value of the elements in your string. If you print the decimal value 65 (for example) using the correct format specifier, then the character A will be printed:
printf("%c\n", 65); // Will print an A
Similarly, printing the character 'A' as a decimal integer will print the value 65:
printf("%d\n", 'A'); // Will print the value 65
So all you need to do is to print the values in your array in the correct format.
Furthermore... All values on computers the last few decades are stored in binary. All of them.
Decimal, octal or hexadecimal are just how you present the values. Storing 0x41, 61, 0101 or 0b01000001 (for compilers with binary notation extension) doesn't matter since in the end it will be the binary value that is stored. If you want to show a value as hexadecimal to a user through some output, you have to format the binary value as such when printing or writing it.

Talking C a char is the smallest integer value available.
Talking C and ASCII a character literal (like 'A') is just another representation of an int value (65 here).
Talking Math there are other ways to represent the very same value, aside the decimal way (using base 10). One common is using the base of 16, the hexadecimal way.
Putting the above together it proves that:
int i = 'A';
char c = i;
is the same as:
int i = 65;
char c = i;
and the same as:
int i = 0x41;
char c = i;
and the same as:
char c = 'A';
and the same as:
char c = 65;
and the same as:
char c = 0x41;
So
char a[5] = "ABCDE";
in fact already is an integer array of five (small) integers.
If printed using the correct conversion specifier and length modifier you see what you are after.
for (size_t i = 0; i < 5; ++i)
{
printf("%hhx ", a[i]);
}
Output:
41 42 43 44 45
To indicate to the reader this should be taken as hexadecimal values one could prefix the value using the common 0x notation
printf("0x%hhx ", a[i]);
which gave you
0x41 0x42 0x43 0x44 0x45
If you would show this to Pascal guys you perhaps would use
printf("$%hhx ", a[i]);
which gave you
$41 $42 $43 $44 $45
To see the characters themselves just us:
printf("%c ", a[i]);
and get
A B C D E
To see the decimal values use
printf("%d ", a[i]);
and get
65 66 67 68 69
The conclusion is, that it's all just matter of how you represent ("print") the same values (the content of a's elements) . The "conversion" happens when creating the representation of a very same value (via printing and passing the right "instructions"), that is during output only.
As you refer to ASCII only, this implies all value are <128, so you can just plain copy the array's values using either a loop
char src[5] = "ABCDE";
uint8_t dst[5];
for (size_t i = 0 i < 5; ++i)
{
dst[i] = src[i];
}
or by copying the related memory block at once
memcpy(dst, src, 5);

you can convert the value to hexadecimal using the basic algorithm i.e division by 16.
I have created the following function where you can pass the string to be converted and a an array of strings where you will get the response.
void hexCon(char str[],char result[][5]){
int i,check,rem = 0;
char res[20],res2[20];
int len = 0;
char temp;
for(i=0; i < strlen(str) ; i++){
len=0;
check = str[i];
while(check > 0){
rem = check%16;
switch(rem){
case 10:temp='A';break;
case 11:temp='B';break;
case 12:temp='C';break;
case 13:temp='D';break;
case 14:temp='E';break;
case 15:temp='F';break;
default:temp=rem + '0';
}
res[len] = temp;
check = check /16;
len++;
}
reverse(res,len,res2); //reversing the digits
res2[len] = '\0'; //adding null character at the end of string
strcpy(result[i],res2); //copying all data to result array
}
}
where reverse function is :
void reverse(char str[], int size, char rev[])
{
int i=0,j=0;
for(i=size-1 , j=0 ; i >= 0; i-- , j++ ){
rev[j] = str[i];
}
}
you can call it like :
void main(){
char str[]="ABCDE";
char result[strlen(str)][5];
int i;
hexCon(str,result);
for(i =0 ;i < strlen(str); i++){
printf("%s\n",result[i]);
}
}
the algorithm used is explained here :-
https://www.permadi.com/tutorial/numDecToHex/
Hope this helps :)

Related

How to add a sequence of numbers in a string to an integer array in c?

What I have is a string with some numbers (unknown amount but has a maximum), for example char string[] = "12 13 14 123 1234 12345"; and I wanna add each number to an array. So let's say I have an array int numbers[50]; and I want to add it to the array so it's like {12, 13, 14, 123, 1234, 12345}.
I've tried a loop through the string that uses a variable as a state machine to detect if it is reading a number but the code ended up looking like spaghetti so I just lost the way I was thinking. I cannot use malloc() or anything that allocates memory for this exercise.
Any ideas?
Here you are.
#include <stdio.h>
int main(void)
{
enum { N = 50 };
int numbers[N];
char *s = "12 13 14 123 1234 12345";
size_t n = 0;
char *p = s;
for ( int value, pos = 0; n < N && sscanf( p, "%d %n", &value, &pos ) == 1; p += pos )
{
numbers[n++] = value;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", numbers[i] );
}
putchar( '\n' );
return 0;
}
The program output is
12 13 14 123 1234 12345
The state machine idea is good (albeit overkill; you only have three or four states after all).
You could use both this and Horner's Algorithm to parse the integer.
- set Horner accumulator to 0 and HaveNumber to 0 (false).
- loop:
- read character
- if digit:
- multiply Horner by 10
- add the value of the digit to Horner
- set HaveNumber to 1
- continue
- if HaveNumber:
push Horner onto array
set HaveNumber to 0
- set Horner to 0
- if character was a 0 instead of a space:
break
This does not need memory and does not necessarily use any function call (the digit check may be done verifying the ASCII value of the digit between 0x30 and 0x39)
You can use strtok to split string into substrings and then use atoi to convert that into ints.
#include <stdlib.h>
#include <string.h>
int main()
{
char my_string[] = "12 23 234 2345";
int my_array[50] = {0};
char* token = strtok(my_string, " ");
int i = 0;
while (token)
{
my_array[i] = atoi(token);
token = strtok(NULL, " ");
i++;
}
return 0;
}

what's meant by converting an ASCII character to alphabetical index and how can i do that?

in Caesar (CS50) it says that i need to convert an ASCII character to alphabetical index in one of the steps. what does that mean? i saw a video that said that i "need to find the relationship between a number's ASCII value and its actual index in the alphabet", but i haven't really understood how I might implement this* and *what exactly is the relationship.
please elaborate in your answer because I'm new to this.
string plaintext = get_string("plaintext;");
As you may or may not know ASCII characters are encoded as 8-bit values and character constants, in reallity, have int type in C.
Using this knowledge you can perform character arithmetic as if they are regular numbers, take the following example:
printf("%d\n", 'a');
This prints 'a''s int value which is 97.
Now this:
printf("%d\n", 'g' - 'a');
This will print 6 which is the result of 103 - 97.
Now your string:
const char* plaintext = "plaintext";
for(size_t i = 0; i < strlen(plaintext); i++){
printf("%c - %d\n",plaintext[i], plaintext[i] - 'a' + 1);
}
The result:
p - 16
l - 12
a - 1
i - 9
n - 14
t - 20
e - 5
x - 24
t - 20
As you can see the printed results are the indexes of the letters in the alphabet 1...26, I added 1 to the result because, as you know, in C indexing starts at 0 and you would have 0...25.
So the bottom line is that you can use this character arithmetic to find the indexes of characters, this also aplies to caps, but you can't mix both.
Note that there are other character encodings that do not allow for this kind of arithmetic because the alphabetic characters are not in sequencial order, like, for example, EBCDIC.
It means that a single char variable is nothing but an integer containing an ASCII code, such as 65 for 'A'. It might be more convenient for an algorithm to work with the interval 0 to 25 than 65 to 90.
Generally, if you know that a char is an upper-case letter, you can do a naive conversion to alphabetical index by subtracting the letter 'A' from it. Naive, because strictly speaking the letters in the symbol (ASCII) table need not be located adjacently. For a beginner-level program, it should be ok though:
char str[] = "ABC";
for(int i=0; i<3; i++)
printf("%d ", str[i] - 'A'); // prints 0 1 2
Wheras a 100% portable converter function might look something like this:
int ascii_to_int (char ch)
{
const char LOOKUP_TABLE [128] =
{
['A'] = 0,
['B'] = 1,
...
};
return LOOKUP_TABLE[ch];
}
Here you have an example. It is portable as it does not depend if the char encoding.
const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ";
int getIndex(const char *alphabet, int c)
{
int result = -1;
const char *res;
res = strchr(alphabet, c);
if(res)
{
result = res - alphabet;
}
return result;
}
int main(void)
{
char *str = "Hello World!!!";
while(*str)
{
printf("Index of %c is %d\n", *str, getIndex(alphabet, *str));
str++;
}
}
https://godbolt.org/z/rw2PK9

Numerical operations between int and char in C

I would like to know how are data really stored, because in example beyond is intuition weak.
I believed, that any value has it's numerical recognition; as 'a' has value of 48; so I assumed, that in any situation I can decrement 48 as 'a' (eg. (100 - 'a' == 52)).
Reality seems to be different.
So;
when can I decrement with 'a' to get int-like value?
what should I use here, so it would looks like more intuitively?
...
program is barely finished, however function takes array of chars and it needs to get int of value (3) from one of chars. /* for this scenario */
Thank you for help!
/* command reader */
int cr (char a[])
{
printf("%s\n", a);
/* command sequence */
char co[350]; /* <-- change later */
for (int cri = 0, coi = 0; a[cri]; cri++, coi++)
{
printf("%c ", a[cri]);
co[coi] = a[cri];
}
int ec (char co[])
{
printf("\n%s co\n", co);
printf("\n%c co1\n", co[1]);
co[1] = co[1];
printf("\n basic: %d\n\n", co[1]); /* 51 */
co[2] = co[1] - 'a';
printf("\n charred out: %d\n\n", co[2]); /* -46 */
co[3] = co[1] - 48;
printf("\n numbered out: %d\n\n", co[3]); /* 3 */
return 0;
}
ec(co);
return 0;
}
cr("F3 R B");
The "value" of 'a', that is its numerical representation, actually depends on the character set. In most cases that is the American Standard Code for Information Interchange (ASCII) or a character set where the first 128 codepoints are identical to ASCII. However, the ASCII value for 'a' is actually 97 and not 48.
As WhozCraig said, I was looking for (- "0"), where numeric value of "0" is 48.

Print a Char Array of Integers in C

For class, I am required to create a function that converts an Integer into it's corresponding Binary number. However, I am forced to use the given main and parameters for the to_binary function. The whole problem requires me to print out the 32 bit binary number, but to break it up, I am just trying to print out the Char Array, that I thought I filled with Integers (perhaps the issue). When I do compile, I receive just a blank line (from the \n) and I am wondering how I can fix this. All I want to do is to be able to print the binary number for 5 ("101") yet I can't seem to do it with my professor's restrictions. Remember: I cannot change the arguments in to_binary or the main, only the body of to_binary. Any help would be greatly appreciated.
#include<stdio.h>
void to_binary(int x, char c[]) {
int j = 0;
while (x != 0) {
c[j] x = x % 2;
j++;
}
c[33] = '\0';
}
int main() {
int i = 5;
char b[33];
to_binary(i,b);
printf("%s\n", b);
}
This is the answer to your question.
void to_binary(int x, char c[]) {
int i =0;
int j;
while(x) {
/* The operation results binary in reverse order.
* so right-shift the entire array and add new value in left side*/
for(j = i; j > 0; j--) {
c[j] = c[j-1];
}
c[0] = (x%2) + '0';
x = x/2;
i++;
}
c[i]=0;
}
the problem is in the code below:
while (x != 0) {
c[j] = x % 2; // origin: c[j] x = x % 2; a typo?
j++;
}
the result of x % 2 is a integer, but you assigned it to a character c[j] —— integer 1 is not equal to character '1'.
If you want to convert a integer(0-9) to a character form, for example: integer 7 to character '7', you can do this:
int integer = 7;
char ch = '0' + integer;
One of the previous answers has already discussed the issue with c[j] x = x % 2; and the lack of proper character conversion. That being said, I'll instead be pointing out a different issue. Note that this isn't a specific solution to your problem, rather, consider it to be a recommendation.
Hard-coding the placement of the null-terminator is not a good idea. In fact, it can result in some undesired behavior. Imagine I create an automatic char array of length 5. In memory, it might look something like this:
Values = _ _ _ _ _
Index = 0 1 2 3 4
If I were to populate the first three indexes with '1', '0', and '1', the array might look like so:
Values = 1 0 1 _ _
Index = 0 1 2 3 4
Let's say I set index 4 to contain the null-terminator. The array now looks like so:
Values = 1 0 1 _ \0
Index = 0 1 2 3 4
Notice how index three is an open slot? This is bad. In C/C++ automatic arrays contain garbage values by default. Furthermore, strings are usually printed by iterating from character to character until a null-terminator is encountered.
If the array were to look like it does in the previous example, printing it would yield a weird result. It would print 1, 0, 1, followed by an odd garbage value.
The solution is to set the null-terminator directly after the string ends. In this case, you want your array to look like this:
Values = 1 0 1 \0 _
Index = 0 1 2 3 4
The value of index 4 is irrelevant, as the print function will terminate upon reading index 3.
Here's a code example for reference:
#include <stdio.h>
int main() {
const size_t length = 4;
char binary[length];
size_t i = 0;
while (i < length - 1) {
char c = getchar();
if (c == '0' || c == '1')
binary[i++] = c;
}
binary[i] = '\0';
puts(binary);
return 0;
}
#include<stdio.h>
int binary(int x)
{
int y,i,b,a[100];
if(x<16)
{
if(x%2==1)
a[3]=1;
if(x/2==1||x/2==3 || x/2==5 || x/2==7)
a[2]=1;
if(x>4 && x<8)
a[1]=1;
else if(x>12 && x<16)
a[1]=1;
if(x>=8)
a[0]=1;
}
for(i=0;i<4;i++)
printf("\t%d",a[i]);
printf("\n");
}
int main()
{
int c;
printf("Enter the decimal number (less than 16 ):\n");
scanf("%d",&c);
binary(c);
}
this code might help it will simply convert the decimal number less than 16 into the 4 digit binary number.if it contains any error than let me know

Conversion of Char to Binary in C

I am trying to convert a character to its binary representation (so character --> ascii hex --> binary).
I know to do that I need to shift and AND. However, my code is not working for some reason.
Here is what I have. *temp points to an index in a C string.
char c;
int j;
for (j = i-1; j >= ptrPos; j--) {
char x = *temp;
c = (x >> i) & 1;
printf("%d\n", c);
temp--;
}
We show up two functions that prints a SINGLE character to binary.
void printbinchar(char character)
{
char output[9];
itoa(character, output, 2);
printf("%s\n", output);
}
printbinchar(10) will write into the console
1010
itoa is a library function that converts a single integer value to a string with the specified base.
For example... itoa(1341, output, 10) will write in output string "1341".
And of course itoa(9, output, 2) will write in the output string "1001".
The next function will print into the standard output the full binary representation of a character, that is, it will print all 8 bits, also if the higher bits are zero.
void printbincharpad(char c)
{
for (int i = 7; i >= 0; --i)
{
putchar( (c & (1 << i)) ? '1' : '0' );
}
putchar('\n');
}
printbincharpad(10) will write into the console
00001010
Now i present a function that prints out an entire string (without last null character).
void printstringasbinary(char* s)
{
// A small 9 characters buffer we use to perform the conversion
char output[9];
// Until the first character pointed by s is not a null character
// that indicates end of string...
while (*s)
{
// Convert the first character of the string to binary using itoa.
// Characters in c are just 8 bit integers, at least, in noawdays computers.
itoa(*s, output, 2);
// print out our string and let's write a new line.
puts(output);
// we advance our string by one character,
// If our original string was "ABC" now we are pointing at "BC".
++s;
}
}
Consider however that itoa don't adds padding zeroes, so printstringasbinary("AB1") will print something like:
1000001
1000010
110001
unsigned char c;
for( int i = 7; i >= 0; i-- ) {
printf( "%d", ( c >> i ) & 1 ? 1 : 0 );
}
printf("\n");
Explanation:
With every iteration, the most significant bit is being read from the byte by shifting it and binary comparing with 1.
For example, let's assume that input value is 128, what binary translates to 1000 0000.
Shifting it by 7 will give 0000 0001, so it concludes that the most significant bit was 1. 0000 0001 & 1 = 1. That's the first bit to print in the console. Next iterations will result in 0 ... 0.
Your code is very vague and not understandable, but I can provide you with an alternative.
First of all, if you want temp to go through the whole string, you can do something like this:
char *temp;
for (temp = your_string; *temp; ++temp)
/* do something with *temp */
The term *temp as the for condition simply checks whether you have reached the end of the string or not. If you have, *temp will be '\0' (NUL) and the for ends.
Now, inside the for, you want to find the bits that compose *temp. Let's say we print the bits:
for (as above)
{
int bit_index;
for (bit_index = 7; bit_index >= 0; --bit_index)
{
int bit = *temp >> bit_index & 1;
printf("%d", bit);
}
printf("\n");
}
To make it a bit more generic, that is to convert any type to bits, you can change the bit_index = 7 to bit_index = sizeof(*temp)*8-1

Resources