how to fill an array with 0's in C - c

For my project i need to make an hexadecimal calculator and additional to that i need to convert it to binary and show it, witch i know is easy. The max of hexadecimal i can read is '8' but if i read a hexadecimal with less than 8 characters i need to fulfill the first binary numbers with 0. Ej:
in Hex:ADA0CAFE
in Binary:10101101 10100000 11001010 11111110
but if i get an hex like:C45FA
the output should be: 00000000 00001100 01000101 11111010
Part of my code look something like this:
char hex[100];
printf("Hexadecimal: ");
scanf("%s",hex);
convert(hex);
and the function to convert it:
void convert(char hex[]){
for(i=0;i<8;i++){
switch(hex[i]){
case '0': printf("0000"); break;
case '1': printf("0001"); break;
case '2': printf("0010"); break;
case '3': printf("0011"); break;
.
.
.
}
So the part i dont figure out how to is to get the first position of the array fill with 0 and then start writing the array with the character of the hexadecimal.

In convert find the length of the hex string passed, and put out leading 0000 strings to make up the length to 8. Perhaps like this:
void convert(char hex[]){
size_t len, i;
len = strlen(hex);
for(i = len; i < 8; i++) {
printf("0000"); // pad with leading zeros
}
for(i = 0; i < len; i++) { // the rest of the string
switch(hex[i]) {
case '0': printf("0000"); break;
case '1': printf("0001"); break;
case '2': printf("0010"); break;
case '3': printf("0011"); break;
.
.
.
}
}
}

Related

Changing number from character array to int array with decimal value

I am starting to learn C and I am having problem with changing numbers from character array to integer array. Here is my Code and I got random number and I have no idea why I am having those numbers.
The answer is 0 , 45, 45, 45
and I used 15 for plus sign, 25 for minus, 35 for multiply and 45 for division just for testing.
And also the answer which I want is if char[]="+123"-> int[0]=15;int[1]=1;int[2]=2;int[3]=3;
Thanks in advance and very much appreciated!
#include <stdio.h>
int main(){
int i=0;
char retezec[]="123+";
int array_length=(sizeof(retezec) / sizeof(retezec[0])-1);
int new_array[50];
while(retezec[i++]!='\0'){
switch(retezec[i]){
case '0':
new_array[i]=0;
case '1':
new_array[i]=1;
case '2':
new_array[i]=2;
case '3':
new_array[i]=3;
case '4':
new_array[i]=4;
case '5':
new_array[i]=5;
case '6':
new_array[i]=6;
case '7':
new_array[i]=7;
case '8':
new_array[i]=8;
case '9':
new_array[i]=9;
case '+':
new_array[i]=15;
case '-':
new_array[i]=25;
case '*':
new_array[i]=35;
case '/':
new_array[i]=45;
}
}
for(int i=0;i<array_length;i++){
printf("%d\n",new_array[i]);
}
}
Adding with the previous answers the reason you are getting 45 every time is that you haven't given the break keyword in every condition of switch case. Just add it and you will get the desired output :)
For example:
case '0':
new_array[i]=0;
break;
See the link below to have a good understanding. Hope it will help you.
https://www.programiz.com/c-programming/c-switch-case-statement
In your code -
while(retezec[i++]!='\0'){
switch(retezec[i]){
....
i is 0 when while loop condition is first evaluated, but in switch i already becomes 1. So your switch block checks elements from index 1 and not 0. Same way new_array is populated from index 1. The new_array[0] then have garbage value (as you are not initializing new_array)
You can use a for loop which will loop until array_length instead of the while loop like -
for (i = 0; i < array_length; i++) {
switch(retezec[i]) {
....
}
}
Also the switch case looks like an overkill. May be replace it with if-else
This can be boiled down significantly knowing that the C standard define the binary representation of 0 to 9 to necessarily be continuous.
#include <stdlib.h> /* for calloc() */
#include <stdio.h> /* for fprintf() */
int main(void)
{
char retezec[] = "123+";
size_t array_length = sizeof retezec / sizeof *retezec; /* sizeof evaluates to size_t not int. */
int * new_array = calloc(array_length * sizeof *new_array); /* Only get as much as needed, and have set to all 0s. */
if (NULL == new_array)
{
perror("calloc() failed");
return EXIT_FAILURE;
}
for (size_t i = 0; retezec[i] != '\0'; ++i) /* Use a for-loop where a for-loop can be used. */
{
switch(retezec[i])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
new_array[i] = retezec[i] - '0';
break;
case '+':
new_array[i] = 15;
break;
case '-':
new_array[i] = 25;
break;
case '*':
new_array[i] = 35;
break;
case '/':
new_array[i] = 45;
break;
default:
sprintf(stderr, "Unhandled character: '%c'\n", retezec[i]);
break;
}
}
for(size_t i = 0; i < array_length; ++i)
{
printf("%d\n", new_array[i]);
}
free(new_array);
return EXIT_SUCCESS;
}

How can i speed up hexadecimal characters conversion to binary characters

I have already a function that convert hex char(input) to binary char(output). it works perfect, for small amount of data(input length).But when the input is too big, it stuck/not working. May be strcat take too much time. Is there some alternate solution, So i can convert big hex input characters into equivalent binary.
My function is:
void fun_hex_ch_2bin(int len_hex_str,uint8_t *hex,uint8_t *bin){
/* Extract first digit and find binary of each hex digit */
int i=0,j=0;
char array_hex[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
uint8_t *new_hex=malloc(len_hex_str*2);
char hex_char1,hex_char2;
j=0;
for(i=0;i<len_hex_str;i++)
{
hex_char1=array_hex[hex[i]&0x0f];
hex_char2=array_hex[(hex[i]>>4)&0x0f];
//printf("%c %c\n",hex_char1,hex_char2);
new_hex[j]=hex_char2;
new_hex[j+1]=hex_char1;
j=j+2;
}
for(i=0; i<len_hex_str*2; i++)
{
switch(new_hex[i])
{
case '0':
strcat(bin, "0000");
break;
case '1':
strcat(bin, "0001");
break;
case '2':
strcat(bin, "0010");
break;
case '3':
strcat(bin, "0011");
break;
case '4':
strcat(bin, "0100");
break;
case '5':
strcat(bin, "0101");
break;
case '6':
strcat(bin, "0110");
break;
case '7':
strcat(bin, "0111");
break;
case '8':
strcat(bin, "1000");
break;
case '9':
strcat(bin, "1001");
break;
case 'a':
case 'A':
strcat(bin, "1010");
break;
case 'b':
case 'B':
strcat(bin, "1011");
break;
case 'c':
case 'C':
strcat(bin, "1100");
break;
case 'd':
case 'D':
strcat(bin, "1101");
break;
case 'e':
case 'E':
strcat(bin, "1110");
break;
case 'f':
case 'F':
strcat(bin, "1111");
break;
default:
printf("Invalid hexadecimal input.");
}
}
}
Just use sprintf() instead of strcat()
char *bin; // points to a long enough buffer
int binlen = 0;
binlen += sprintf(bin + binlen, "something"); // strcat(bin, "something");
binlen += sprintf(bin + binlen, "otherthing"); // strcat(bin, "otherthing");
binlen += sprintf(bin + binlen, "foobar"); // strcat(bin, "foobar");
//...
// you can even do
binlen += sprintf(bin + binlen, "%.2f", 2.71828); // strcat(bin, "2.72");
16 is a power of 2 so converting it to binary is pretty simple.
Each hex digit corresponds to exactly 4 binary digits - and you can rely on this fact.
As a first step you need to convert the input characters from ASCII to numeric values.
That's easily done in one pass over the input hex string and subtracting 48 if the character is between '0' and '9' or subtracting 88 if the character is between 'a' and 'f' (take a look at the ASCII table if need an explanation on why).
After that the conversion is straightforward - go over the hex array and for each hex value take a look at the last bit and proceed to the next bit exactly 4 times, move to the next hex value and repeat the procedure.
Something like this:
int i = 0, j = 0;
while(i < len_hex_str)
{
bin[j++]=hex[i] & 1;
hex[i] >>= 1;
if(j % 4 == 0) i++;
}
And since you seem to be in need to have it ASCII representation, just pass over the output string and add 48 to each digit.
How can i speed up hexadecimal characters conversion to binary characters (?)
May be strcat take too much time.
Yes. Each call to strcat() takes longer and longer time as code does not take advantage of data already converted.
strcat() take n time to traverse the first characters.
1st strcat call, n = 0
2st strcat call, n = 8
3rd strcat call, n = 16
4th strcat call, n = 24
ith strcat call, n = 8*(i-1)
See how the sum (0+8+16+24+...) goes up by order of i*i as i increases?
Note that the first call to strcat(bin, ...) is suspect as bin[0] is not certainly a null character - something required when concatenating to a string.
Is there some alternate solution (?)
I recommend a re-write. Directly read from hex as binary and skip the in-between conversion to hexadecimal.
void fun_hex_ch_2bin(int len_hex_str, uint8_t *hex, uint8_t *bin) {
while (len_hex_str > 0) {
len_hex_str--;
// Start with the MSBit
for (uint8_t mask = 0x80; mask; mask >>=1) {
*bin++ = mask & *hex ? '1' : '0';
}
hex++;
}
// Append a null character as `bin` is to point to a _string_.
*bin = '\0';
}
I'd expect bin, as a string to be char* and not unit8_t *.

How to get rid of the Heap-corruption error (Critical error c0000374) in C when converting hex into binary string?

Part of my project, where we have to take an input file with hex numbers and convert them to MIPS code, I want to convert the hex into binary so it'd be easier for me to convert it into MIPS. However, when I run the code, it crashes and quits when it reaches the part where it calls the converter function. GDB says its a critical error c0000374. How do I fix this?
I have tried giving the target string more space and it doesn't seem to have any effect. I have also tried using malloc to no avail.
char* convertBinary (int hex)
{
char* hexdec = calloc(9, sizeof(char));
char* bin = calloc(SIZE+1, sizeof(char));
snprintf(hexdec, SIZE, "%08X", hex);
long int i;
for (i = 0; hexdec[i]; ++i)
{
switch (hexdec[i])
{
case '0':
strcat(bin, "0000");
break;
case '1':
strcat(bin, "0001");
break;
case '2':
strcat(bin, "0010");
break;
case '3':
strcat(bin, "0011");
break;
case '4':
strcat(bin, "0100");
break;
case '5':
strcat(bin, "0101");
break;
case '6':
strcat(bin, "0110");
break;
case '7':
strcat(bin, "0111");
break;
case '8':
strcat(bin, "1000");
break;
case '9':
strcat(bin, "1001");
break;
case 'A':
case 'a':
strcat(bin, "1010");
break;
case 'B':
case 'b':
strcat(bin, "1011");
break;
case 'C':
case 'c':
strcat(bin, "1100");
break;
case 'D':
case 'd':
strcat(bin, "1101");
break;
case 'E':
case 'e':
strcat(bin, "1110");
break;
case 'F':
case 'f':
strcat(bin, "1111");
break;
default:
printf("\nInvalid hexadecimal digit %c",
hexdec[i]);
}
}
return bin;
}
Also, in case it helps, here is the main function where I call this function
int main ()
{
int command = 10010100; //This is in hex
char* binaryString = convertBinary(command);
printf("The coverted binary is: %s\n", binaryString);
}
I expect the function to return a string of the binary numbers that have been converted from an 8 digit hex number. However, the program just quits and doesn't output anything. When debugged with GDB, it lays out a warning saying,
warning: Critical error detected c0000374
There are multiple problems in your code:
You do not check the for memory allocation failure.
Since you allocate 9 bytes for hexdec, snprintf(hexdec, SIZE, "%08X", hex); should be
snprintf(hexdec, 9, "%08X", hex);
The definition of SIZE is missing, as well as the #include lines. Post the complete source of the program exhibiting the offending behavior.
There is no need to loop until the end of the string hexdec: since you convert the hex value with %08X, just loop with:
for (i = 0; i < 8; ++i)
You should free(hexdec) before leaving the convertBinary function.
The code and comment do not agree in int command = 10010100; //This is in hex, which one is wrong? Probably both.
There is no need to use long type for i, int will suffice. Conversely, the argument hex should have unsigned int type.
Here is a simplified version of your code:
#include <stdio.h>
#include <stdlib.h>
char *convertBinary(unsigned int hex) {
char *bin = calloc(33, 1);
int i;
if (bin) {
for (i = 32; i-- > 0;) {
bin[i] = '0' + (hex & 1);
hex >>= 1;
}
}
return bin;
}
int main() {
int command = 0x10010100; //This is in hex
char *binaryString = convertBinary(command);
if (binaryString == NULL) {
printf("Memory allocation failure\n");
} else {
printf("The converted binary is: %s\n", binaryString);
free(binaryString);
}
return 0;
}

Assigning a string in a char * array to another char * array

I am trying to convert the hex values in array a to binary values and assign converted values to array b then print the array b. But all values in array b are same. The output is:
111100001011000100010111101010001101
111100001011000100010111101010001101
111100001011000100010111101010001101
If I use b[i] = strdup(hexToBin(a[i])); instead of b[i] = hexToBin(a[i]); the output will be:
111100001011
111100001011000100010111
111100001011000100010111101010001101
Is this something about pointers? Char * is a pointer which points first character of the string and are all characters after the pointer printed? What is right way of doing this?
#include <stdio.h>
#include <string.h>
char bin[100] = "";
char * hexToBin(char hex[50]);
int main(void) {
char * a[] = {
"f0b",
"117",
"a8d",
};
char * b[3];
for(int i = 0; i < 3; i++) {
b[i] = hexToBin(a[i]);
}
for(int i = 0; i < 3; i++) {
printf("%s\n", b[i]);
}
}
char * hexToBin(char hex[50]) {
for(int i=0; hex[i]!='\0'; i++)
{
switch(hex[i])
{
case '0':
strcat(bin, "0000");
break;
case '1':
strcat(bin, "0001");
break;
case '2':
strcat(bin, "0010");
break;
case '3':
strcat(bin, "0011");
break;
case '4':
strcat(bin, "0100");
break;
case '5':
strcat(bin, "0101");
break;
case '6':
strcat(bin, "0110");
break;
case '7':
strcat(bin, "0111");
break;
case '8':
strcat(bin, "1000");
break;
case '9':
strcat(bin, "1001");
break;
case 'a':
case 'A':
strcat(bin, "1010");
break;
case 'b':
case 'B':
strcat(bin, "1011");
break;
case 'c':
case 'C':
strcat(bin, "1100");
break;
case 'd':
case 'D':
strcat(bin, "1101");
break;
case 'e':
case 'E':
strcat(bin, "1110");
break;
case 'f':
case 'F':
strcat(bin, "1111");
break;
default:
printf("Invalid hexadecimal input.");
}
}
return bin;
}
The hexToBin function returns a pointer to the first element of the global bin array. Everytime!.
That means all pointers in b will be the very same pointer to the very same first element of the bin array.
If you know the maximum length of the strings, I recommend that you make b an array of arrays of char. For example
char b[3][500]; // 3 arrays of 499-character strings (+1 for the null-terminator)
Then instead of hexToBin returning a pointer to a single global array, pass a pointer to the string to be filled as argument to hexToBin:
void hexToBin(char *hex, char *bin);
and call it as
hexToBin(a[i], b[i]);
You only have one bin. What your hexToBin does is appending to that one bin and then returning that bin. In other words, when you call it multiple times, the result is always the same pointer, because you always return bin;.
So if you do this:
b[i] = hexToBin(a[i]);
Then in the end, all elements of b are pointing to bin, that's why you get the same output when you print them. If you do this instead:
b[i] = strdup(hexToBin(a[i]));
Then the result is not the same, because they all don't get bin assigned, but a copy of what bin has been at that time. That's why the results are different. So b[0] points to one copy, then bin is appended to again, but that doesn't change the b[0] copy.
If you use strdup, don't forget to free the memory it allocated:
for(int i = 0; i < 3; i++) {
free(b[i]);
}
[My answer is mistaken. I leave it posted here for reference but the other answers are preferable.]
Your code looks pretty good for beginner's code and I like your style. I especially like this line:
char * b[3];
Unfortunately, for this particular application, you must replace this with a less elegant line like
char b[3][5];
The former line reserves no storage for your output. The latter line reserves five bytes per hex digit. You need storage, somehow.

Why does the string return "#" or mess up my "Z"?

char convertalphas(char s) {
switch (s){
case 'A':
return '0';
break;
case 'B':
return '1';
break;
case 'C':
return '2';
break;
case 'D':
return '3';
break;
case 'E':
return '4';
break;
case 'F':
return '5';
break;
case 'G':
return '6';
break;
case 'H':
return '7';
break;
case 'I':
return '8';
break;
case 'J':
return '9';
break;
case 'K':
return '10';
break;
case 'L':
return '11';
break;
case 'M':
return '12';
break;
case 'N':
return '13';
break;
case 'O':
return '14';
break;
case 'P':
return '15';
break;
case 'Q':
return '16';
break;
case 'R':
return '17';
break;
case 'S':
return '18';
break;
case 'T':
return '19';
break;
case 'U':
return '20';
break;
case 'V':
return '21';
break;
case 'W':
return '22';
break;
case 'X':
return '23';
break;
case 'Y':
return '24';
break;
case 'Z':
return '25';
break;
}
}
int main()
{
char astring[10];
int i = 0;
int flag = 0;
int startedalpha = 0;
//check if there is a digit input or not
int nodigit = 0;
char cell[10];
int col;
scanf( "%s", &astring );
for ( i = 0; i < 10; ++i )
{
if(astring[i] != '\0') {
//check whether letter is capital or small
if (astring[i] >= 65 && astring[i] <= 90)
{
startedalpha = 1;
//printf( "%c\n", astring[i] );
cell[i] = convertalphas(astring[i]);
printf("cell is %s\n", cell);
}
What im trying to do is to concatenate all of my conversions for a later use. when I put "AB" it returns "01#" and when I put "Z" it returns something else than "25". I don't know what is wrong but it is driving me crazy! I want to be able to input "ABZ" and it saves all of my values into the variable cell. For example, "ABZ" "0125"
Thanks!
I'm confused with this forum. Obviously, I posted the question because there is something I don't know and I'm not a guru as many of you! So, why would I get -2? I already posted what I tried. I thought it is about helping not being condescending!
Thanks for those who replied anyway!
Edit --
I converted my switch statement to int but now how can I concatenate the integers in variable cell?
One of things I noticed is that you have a char returning function, and is returning something else than a char, like '10'. It will return an unexpected value. You can, for example, set the return of this function to integer.
So it will look like this:
int convertalphas(char s) {
switch (s){
case 'A':
return 0;
case 'B':
return 1;
case 'C':
return 2;
case 'D':
return 3;
case 'E':
return 4;
return -1;
}
And then, change inside the loop in main function:
sprintf(auxvar, "%d", convertalphas(astring[i]);
for( jj = 0; jj < strlen(auxvar); jj++)
cell[i++] = auxvar[jj];
I hope it can help you somehow!
Good Luck.
According to the C Standard (6.4.4.4 Character constants)
...The value of an integer character constant containing more than one
character (e.g., 'ab'), or containing a character or escape sequence
that does not map to a single-byte execution character, is
implementation-defined.All
All return values of the function starting from '10' to '25' inclusively are imolementation defined and you can get the result that you did not expect to get.
You need to write a function that would be declared like
char * convertalphas( const char *s );
Or
char * convertalphas( char *dest, const char *source );
By the way it will be difficult to make the reverse conversion. For example what does "25" mean? Whether it is "CF" or "Z"?:)
Apart from the values returned by chars 'K' thru 'Z' (as mentioned by others) there are some other errors with the use of cell
Each character returned from your function is written into cell[] and then you print cell as a string. But there is no string terminator. You either need to fill cell[] with zeros first, or write a 0 into the next character
cell[i] = convertalphas(astring[i]);
cell[i+1] = 0;
But the problem with this is that cell[i] is skipped when the char is not a capital letter. You need to maintain a separate index into cell[]
cell[j++] = convertalphas(astring[i]);
cell[j] = 0;
One more problem is cell[] is not long enough for the final string terminator. You need to declare it as
char cell[11];
To summarize, your problem is:
A char function cannot return anything other than a single character. If you try to return something like '12', it just simply doesn't work. You need to rethink your algorithm. Implementing this using ints should be very straightforward.
Is this a homework assignment requiring the use of the switch statement? If not, and if you follow the advice to return int instead of char, a simple s-65 would do the trick, you don't need a 78-line switch.
Since cell is a char array, each element of cell can also only store a single character.
It is not very clear what you are trying to achieve, so I will try to comprehend it in two ways:
3.1. You want to store each character's value separately in cell.
Example: for input "ABZ", you want cell to be {0, 1, 25}.
This is easy. Change cell to an int array, and output them using %d format specifier in your printf.
3.2 You treat cell as a string rather than an array of characters, and you concatenate the string for every character's value.
Example: for input "ABZ", you want cell to be "0125", or in other words, {'0', '1', '2', '5'}. This means that you won't be able to differentiate between "ABZ" and, say, "AMF", as others have pointed out.
If this is what you want to achieve, firstly 10 elements is not enough for cell - each character must be stored separately, and you cannot store "25" as two characters in a single element of cell.
You can assign it with, say, 21 elements (2 max for each alphabet, one extra for the terminating '\0' byte). After each alphabet is converted to its value in int, implement a counter and some conditionals to fill cell one character at a time. Example, if an alphabet's value is stored in val:
char cell[21];
int i=0;
if(val < 10) {
cell[i] = val + '0';
i++;
} else {
cell[i] = val / 10 + '0';
i++;
cell[i] = val % 10 + '0';
i++;
}
I'll leave the implementation of this into a loop as an exercise for you...

Resources