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;
}
Related
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;
}
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.
I'm doing an exercise from KNKings book "C Programming: A modern approach" which involves converting a phone number in alphabetic form, entered by the user, into numeric form. When the program encounters non-alphabetic characters (digits or punctuations, for example), it should leave them unchanged. I may assume that the user only enters upper-case letters.
However, my program seems to produce garbage, to say the least.
#include <stdio.h>
#define MAX_SIZE 50
int main(void)
{
char alphabetic[MAX_SIZE], ch;
int num_elements = 0;
printf("Enter phone number: ");
int i;
for (i = 0; i < MAX_SIZE && ((ch = getchar()) != '\n'); i++){
alphabetic[i] = ch;
num_elements++;
}
for (i = 0; i <= num_elements; i++){
switch (alphabetic[i]){
case 'A': case 'B': case 'C': alphabetic[i] = '2'; break;
case 'D': case 'E': case 'F': alphabetic[i] = '3'; break;
case 'G': case 'H': case 'I': alphabetic[i] = '4'; break;
case 'J': case 'K': case 'L': alphabetic[i] = '5'; break;
case 'M': case 'N': case 'O': alphabetic[i] = '6'; break;
case 'P': case 'R': case 'S': alphabetic[i] = '7'; break;
case 'T': case 'U': case 'V': alphabetic[i] = '8'; break;
case 'W': case 'X': case 'Y': alphabetic[i] = '9'; break;
default: break;
}
}
printf("%s\n", alphabetic);
return 0;
}
In particular, I enter: COLLECT-800.
It outputs something like this: u░#■ ║k ╩
What did I do wrong?
You have the right idea, but there are two things missing in your program:
Most importantly, the null terminator at the end of the string. After your for loop in which you read the number, add the line:
alphabetic[i] = '\0';
If the user enters lowercase letters, they are ignored in the switch statement. To get around this, include <ctype.h> and change the switch quantity from alphabetic[i] to toupper(alphabetic[i]). Calling toupper on an already upper case letter is benign.
You're not putting a null-terminator anywhere so it's undefined behavior when you read the string regardless of whether you modified it afterwards. Put this line:
alphabetic[num_elements] = 0;
After your for (i = 0; i < MAX_SIZE &&... loop.
Personally, I wouldn't do the getchar loop and instead read in the string like this:
scanf("%49s", alphabetic); // reads in a string up to 50 characters
for (i = 0; alphabetic[i]; i++) { ...
I am having an impossible time trying to make this work. It is just a sample run of the code without the full options.
What is needed from the program is for the user to enter there choice, 1-3 or a-c. I am using a string in case the user enters more than just a single character. The switch case then should compare just the first char in the array to the cases. And the do while loop is to make sure it keeps going until they enter the right characters.
#include <stdio.h>
#define SIZE 81
void main(){
char thing[SIZE] = {3};
int rvalue;
do
{
scanf_s("%s", thing);
switch (thing[0])
{
case 'a':
case 1:
printf("first\n");
rvalue = 1;
break;
case 'b':
case 2:
printf("second\n");
rvalue = 2;
break;
case 'c':
case 3:
printf("third\n");
rvalue = 3;
break;
default:
printf("Wrong\n");
rvalue = 4;
break;
}
} while (rvalue == 4);
}
Change
scanf_s("%s", thing);
To
scanf_s("%s", thing,(unsigned int)sizeof(thing)); //Read the comments to know why the cast is required
This done because scanf and scanf_s are different function. scanf_s has an additional argument present to prevent buffer overflows.
Also change these
case 1:
case 2:
case 3:
To
case '1':
case '2':
case '3':
Because the character 1('1') and the rest of them are different from the integer 1. The characters(those enclosed in single quotes) have their values represented in the ASCII table.
As far as it seems, you want to print first when the first character in the thing string is a or 1, and so on.
The problem is that case 1: is not same as case '1':. 1 is an int, '1' is a char, and as you are comparing the first character of the string, you need to change your casestatements a bit.
Code:
#include <stdio.h>
#define SIZE 81
void main(){
char thing[SIZE] = {3};
int rvalue;
do
{
scanf_s("%s", thing,SIZE);
switch (thing[0])
{
case 'a':
case '1':
printf("first\n");
rvalue = 1;
break;
case 'b':
case '2':
printf("second\n");
rvalue = 2;
break;
case 'c':
case '3':
printf("third\n");
rvalue = 3;
break;
default:
printf("Wrong\n");
rvalue = 4;
break;
}
} while (rvalue == 4);
}
I am trying to make a switch statement that takes in a word into an array and then throws each letter through a switch statement and allocates a point to each letter depending on which letter it is and giving a final point value for the word, and I can't seem to get the array part right. Any help would be appreciated!
int main(){
int letter_points = 0;
char word[7];
int word_length = 7;
int i;
printf("Enter a Word\n");
scanf("%s", word);
for(i = 0; i < word_length; i++){
switch(word){
//1 point
case 'A':
case 'E':
case 'I':
case 'L':
case 'N':
case 'O':
case 'R':
case 'S':
case 'T':
case 'U':
letter_points++;
break;
//2 points
case 'D':
case 'G':
letter_points += 2;
break;
//3 points
case 'B':
case 'C':
case 'M':
case 'P':
letter_points += 3;
break;
//4 points
case 'F':
case 'H':
case 'V':
case 'W':
case 'Y':
letter_points += 4;
break;
//5 points
case 'K':
letter_points += 5;
break;
//8 points
case 'J':
case 'X':
letter_points += 8;
break;
//10 points
case 'Q':
case 'Z':
letter_points += 10;
break;
}
}
printf("%d\n", letter_points);
return;
}
It would probably be faster to have a lookup array:
int const letter_score[26] = { 1, 2, 1, 3, ..., 10 };
/* key: A B C D Z */
score += letter_score[c - 'A']; // or "toupper(word[i]) - 'A'"
Caveat: this requires an encoding in which the upper-case letters are arranged contiguously, such as Unicode or ASCII.
Try using this
switch(word[i]){
in the switch statement. As it stands, you are not testing each element in your array even though you are iterating over the range of the array. Having said that I would go for the approach suggested by Kerrek SB in the other answer. This is much neater and more compact.
The variable word is an array, but you want to switch on each character. Thus, you need:
switch(word[i])
In C, you cannot use arrays in switch (and expressions for case). Also, the type passed to switch() and types specified in each case must match. So the most you can do is switch on a character. You almost got it right though, except that you are passing the whole array into switch. Use index to reference a character instead. For example:
switch (word[i]) {
...
}
You have word as an array of size7, you cannot switch on the array, you have to swicth on each character of the array so use:
switch(word[i])