unexpected output from switch statement in c program [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm getting output of a - 0000520 when I input a while i should get 0001010 as per the code I've assigned. Also the default runs every time (tested using a printf statement) for unexplained reason. My code is here:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int splitWord(char* word, int count);
int sunCode(char letter);
int main()
{
char inputString[100];
char splitStrings[10][10];
int i, j, count;
printf("Enter the message.\n");
fgets(inputString, 100, stdin);
j = count = 0;
for (i = 0; i <= (strlen(inputString)); i++) {
if (inputString[i] == ' ' || inputString[i] == '\0') {
splitStrings[count][j] = '\0';
count++;
j = 0;
}
else {
splitStrings[count][j] = inputString[i];
j++;
}
}
printf("\nOriginal String is: %s\n", inputString);
for (i = 0; i < count; i++) {
/*for(j=0;j<=strlen(splitStrings[i]);j++){
printf("%s",splitStrings[i][j]);
}*/
splitWord(splitStrings[i], count);
}
return 0;
}
int splitWord(char* word, int count)
{
int i;
int strLength = strlen(word);
for (i = 0; i <= strLength; i++) {
sunCode(word[i]);
// printf("%c\n",word[i]);
}
return 0;
}
int sunCode(char letter)
{
char letr = tolower(letter);
int code = 0;
switch (letr) {
case '0':
code = 0000000;
break;
case '1':
code = 0000001;
break;
case '2':
code = 0000010;
break;
case '3':
code = 0000011;
break;
case '4':
code = 0000100;
break;
case '5':
code = 0000101;
break;
case '6':
code = 0000110;
break;
case '7':
code = 0000111;
break;
case '8':
code = 0001000;
break;
case '9':
code = 0001001;
break;
case 'a':
code = 0001010;
break;
case 'b':
code = 0001011;
break;
case 'c':
code = 0001100;
break;
case 'd':
code = 0001101;
break;
case 'e':
code = 0001110;
break;
case 'f':
code = 0001111;
break;
case 'g':
code = 0010000;
break;
case 'h':
code = 0010001;
break;
case 'i':
code = 0010010;
break;
case 'j':
code = 0010011;
break;
case 'k':
code = 0010100;
break;
case 'l':
code = 0010101;
break;
case 'm':
code = 0010110;
break;
case 'n':
code = 0010111;
break;
case 'o':
code = 0011000;
break;
case 'p':
code = 0011001;
break;
case 'q':
code = 0011010;
break;
case 'r':
code = 0011011;
break;
case 's':
code = 0011100;
break;
case 't':
code = 0011101;
break;
case 'u':
code = 0011110;
break;
case 'v':
code = 0011111;
break;
case 'w':
code = -010000;
break;
case 'x':
code = 010001;
break;
case 'y':
code = 010010;
break;
case 'z':
code = 010011;
break;
case ' ':
code = 45;
printf("\nis space\n");
break;
default:
break;
}
printf("%c - %07d\n", letr, code);
}
I tried to see if it's giving ASCII values (it isn't)
the letter is being passed properly in the sunCode function (it is)
I do not understand why it is behaving like this, verified the syntax and conditions of switch too.
I am using gcc 7.3.0 on Ubuntu.

Leading zeros indicate that the number is expressed in octal, or base 8; thus, 010 = 8.
https://stackoverflow.com/a/1661378/10479742
0001010 in octal is 520 in decimal, and that's why you get that result. Either remove leading zeros, or change code to string.

Related

switch/case not recognizing certain char inputs

I am creating a program for an online coding course which takes a poker hand and calculates the odds of the hand winning. I am currently in the early stages, writing the functions necessary to advance to the next part of the assignment. I have isolated my issues to one function, card_from_letters.
I created my-test-main.c to test card_from_letters. It creates two chars, representing the suit and value of a poker card. It then creates the struct testCard2.
A card_t struct has two components: an unsigned int for value, and an enumerated type for suit between SPADES and CLUBS. I cannot change the struct card_t.
int main(void) {
char sui = 'c';
char val = 'Q';
card_t testCard2 = card_from_letters(val, sui);
printf("last test! My card %c%c is value %d, and suit %d!\n", val, sui, testCard2.value, testCard2.suit);
}
This is my function card_from_letters:
card_t card_from_letters(char value_let, char suit_let) {
card_t temp;
assert(suit_let == 'd' ||'h' || 'c' || 's');
assert((value_let >= '2' && value_let <= '9') || (value_let = '0' || 'K' || 'Q' || 'J' || 'A'));
switch (value_let) {
case '2': temp.value = 2; break;
case '3': temp.value = 3; break;
case '4': temp.value = 4; break;
case '5': temp.value = 5; break;
case '6': temp.value = 6; break;
case '7': temp.value = 7; break;
case '8': temp.value = 8; break;
case '9': temp.value = 9; break;
case '0': temp.value = 10; break;
case 'K': temp.value = 13; break;
case 'Q': temp.value = 12; break;
case 'J': temp.value = 11; break;
case 'A': temp.value = 14; break;
}
switch (suit_let) {
case 's': temp.suit = SPADES; break;
case 'h': temp.suit = HEARTS; break;
case 'd': temp.suit = DIAMONDS; break;
case 'c': temp.suit = CLUBS; break;
}
return temp;
}
When val is set between '2' and '9', I am able to run card_from_letters with no problem. When I run my-test-main.c as it is here through gdb, the execution arrow makes it to switch (value_let), but then skips all cases and enters switch (suit_let), where it returns the correct suit. What am I missing here? How come card_from_letters works for chars 2 to 9, but not 0 to A?

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;
}

Convert phone number from alphabetic to numeric form

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++) { ...

Csh script call C program,arguments issue

This the line from the csh script
./model2grd $model -D$nx/$ny/$nz -O$x0/$y0 -I$dx/$dy -L$layer -C$coverage -Avel.dat -Gvel.grd
This is part of the model2grd.c
for (i = 2; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
case 'C':
cov = &argv[i][2];
lcov = TRUE;
break;
case 'A':
xyzfile = &argv[i][2];
lxyz = TRUE;
break;
case 'D':
sscanf(&argv[i][2],"%d/%d/%d",&nx,&ny,&nz);
break;
case 'I':
sscanf(&argv[i][2], "%lf/%lf", &dx, &dy);
break;
case 'O':
sscanf(&argv[i][2], "%lf/%lf", &xmin, &ymin);
break;
case 'L':
layer = atoi(&argv[i][2]);
break;
case 'N':
nan = (float)atof(&argv[i][2]);
break;
case 'Z':
cvalue = (float)atof(&argv[i][2]);
break;
case 'V':
verbose = TRUE;
break;
default:
break;
}
}
}
Does this mean that it takes with D(nx,ny,nz),with O(xmin and ymin),with L layer and with C coverage?Are Avel.dat and Gvel.grd input files or not?
Avel.dat and Gvel.grd are not input files. Look at the argument parsing again.
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
Consider that with this argument:
-Gvel.grd
In plain English, the switch examines the second character of each argument. In this case -Gvel.grd is the argument, so it looks at the G. Passing that test, the case statement then derives the address of the character that comes immediately after the G within the character string. In other words, the v.
Therefore, the file name is actually vel.grd. You should be able to apply this same logic to the rest of the arguments that follow the same pattern.

Nested switch leads to an infinite loop

In the following program, I need to change the initial and final characters to their respective characters as mentioned below in case but this is giving me an infinite loop. What should I do to fix it?
int main(void)
{
char state ='t';
char word[20]="aaabbccaaaaccbbb";
int initiallength = strlen(word)-1; strcat(word,"a");
while(strlen(word)-1 >initiallength)
{
switch(state)
{
case 't':
switch(word[strlen(word)-1])
{
case 'a':
word[strlen(word)-1]='b'; break;
case 'b':
word[strlen(word)-1]='c'; break;
case 'c':
word[strlen(word)-1]='d'; break;
case 'd':
word[strlen(word)-1]='\0'; break;
}
switch(word[0])
{
case 'a':
word[0]='b'; break;
case 'b':
word[0]='c'; break;
case 'c':
word[0]='d'; break;
case 'd':
word[0]='\0'; break;
}
}
}
}
If I understand correctly what you want to do is swap the first and last characters in the given string. If that's the case first your code is way too complicated and second the reason you're getting an infinite loop is because the condition strlen(word)-1 >initiallength is always true.
Test if word is empty
int main(void){
char state ='t';
char word[20]="aaabbccaaaaccbbb";
int initiallength = strlen(word)-1;
strcat(word,"a");
while(strlen(word)-1 >initiallength && strlen(word) >= 0){
printf("%d %d\n", strlen(word)-1, initiallength);
printf("%d len %s\n", strlen(word), word);
switch(state){
case 't':
switch(word[strlen(word)-1]){
case 'a':
case 'b':
case 'c':
word[strlen(word)-1]++;
break;
case 'd':
word[strlen(word)-1] = '\0';
break;
}
switch(word[0]){
case 'a':
case 'b':
case 'c':
word[0]++;
break;
case 'd':
word[0] = '\0';
break;
}
}
}
}

Resources