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?
Related
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++) { ...
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.
I'm working on an encryption program for a class in C. I use modulo 27 math to perform the encryption. I add each encrypted character to an array but I've noticed that unprinted characters are also being added to my string at the end. I realized this when I checked the word count of the encrypted text and it contained more characters than the original text that was encrypted. Can anyone explain why this is happening? This is taking into account the newline at the end of the texts.
Plaintext = THE RED GOOSE FLIES AT MIDNIGHT STOP - wc is 37
Ciphertext = ACBVKWNOGMMMPQHNI XL QBJXDPNVIQVSNZN - wc is 40
//Go through each character of the plaintext
for (i = 0; i < size; i++)
{
//Convert the characters to an integer
PlainNums[i] = charInt(plaintext[i]);
KeyNums[i] = charInt(key[i]);
//Add the int from plain text and the key together
CipherNums[i] = PlainNums[i] + KeyNums[i];
if (CipherNums[i] > 27) //Wrap around if the number exceeds 27
{
CipherNums[i] -= 27;
}
CipherNums[i] = CipherNums[i] % 27; //Use modulo 27 math to generate a new integer
cipherText[i] = IntChar(CipherNums[i]);
}
int charInt(char c)
{
switch (c)
{
case 'A': return 0;
case 'B': return 1;
case 'C': return 2;
case 'D': return 3;
case 'E': return 4;
case 'F': return 5;
case 'G': return 6;
case 'H': return 7;
case 'I': return 8;
case 'J': return 9;
case 'K': return 10;
case 'L': return 11;
case 'M': return 12;
case 'N': return 13;
case 'O': return 14;
case 'P': return 15;
case 'Q': return 16;
case 'R': return 17;
case 'S': return 18;
case 'T': return 19;
case 'U': return 20;
case 'V': return 21;
case 'W': return 22;
case 'X': return 23;
case 'Y': return 24;
case 'Z': return 25;
case ' ': return 26;
default: return -1;
}
}
char IntChar(int n)
{
switch(n)
{
case 0: return 'A';
case 1: return 'B';
case 2: return 'C';
case 3: return 'D';
case 4: return 'E';
case 5: return 'F';
case 6: return 'G';
case 7: return 'H';
case 8: return 'I';
case 9: return 'J';
case 10: return 'K';
case 11: return 'L';
case 12: return 'M';
case 13: return 'N';
case 14: return 'O';
case 15: return 'P';
case 16: return 'Q';
case 17: return 'R';
case 18: return 'S';
case 19: return 'T';
case 20: return 'U';
case 21: return 'V';
case 22: return 'W';
case 23: return 'X';
case 24: return 'Y';
case 25: return 'Z';
case 26: return ' ';
default: return '!'; //error
}
}
Try adding cipherText[size] = '\0'; at the end of the loop to make sure the encoded string only contain the encoded data.
Initialize the cipherText before for loop using memset in your code like the following way.
memset(cipherText,0,sizeof(cipherText));
for (i = 0; i < size; i++)
{
//Convert the characters to an integer
PlainNums[i] = charInt(plaintext[i]);
//....
// rest of the code
You must need to include<string.h.
And it works.
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;
}
}
}
}
switch(ch)
{
//input a number
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[g.y][g.x] = ch - '0';
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
// delete an input from the board
case '0':
case KEY_BACKSPACE:
case KEY_DC:
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[y][x] = 0;
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
}
Problem: Case '1' through case '9' worked fine. Then I added case '0', case KEY_BACKSPACE and case KEY_DC. Although it compiles, none of the cases now work, including cases '1' - '9'. What am I missing?
All of your cases are falling through. I assume that you should have a break; before case 0:.
You are missing a break;. In C, switch has fall-through semantics. Once a case is met, all subsequent cases are exceuted unless a break; stops execution.