How to create array with hex chars from array of numbers - c

I have array of chars:
char macChars=[12];
The content of it is e.g. macChars[0]=53, macChars[1]=66 ...
I need to convert these numbers to hex chars, so i would have another array:
macCharsHex[0]=5 //value 53 in hex
macCharsHex[1]=B //value 66 in hex
Thank you.

Assuming ASCII, your example already does contain the values you want them to contain. So you don't have to convert anything. Maybe you want to print them?

This should work:
char hex[255] = {0}; // Varible to hold the hex value
int dec = 1234; // Decimal number to be converted
sprintf(hex,"%X", dec);
printf("%s", hex); // Print hex value

Use sprintf(), for instance. Note that it will take more space, if you have 12 bytes you will need 24 + 1 bytes for the string representation, since each byte requires two characters in hex and then the terminating '\0'-byte.
I suspect that I don't understand the question at all, especially not the example given.
If you have macChars[0] == 53, which is 0x35 in hex, then I would expect to get maxCharsHex[0] == '3' and macCharsHex[1] == '5' after the first char has been converted. This is done like so with sprintf():
sprintf(maxCharsHex, "%02x", (int) macChars[0] & 0xff);
The cast and mask is to be on the safe side for signed characters.

They are already converted, since character in C are represented by their corresponding character codes.
Therefore, as far as storing things in arrays is concerned there is nothing you need to do and if you want "5" and "B" to show up correctly when printing or doing something like that its a matter of using the correct printing function (putchar, printf with %c, etc).

Related

Why does this variable equal a number and a character?

While debugging this code snippet here:
int main () {
char str[] = "Stackoverflow";
char a = *str;
return 0;
}
Why does a show as 83 'S'?
I think you might want to have more than one thing clarified:
First, pointer str points to the first character of a sequence of character values in memory, i.e. S, t, a, ...
Then, *str dereferences this pointer, i.e. it reads the value of the character to which str points. Hence *str yields S.
Statement char a = *str assigns the value S to variable a of type char, which represents a portion of memory capable of storing one character. Usually, char is an 8 bit signed (or unsigned) integral value, and any simple character is therefore represented by a value between -127 and +128 (the range of signed 8 bit values). The character value S, for example, seems to be represented as integral value 83 according to ASCII. Whether a system uses ASCII or some other character set is system defined, but ASCII is by far the most common character set today.
So S and 83 are actually the same thing, it's just that when a terminal interprets value 83 to be printed as character, it prints S. The other way round, if we interpret S as integral value, a terminal would print 83:
#include <stdio.h>
int main() {
printf("'S' as integral value: %d\n", 'S');
printf("83 as character value: %c\n", 83);
char c1 = 'S';
char c2 = 83;
if (c1 == c2) {
printf("c1 and c2 are equal.\n");
} else {
printf("c1 and c2 are not equal.\n");
}
}
Output:
'S' as integral value: 83
83 as character value: S
c1 and c2 are equal.
83 is the ASCII code for uppercase letter 's'.
*str is equal to writing str[0] so in this case the first memory slot of the array str which corresponds to the character 'S'
Computers understand everything as numbers: Characters, strings, photos, videos, audio ... etc. Everything is a number inside a computer and thus people wondered how to represent characters.
And because of this fact, they decided to encode characters as numbers so that every character has a corresponding number that encodes it inside the computer.
Throughout history, many character encoding schemes (A matching between characters and numbers) have been worked out but one of them is very famous and almost used everywhere : It's called ASCII character encoding. ASCII is a 7-bits encoding that represents all numerical characters and Latin alphabet characters (Uppercase and lowercase) beside some other symbols.
By default, your system provides ASCII input to your C program and thus, internally, this input is stored in memory as ASCII standard says. For instance, when you type A on your keyboard, the keyboard sends the value 65 (This is the decimal value of the character A in the ASCII standard. Internally, it is sent as a sequence of 1000001101 because computers work in binary) to your program. Your program stores this value (65) inside a memory location specified by a variable (char c;). When you ask the computer to print this character, it checks the ASCII value stored in the character's variable and then figures out a way how to draw the matching symbol on the screen.
In C, strings are just a sequence (Or an array) of characters. When you hold a pointer to a string, it actually points to the first character of the string (The character array). If you advance the pointer by 1, you will point to the second character and so on. So, if you dereference your original pointer (That points to the first character), you will get the ASCII value of the character stored in that position (The first position) and thus in your case you get 83 which corresponds to the symbol 'S'.
The program below shows all ASCII characters and their graphical representation : Some few characters might not have a visual representation because they are used for controlling input and terminal, especially, the first few characters (First 34 values).
#include <stdio.h>
int main ()
{
/* Unsigned to avoid integer overflow in the loop below */
unsigned char c;
/* ASCII is 7-bit so it can represent
2^7 = 128 (from 0 to 127) symbols */
for (c = 0; c < 128; c++)
printf ("ASCII value of %c = %d\n", c, c);
return 0;
}

Writing one byte in struct variable

I'm trying to modify one byte of my structure with the following code :
struct example *dev;
PRINT_OPAQUE_STRUCT(dev);
sprintf((char*) dev + 24, "%x",1);
PRINT_OPAQUE_STRUCT(dev);
The PRINT_OPAQUE_STRUCT is just printing the content of the structure, and is defined in this other topic :
Print a struct in C
The output of this program is :
d046f64f20b3fb4f00000000e047f64f00000000ffffffff000000
d046f64f20b3fb4f00000000e047f64f00000000ffffffff310000
I don't know why I have the value "31" written and not the value "01" as wanted. I tried to replace the second argument of sprintf with "%01x" but it didn't change anything. Anyone knows why?
Thanks!
Well, you are formatting the value 1 as a string. That's what sprintf does. 0x31 is the character code for the character '1'. If you just want to write the byte value 0x01 into your struct, then you don't need sprintf. Just do this:
*((char*)dev + 24) = 1;
or (the same, but with slightly different syntax):
((char*)dev)[24] = 1;
Note also, like one comment below says, sprintf will not just write one single byte. Since it writes a string, and C strings are null-terminated, it will also write a null character ('\0', 0x00) right after the '1'.
I don't know why I have the value "31" written and not the value "01" as wanted.
The reason you see 31 is that your chain of functions interprets the value 1 twice:
First, sprintf interprets it as a character representing a hex digit
Second, PRINT_OPAQUE_STRUCT interprets the value again, now as a hex number
Essentially, sprintf converts 1 to its character representation, which is '1'. On your system, its code is 0x31, hence the output that you get.
You need to remove one of these two interpretations to get your code to print 1. To remove the first interpretation, simply assign 1 to the pointer, like this:
((char*)dev)[24] = 1;
To remove the second interpretation, print with %c instead of %x in PRINT_OPAQUE_STRUCT (which may not be possible).

How to Send Hex string from uart to microcontroller and store it to integer for future "if" statement

okay, im really beg for a help here, cause im hittin a rock bottom. ive spend weeks to do this and still not able to.
i have an avr, i will recive a string containing hex value in it from UART.
ex :
0x3cffaa31
i need to split it into
0x3c
0xff
0xaa
0x31
and store it into a variable so i can do if statement with it.
how can i achieve this, please help me. i already lookin here and there on the internet yet i still lost.
uint8_t Values[4]={0};
uint8_t Loc=0;
uint32_t Mask=0xFF; //32 bits UART Rx Buffer size
for(uint8_t i=0;i<=24;i+=8)
{
Values[Loc]=(((Mask<<i) & UartRxBuf) >> i);
Loc++;
}
Help me out if I'm interpreting this wrong, but it sounds like you need to;
split the incoming string from the UART into indidual 2-character strings, each one representing a byte of hex. If you will always have 4 bytes of data, in the format that you've shown, then this will be easy. e.g. you always know that the two characters of the first byte are at index 2 and 3 of the char[] holding your input string.
Convert each two-character string to an int, so you can use them for numerical calculations. Look at strtol, which is available in AVR libc, for this http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__stdlib_1gaf8ce3b8dae3d45c34c3b172de503f7b3.html
Make sure to specify base16 for strtol-- e.g.:
long converted = strtol(digits, NULL, 16);
(where digits is a char[] containing your two hex characters, null-terminated)
UPDATE- looks like strtol doesn't care if the string has a preceding 0x, so something like this would work to get the first hex value from the raw string:
const char *raw = "0x3cffaa31";
char digits[3];
long converted;
/* Copy two bytes from 'raw', starting from index 2,
* (so we can skip the '0x') to get the string "3c" */
strncpy(digits, raw + 2, 2);
/* Make sure the new string is null-terminated */
digits[2] = '\0';
/* Convert hex string to a long. Now you can use it
* in an if-statement */
converted = strtol(digits, NULL, 16);
I donot think this is an issue
If you are using uart in 8bit mode you will recieve only one byte data at a time .
Just increase the array index every time you recieve the data
for(i = 0; i<4; i++){
while(UART_recieve_not_completed);
arr[i] = UART_RX_BUFF;}
Hope this helps

Calling the 1's, 10's, 100's... columns of an integer using a string array

I'm trying to convert a long long integer to a string array with the 1's column in position 0 of the array, the 10's column in position 1, the 100's column in position 2, like this:
INPUT: 4444555566667777 -----> OUTPUT: [4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7]
To test my code, I wrote for my last line printf("%d\n",number_str[3]). I expected my program to output the value of position 4, "7". Instead, it output "52". Changing my last line to printf("%d\n",number_str[4]) yields "53" instead of "6", as I expected. Can anyone explain what's going on?
Surely 52 and 53 correspond to ASCII values, but then, how can I convert them to integers? Can I do this in line?
Where I'm headed with this part of my program is to add up all of the numbers in the 10's, 1,000's, 100,000's, 10,000,000's... columns. Every other digit in a base-10 credit card number. This is one step in my attempt at a Luhn validation.
// Libraries
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Program
int main(void)
{
// Get CC number
printf("Enter your credit card number: ");
long long number_ll = GetLongLong();
// printf("%lld\n", number_ll);
// Convert long long to string
char number_str[64];
sprintf(number_str, "%lld", number_ll);
// printf("%s\n", number_str);
// Get length of card number string
int cclength = strlen(number_str);
// Check the length of card number string
if ( ! (cclength == 13 || cclength == 15 || cclength == 16))
printf("INVALID\n");
else
printf("%d\n",number_str[3]);
To convert ascii into integer use
#include <stdlib.h>
int atoi(const char *str);
change this
printf("%d\n",number_str[3]);
to
char buf[2];
buf[0]=number_str[3];
buf[1]='\0';
printf("%d\n",atoi((const char*)buf));
Using "%d" on a char will print its ASCII code. Use "%c" to print itself.
And your string's order is reversed compared to your purpose. The rightmost digit(1's column) is at the tail of the string, and the leftmost one is in position 0.
So to print the number at position i (count from right to left), you should use:
printf("%c\n", number_str[cclength - i - 1]);
I'm going to go ahead and expand on my comment since I don't believe either of the other answers responded to your full question.
By reading the CC number into a long long, and then using sprintf to plug the number into a character array, I would say you're correctly getting the number into a form that you can use for validation. In fact, you can check the return value of sprintf to see whether or not it's a valid number (although a failure case would be unlikely since you're plugging in a long long.
Once you have the CC number in a character array, you know that each element of the array will contain one character, which corresponds to one digit in the CC number. It sounds like for your purposes, it's more useful for the values in the array to be the decimal values, rather than the ASCII values. Logically, this is the difference between the values '0' and 0. You can look up any ASCII chart to see the corresponding ASCII value for each character, but since characters can be manipulated just like integers, you can traverse the array:
for(i = 0; i < 64; i++) num_str[i] -= '0';
Note that this doesn't handle there being less than 64 characters or uninitialized values in the array after the CC number characters, so you'll need to modify it. What's important to realize is that you're just shifting the character values down by '0', which happens to have the integer value 48.
Once you do this conversion, printing out a value in the array with printf using %d as the format specifier will work like you expect; even though the array data type is char, each element may be printed as a decimal integer.
Once you've read the number into the char array and made the conversion, all you need to do is traverse the array again, performing whatever steps are involved in the CC Validation process. You may need to traverse the array in reverse if the validation method requires the digits to be in order.

memcpy() to copy integer value to char buffer

I am trying to copy the memory value of int into the char buffer. The code looks like below,
#define CPYINT(a, b) memcpy(a, &b, 4)
............
char str1[4];
int i = 1;
CPYINT(str1, i);
printf("%s",s);
...........
When I print str1 it’s blank. Please clarify.
You are copying the byte representation of an integer into a char array. You then ask printf to interpret this array as a null terminating string : str1[0] being zero, you are essentially printing an empty string (I'm skipping the endianness talk here).
What did you expect ? Obviously, if you wanted to print a textual representation of the integer i, you should use printf("%d", i).
try
printf("%02X %02X %02X %02X\n", str1[0], str1[1], str1[2], str1[3]);
instead.
The binary representation of the integer 1, probably contains leading NULs, and so your current printf statement terminates earlier than you want.
What is your intention here? Right now you are putting arbitrary byte values into the char array, but then interpreting them as a string, as it happens the first byte is probably a zero (null) and hence your print nothing, but in all probability many of the characters will be unprintable, so printf is the wrong tool to use to check if the copy worked.
So, either: loop through the array and print the numeric value of each byte, %0xd might be useful for that or if your intention is actually to create a string representation of the int then you'll need a larger buffer, and space for a null terminator.
Maybe you need convert intger to char* in that way tou can use itoa function
link text

Resources