Related
I have a problem with STM32F401CCU. After executing a code disconnecting and connecting power the STM freezes and to unfreeze it I need to reload the build.
I have a complex set of functions that are used to turn an array of int values into a single very long char array. The char array is then written to the long term Flash memory. In order to execute that I do many operations with char arrays and they appear to be executed properly, as saving to Flash is done correctly - I tested Flash content with ST LINK and they are what they should be. But after turning power off/on to actually test if long term Flash memory works I encounter a fatal bug - upon powering STM back on it freezes and the only way to unfreeze it is to reload the build.
After many hours of tests I figured that the problem is with memcpy usage in StringCreateStrForFlashOneProduct. Presumably I created a sort of memory leak, but I don't get what's wrong.
A piece of example operation that causes STM to freeze:
static char send_save_string_final[2048];
char sssssend_char[2048] = "000000NewProduct";
char *StringCreateStrForFlashOneProduct(const int someint)
{
memcpy(sssssend_char, "000000008888008000000000888800800000000088880080", 48);
memcpy(send_save_string_final, sssssend_char, 48);
return send_save_string_final;
}
The code I actually use:
FUNCTION ONE - Creates a single array of chars and then saves it to flash memory
static char output_all_sorts[6001] = "";
char all_save_string[6001] = "";
char sssssend_char_all_sorts[2048] = "00000AllProducts";
char append_char_numz_all_sorts[17] = "0000000000000000";
void FlashSaveAllSorts(void)
{
strcpy(sssssend_char_all_sorts, "00000AllProducts");
sssssend_char_all_sorts[2047] = 0;
strcpy(output_all_sorts, "0");
output_all_sorts[6000] = 0;
strcpy(all_save_string, "00000AllProducts");
all_save_string[6000] = 0;
strcpy(append_char_numz_all_sorts, "0000000000000000");
append_char_numz_all_sorts[16] = 0;
for (int doin_int = 0; doin_int <= 6; doin_int++)
{
strcpy(sssssend_char_all_sorts, StringCreateStrForFlashOneProduct(doin_int));
strcat(all_save_string, sssssend_char_all_sorts);
strcpy(output_all_sorts, all_save_string);
}
strcpy(output_all_sorts, all_save_string);
output_all_sorts[strlen(output_all_sorts)] = 0;
Flash_Write_Data(0x08020000, output_all_sorts, 3000);
}
FUNCTION TWO - Creates a single line with all data for one product
static char send_save_string_final[2048] = "0";
char sssssend_char[2048] = "000000NewProduct";
char append_char_numz[17] = "0000000000000000";
char *StringCreateStrForFlashOneProduct(const int someint)
{
strcpy(send_save_string_final, "0");
send_save_string_final[2047] = 0;
strcpy(sssssend_char, "000000NewProduct");
sssssend_char[2047] = 0;
strcpy(append_char_numz, "0000000000000000");
append_char_numz[16] = 0;
strncpy(append_char_numz, StringCreateStringFromIntTwo(someint), 17);
append_char_numz[16] = 0;
strcat(sssssend_char, append_char_numz);
for (int kk = 0; kk < 3; kk = kk + 1)
{
char append_char_one[17] = "0000000000000000";
for (int jj = 0; jj < 12; jj = jj + 1)
{
char append_char[17] = "0000000000000000";
memcpy(append_char, StringCreateStringFromIntTwo(tunable_vars_machine_for_flash[someint][kk][jj]), 17);
strcat(sssssend_char, append_char);
}
memcpy(append_char_one, "000000000MenuEnd", 17);
strcat(sssssend_char, append_char_one);
}
char append_char_end_zeros[17] = "0000000000000000";
memcpy(append_char_end_zeros, StringCreateStringFromIntTwo(0), 17);
strcat(sssssend_char, append_char_numz);
memcpy(send_save_string_final, sssssend_char, 2047);
return send_save_string_final;
}
FUNCTION THREE - Creates a 16-chars array with a following format 000000000000001333, zeros are required to have consistent length of saved string, 1333 is example data value:
char *StringCreateStringFromIntTwo(int base_int_base)
{
//clearprint("StringCreateStri");
int base_int = base_int_base;
if (base_int == 0)
{
base_int = 999999; /// avoid saving zero to flash memory
}
static char send_char_final[17] = "0000000000000000";
char send_char[16] = "00000000";
static char send_char_sixteen_zeros[17] = "0000000000000000";
int legnewpigwphjh = strlen(send_char);
char str_zero[2] = "0";
char str_two_zeros[3] = "00";
char str_three_zeros[4] = "000";
char str_four_zeros[5] = "0000";
char str_five_zeros[6] = "00000";
char str_six_zeros[7] = "000000";
char str_seven_zeros[8] = "0000000";
char str_eight_zeros[9] = "00000000";
char str_sixteen_zeros[17] = "0000000000000000";
int int_mem_length = countDigits(base_int);
char str_mem_write_int[9];
sprintf(str_mem_write_int, "%d", base_int);
if (int_mem_length == 7)
{
strcat(send_char, str_zero);
}
if (int_mem_length == 6)
{
strcat(send_char, str_two_zeros);
}
if (int_mem_length == 5)
{
strcat(send_char, str_three_zeros);
}
if (int_mem_length == 4)
{
strcat(send_char, str_four_zeros);
}
if (int_mem_length == 3)
{
strcat(send_char, str_five_zeros);
}
if (int_mem_length == 2)
{
strcat(send_char, str_six_zeros);
}
if (int_mem_length == 1)
{
strcat(send_char, str_seven_zeros);
}
strcat(send_char, str_mem_write_int);
strcpy(send_char_final, str_sixteen_zeros);
strcpy(send_char_final, send_char);
return send_char_final;
}
Your code is way too complicated. There are too many string copies and concatenations, and countless useless operations. You do not seem to master pointers, nor basic memory layout concepts. Above all, given your skill level, you should absolutely avoid strncpy and memcpy.
Here is a simpler approach with functions that construct the appropriate string format at the end of the buffer and return the number of characters written. With this method, composing a long string is much simpler and much less error prone:
// function to construct a fixed length string of digits with leading 0s
// buffer must point to an array at least 17 bytes long
// returns the number of characters, ie: 16
int FormatNumber16(char *buffer, int someint) {
if (someint == 0) {
// This test seems bogus: the product number 0 will be written as 999999
// and so will the MenuEnd number
someint = 999999; // avoid writing 0 ???
}
return snprintf(buffer, 17, "%016d", someint);
}
// function to construct the product string to store to flash
// buffer must point to an array at least 641 bytes long
// returns the number of characters, ie: 640
int FormatOneProduct(char *buffer, int product_nb) {
int pos = 0;
pos += snprintf(buffer + pos, 17, "%016s", "NewProduct");
pos += FormatNumber16(buffer + pos, product_nb);
for (int kk = 0; kk < 3; kk++) {
for (int jj = 0; jj < 12; jj++) {
pos += FormatNumber16(buffer + pos,
tunable_vars_machine_for_flash[product_nb][kk][jj]);
}
}
pos += snprintf(buffer + pos, 17, "%016s", "MenuEnd");
// vvv this will actually append 0000000000999999 ?
pos += FormatNumber16(buffer + pos, 0);
// pos should be 640 = 16 + 16 + 12*3*16 + 16 + 16
return pos;
}
// function to write all product data to flash (7 products)
void FlashSaveAllSorts(void) {
char buffer[6001] = ""; // no need for global data
int pos = 0;
pos += snprintf(buffer + pos, 17, "%016s", "AllProducts");
// append the description of all 7 products (0 to 6 included)
for (int product_nb = 0; product_nb <= 6; product_nb++) {
pos += FormatOneProduct(buffer + pos, product_nb);
}
// buffer contains 4496 = 16 + 640*7 characters, why write 3000 bytes?
Flash_Write_Data(0x08020000, buffer, 3000);
}
Some example functions:
char *StringCreateStrForFlashOneProduct(char *buff, size_t len, int someint)
{
int mask = 1000000000;
char *wrk = buff;
if(!someint) someint = 999999;
memset(buff, '0', len - 10);
wrk += len - 10;
while(mask)
{
*wrk++ = '0' + abs(someint / mask);
someint %= mask;
mask /= 10;
}
*wrk = 0;
return buff;
}
example usage:
int main(void)
{
char str[17];
printf("`%s`\n", StringCreateStrForFlashOneProduct(str, 16, 1234));
}
I am currently dealing with a problem that especially has something to do with the first and second ASCII characters, the NULL Character and SOH Character.
The goal of this code is to send some characters and save them in a Tag, which contains 32 Bits/4 Bytes Blocks where Data can be saved in.
I know that there are better ways to achieve this. My Code functions nearly properly except in one single case:
When the Character equals the first ASCII character NULL. Which means when I view the value of the character: c_Char="", when this get sent to the Tag, it doesnt count as an ascii character and gets skipped.
Which means when I check which Characters are sent, the Buffer does not return the character with the 0 decimal value since it was not saved and got skipped.
Is there any If-Condition that I can use to make my program count the NULL ascii character?
This is part of the main Code:
// Splitting the 32 bits from B0 to 4 Bytes
Daten_EEPROM_Byte_VERTEILER(B0);
// Converting The four 32 Bits/4 Bytes Variables into 4 different decimal numbers
Data_Converting_binary_decimal(cFirst_Byte,&i_Char1);
Data_Converting_binary_decimal(cSecond_Byte,&i_Char2);
Data_Converting_binary_decimal(cThird_Byte,&i_Char3);
Data_Converting_binary_decimal(cFourth_Byte,&i_Char4);
//Converting the 4 decimal numbers into 4 ascii Chars.
Fmt(c_Char1,"%c<%i", i_Char1);
Fmt(c_Char2,"%c<%i",i_Char2);
Fmt(c_Char3,"%c<%i",i_Char3);
Fmt(c_Char4,"%c<%i",i_Char4);
//Converting Ascii characters into hexadecimal numbers.
DATEN_Umwandlungsfunktion_Char_hex (c_Char1, x_char1, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char2, x_char2, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char3, x_char3, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char4, x_char4, &iSeriennummer);
//Putting the 4 hex numbers into the one variable:
Fmt(x_Result_B0,"%s<%s%s%s%s",x_char1,x_char2,x_char3,x_char4);
//Showing the 4 hex numbers in a panel:
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_WB0, ATTR_CTRL_VAL, x_Result_B0);
memset(x_char1,0,sizeof(x_char1));
memset(x_char2,0,sizeof(x_char2));
memset(x_char3,0,sizeof(x_char3));
memset(x_char4,0,sizeof(x_char4));
//Sending the 4 characters into a MSP430 Port to save them in a tag through an antenna
Fmt(Result_Block0,"%s<%s%s%s%s",c_Char1,c_Char2,c_Char3,c_Char4);
Fmt(cCommand,"%s<%s%s%s%s",WRITE_BLOCK,"0_",Result_Block0,ENDE);
// Write and Read Data in and from Block 0
iResult = Befehl_Senden(cCommand,cAnswer);
Fmt(cCommand,"%s<%s%s%s",READ_BLOCK,"0",ENDE);
iResult = Befehl_Senden(cCommand,cAnswer);
CopyBytes(cRead_Block_0,0,cAnswer,23,8);
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_BR0, ATTR_CTRL_VAL, cRead_Block_0);
These are the following functions that are used to convert the variables:
char *decimal_to_binary(int n)
{
int c, d, t;
char *p;
t = 0;
p = (char*)malloc(32+1);
if (p == NULL)
exit(EXIT_FAILURE);
for (c = 31 ; c >= 0 ; c--)
{
d = n >> c;
if (d & 1)
*(p+t) = 1 + '0';
else
*(p+t) = 0 + '0';
t++;
}
*(p+t) = '\0';
return p;
}
void Daten_HILFSFUNKTION_binary_decimal (char *cEingang, int *iAusgang)
{
int multiplier = 0;
int i;
int sum = 0;
int length;
char cMonth[10] = {0};
int iMonth;
length = StringLength (cEingang);
for (i=length-1; i>=0; i--)
{
CopyBytes (cMonth, 0, cEingang, i, 1);
Fmt (&iMonth, "%x<%s", cMonth);
sum = sum +(iMonth*pow(2, multiplier));
multiplier = multiplier + 1;
}
Fmt (iAusgang, "%i<%i", sum);
}
void Daten_EEPROM_Byte_VERTEILER(char *B)
{
CopyBytes(cFirst_Byte, 0,B,0,8);
CopyBytes(cSecond_Byte, 0,B,8,8);
CopyBytes(cThird_Byte, 0,B,16,8);
CopyBytes(cFourth_Byte, 0,B,24,8);
}
char *Daten_EEPROM_HILFSFUNKTION(char *Char_in_Bits, char *c_8Bits)
{
int Decimal = 0;
char c_Character[5] = {0};
CopyString(Char_in_Bits, 0,c_8Bits,0,8);
Daten_HILFSFUNKTION_binary_decimal (Char_in_Bits, &Decimal);
int B_1_dec = Decimal;
Fmt(c_Character,"%c<%i",B_1_dec);
memset(Char_in_Bits,0,sizeof(Char_in_Bits));
return c_Character;
}
void DATEN_alle_Char_uerbergabe_Funktion (char *Byte_Block,char *c_Char1, char *c_Char2, char *c_Char3,char * c_Char4)
{
DATEN_erster_Char_uebergabe_Funktion(Byte_Block, c_Char1);
DATEN_zweiter_Char_uebergabe_Funktion(Byte_Block, c_Char2);
DATEN_dritter_Char_uebergabe_Funktion(Byte_Block, c_Char3);
DATEN_vierter_Char_uebergabe_Funktion(Byte_Block, c_Char4);
}
char DATEN_erster_Char_uebergabe_Funktion (char *Byte_Block,char *c_Char1)
{
return* c_Char1 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cFirst_Byte);
}
char DATEN_zweiter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char2)
{
return *c_Char2 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cSecond_Byte);
}
char DATEN_dritter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char3)
{
return *c_Char3 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cThird_Byte);
}
char DATEN_vierter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char4)
{
return *c_Char4 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cSecond_Byte);
}
void char_Umwandeln (char *cEingang,char *cAusgang)
{
int ilaenge;
int idez_Wert;
int iPos;
char cZwischenspeicher [5] = {0};
ilaenge = StringLength(cEingang);
for (iPos = 0; iPos <=ilaenge - 1; iPos++)
{
idez_Wert = 0;
//CopyBytes (cZwishcenspeicher, 0, cEingang, ilaenge-iPos,1);
CopyBytes (cZwischenspeicher,0,cEingang,iPos,1);
Scan (cZwischenspeicher,"%s>%i[r256]",&idez_Wert);
if (idez_Wert == 0)
{
CopyBytes (cAusgang, 0,"00",0,2);
}
else if (idez_Wert <16)
{
Fmt(cAusgang,"%s<%s%s%i[r16]",cAusgang,"0",idez_Wert);
}
else
{
Fmt(cAusgang,"%s<%s%i[r16]",cAusgang,idez_Wert);
}
}
StringUpperCase(cAusgang);
}
void DATEN_Umwandlungsfunktion_Char_hex (char *Char, char *hex_Char, int *dec_Nummer)
{
char_Umwandeln (Char,hex_Char);
Scan(&hex_Char,"%s>%x",&dec_Nummer);
}
If anyone has already had this problem and knows a solution for this issue, I would be so thankful. Thanks a lot in advance.
I'm able to read a hex file and store the content in a char buffer, i need to store the character in char buffer as hex value in a buffer as shown below. so that i can use that hex value to write into a hardware data register which accepts uint32_t only.
char * buffer =[AABBCCDDEE112233445566]
output:
partitioned_buffer= 0xAABBCCDD
partitioned_buffer= 0xEE112233
and so on. Can any one help on this. Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *fip_buffer;
char *emmc_pattern_buffer;
char hex_pattern() {
FILE *fileptr;
char *buffer;
long filelen;
int i,j;
fileptr = fopen("fip.hex", "rb");
if( fileptr == NULL ) {
printf("cannot open file");// exit(1);
}
fseek(fileptr, 0, SEEK_END);
filelen = ftell(fileptr);
rewind(fileptr);
fip_buffer = (char *)malloc((filelen+1)*sizeof(char));
for(i = 0; i < filelen; i++) {
fread(fip_buffer+i, 1, 1, fileptr);
}
fclose(fileptr); // Close the file
return(fip_buffer);
}
char hex_pattern_read(int a, int filelen){
char mem[8],mem2[7];
int i,j;
for(i=a;i<filelen;i++){
mem[j]=fip_buffer[i];
mem[8]='\0';
j++;
if(j==8){strcpy(mem2,mem);j=0; break;
}
}
emmc_pattern_buffer=mem2;
return(emmc_pattern_buffer);
}
int main(int argc, char **argv) {
printf("Reading hex file\n");
int i,j;
hex_pattern();
int len = strlen(fip_buffer);
//printf("size of buffer is=%d\n%c\n",len,fip_buffer);
for(i=0; i<2; i++){
// printf("Entered loop1");
for(j=0;j<3;j++){
int temp = (j*8)+(128*i);
hex_pattern_read(temp,len); //need to store the returned emmc_pattern_buffer character as hex value
printf("%02X\n",emmc_pattern_buffer);
}
}
return 0;
From comments ...
im reading the hex file content into a buffer, and the buffer has
series of characters in it as 12345678aa64000101681fa1ed19f39d41e...
and so, and im trying to read 8 character each time and im able to
print them, but i want to store that character to hex values.
... I understand that you are successfully reading the hexadecimal text representation of a 32-bit unsigned number from your input file, and you want to convert that to the machine's internal numeric representation. For this purpose, it makes no difference at all whether the bytes have have separate individual significance.
The easiest way to accomplish the task, then, is to make your buffer at least nine bytes long, so that it has room for eight hexadecimal digits plus a string terminator, ensure the terminator is present, and use the strtoul() function to perform the conversion:
char buffer[9];
// ... fill buffer, including terminator byte ...
char *end;
uint32_t value = strtoul(buffer, &end, 16);
if (end != buffer + 8) // ... handle bad data ...
You can write a function to convert the character to integer
uint32_t convertbyte(char *buffer)
{
uint32_t ret = 0;
uint8_t i;
for (i=0; i<8; i++)
{
ret *= 16;
if ((buffer[i] >= 'A') && (buffer[i] <= 'F'))
ret += buffer[i] - 'A' + 10;
else if ((buffer[i] >= '0') && (buffer[i] <= '9'))
ret += buffer[i] - '0';
else
{
printf (" Malformed input");
return 0;
}
}
return ret;
}
This function can then be called for each 32 bit integer you need to be converted.
#include <stdio.h>
#include <stdint.h>
uint32_t convertbyte(char *buffer);
int main(void)
{
char *buffer = "AABBCCDDEE112233445566";
uint32_t partitioned, partitioned2;
partitioned = convertbyte(buffer);
printf ("%X\n",partitioned);
partitioned2 = convertbyte(buffer+8);
printf ("%X\n",partitioned2);
return 0;
}
Output is
AABBCCDD
EE112233
If I understand question correctly, There is a file with byte stream which has to be sent to register by packing 4bytes each.
You can combine individual bytes to make uint32_t as follows,
uint32_t partitioned_buffer = (buffer[0]<<24u) | (buffer [1]<<16u) | (buffer[2]<<8u) | buffer[3];
You can even convert byte stream into o/p uint32_t buffer as follows,
uint32_t partitioned_buffer[op_bufferSize];
for(i =0;i<op_bufferSize;i++)
{
int offset = i<<2;
partitioned_buffer[i] = (buffer[offset+0]<<24u) | (buffer [offset+1 ]<<16u) | (buffer[offset+2]<<8u) | buffer[offset+3];
}
You can use the below functions to convert a string of hex representation to 32 bit(same as uint32_t) hex value.
int char2hex(char ch)
{
int value = -1;
switch(ch)
{
case '0' : value = 0;
break;
case '1' : value = 1;
break;
case '2' : value = 2;
break;
case '3' : value = 3;
break;
case '4' : value = 4;
break;
case '5' : value = 5;
break;
case '6' : value = 6;
break;
case '7' : value = 7;
break;
case '8' : value = 8;
break;
case '9' : value = 9;
break;
case 'A' :
case 'a' : value = 10;
break;
case 'B' :
case 'b' : value = 11;
break;
case 'C' :
case 'c' : value = 12;
break;
case 'D' :
case 'd' : value = 13;
break;
case 'E' :
case 'e' : value = 14;
break;
case 'F' :
case 'f' :value = 15;
break;
}
return value;
}
long str2longhex(char * str){
int nibble = 0;
long hex_value = 0;
for(unsigned int str_i = 0; str_i < 8; str_i++){
#if 1 //Change the 1 to 0 if you want to reverse the endianess
nibble = char2hex(str[str_i]);
#else
nibble = char2hex(str[7-str_i]);
#endif
if(nibble < 0){
//Not a hex representation.
return -1;
}
hex_value = ((hex_value<<4)&0xFF) | nibble;
}
return hex_value;
}
int main()
{
char * buffer = "AABBCCDDEE112233445566";
long value = 0;
unsigned int buffer_i = 0;
while(buffer_i+8 <= strlen(buffer))
{
value = str2longhex(&buffer[buffer_i]);
printf("partitioned_buffer:0x%08lX\n",value);
buffer_i += 8;
}
return 0;
}
Usually in hex files(if you meant files with .hex) data is stored from lowest memory location to highest that is if the text file contains "AABBCCDD" the corresponding hex value will be 0xDDCCBBAA. Don't know about the representation in your file but do check it.
How can I convert integer value to ASCII characters in C language?
I want to assign characters to array of chars.
char buff[10];
Let's say we have:
int = 93 (HEX: 5D) -> result should be - buff = {']'}
int = 13398 (HEX: 3456) -> result should be buff = {'4', 'V'}
Similar as is done here
I don't need to care about non printable characters. There will be always printable characters.
Just use bit-shifting to get the individual bytes.
Assuming an architecture on which the size of int is 4:
int someInt = ...
uint8_t first = (someInt >> 24);
uint8_t second = (someInt >> 16);
uint8_t third = (someInt >> 8);
uint8_t fourth = someInt;
Now you can just put the resulting bytes into your array. Make sure to check first, second and third to make sure they're not 0 first, and skip them if they are. Make sure to end your array with a null terminator, as required by C strings.
This answer assumes big-endian ordering, since that's what you indicated in your example. If you want little-endian, just reverse the order of the bytes when you put them in the array.
Note that this will turn 5DC into 05 and DC. If you want 5D instead, you should check to see whether the first digit in the original int is 0. You can do this using the & operator, testing the int against 0xf0000000, 0x00f00000, etc. If you find the first digit to be 0, shift the int to the right by 4 bits before extracting the bytes from it.
So, something like this:
void ExtractBytes(int anInt, uint8_t *buf, size_t bufSize) {
// passing an empty buffer to this function would be stupid,
// but hey, doesn't hurt to be idiot-proof
if (bufSize == 0) { return; }
// Get our sizes
const int intSize = sizeof(anInt);
const int digitCount = intSize * 2;
// find first non-zero digit
int firstNonZero = -1;
for (int i = 0; i < digitCount; i++) {
if ((anInt & (0xf << ((digitCount - 1 - i) * 4))) != 0) {
firstNonZero = i;
break;
}
}
if (firstNonZero < 0) {
// empty string; just bail out.
buf[0] = 0;
return;
}
// check whether first non-zero digit is even or odd;
// shift if it's odd
int intToUse = (firstNonZero % 2 != 0) ? (anInt >> 4) : anInt;
// now, just extract our bytes to the buffer
int bufPtr = 0;
for (int i = intSize - 1; i >= 0; i--) {
// shift over the appropriate amount, mask against 0xff
uint8_t byte = (intToUse >> (i * 8));
// If the byte is 0, we can just skip it
if (byte == 0) {
continue;
}
// always check to make sure we don't overflow our buffer.
// if we're on the last byte, make it a null terminator and bail.
if (bufPtr == bufSize - 1) {
buf[bufPtr] = 0;
return;
}
// Copy our byte into the buffer
buf[bufPtr++] = byte;
}
// Now, just terminate our string.
// We can be sure that bufPtr will be less than bufSize,
// since we checked for that in the loop. So:
buf[bufPtr] = 0;
// Aaaaaand we're done
}
Now let's take it for a spin:
uint8_t buf[10];
ExtractBytes(0x41424344, buf, 10);
printf("%s\n", buf);
ExtractBytes(0x4142434, buf, 10);
printf("%s\n", buf);
and the output:
ABCD
ABC
convert integer value to ASCII characters in C language?...
Referring to an ASCII table, the value of ']' in C will always be interpreted as 0x5D, or decimal value 93. While the value of "]" in C will always be interpreted as a NULL terminated char array, i.e., a string representation comprised of the values:
|93|\0|
(As illustrated in This Answer, similar interpretations are valid for all ASCII characters.)
To convert any of the integer (char) values to something that looks like a "]", you can use a string function to convert the char value to a string representation. For example all of these variations will perform that conversion:
char strChar[2] = {0};
sprintf(strChar, "%c", ']');
sprintf(strChar, "%c", 0x5D);
sprintf(strChar, "%c", 93);
and each produce the identical C string: "]".
I want to assign characters to array of chars...
example of how to create an array of char, terminated with a NULL char, such as "ABC...Z":
int i;
char strArray[27] = {0};
for(i=0;i<26;i++)
{
strArray[i] = i+'A';
}
strArray[i] = 0;
printf("Null terminated array of char: %s\n", strArray);
unsigned u = ...;
if (0x10 > u)
exit(EXIT_FAILURE);
while (0x10000 < u) u /= 2;
while (0x1000 > u) u *= 2;
char c[2] = {u / 0x100, u % 0x100);
im working on an assmebler project that i have and i need to translate binary machine code that i have to a "weird" 4 base code for example
if i get binary code like this "0000-10-01-00" i should translate it to "aacba"
00=a
01=b
10=c
11=d
i have managed to translate the code to 4 base code but i dont know how to continue from there or if this is the right way to do it,...
adding my code below
void intToBase4 (unsigned int *num)
{
int d[7];
int j,i=0;
double x=0;
while((*num)>0)
{
d[i]=(*num)%4;
i++;
(*num)=(*num)/4;
}
for(x=0,j=i-1; j>=0; j--)
{
x += d[j]*pow(10,j);
}
(*num)=(unsigned int)x;
}
I've included a little 32-bit to num to letter converter for you to grasp the basics. It works a single "32-bit number" at a time. You could use this as a basis for an array based solution like you have half way done in your example, or change the type to be bigger, or whatever. It should show you roughly what you need to do:
void intToBase4 (uint32_t num, char *outString)
{
// There are 16 digits per num in this example
for(int i=0; i<16; i++)
{
// Grab the lowest 2 bits and convert to a letter.
*outString++ = (num & 0x03) + 'a';
// Shift next 2 bits low
num >>= 2;
}
// NUL terminate string.
*outString = '\0';
}
A bit more universal one:
Usage:
value - value to decode, buff - buff where result string will be stored, numofwrds - number of fields to be decoded, ... fields sizes in bits
example "xxxxyyvvzz": - 4 bits, two bits, two bits, two bits
decode(v, buff, 4, 4, 2, 2, 2);
char dictionary[] = "abcdefghijklmnopqrstuwxyz";
char *decode(unsigned int value, char *buff, int numofwrds, ...)
{
va_list vl;
int *fieldsizes = malloc(sizeof(int) * numofwrds);
int bitsize = 0;
char *result = NULL;
if (fieldsizes != NULL)
{
va_start(vl, numofwrds);
for (int i = 0; i < numofwrds; i++)
{
fieldsizes[i] = va_arg(vl, int);
bitsize += fieldsizes[i];
}
va_end(vl);
for (int i = 0; i < numofwrds; i++)
{
unsigned int mask, offset;
mask = (1 << fieldsizes[i]) - 1;
offset = bitsize - fieldsizes[i];
mask <<= offset;
buff[i] = dictionary[(value & mask) >> offset];
bitsize -= fieldsizes[i];
}
free(fieldsizes);
result = buff;
}
buff[numofwrds] = '\0';
return result;
}