Reputation: 35
I'm new in C and I couldnt find the answer to my question in the forum.
The point is, I need to get a value of deck cards from the user. So it can spread from 2 to 10 and also be 'J', 'Q', 'K' or 'A'. That means it can be a integer or a character.
I'm trying to put it in an integer variable called "_val1". This work for any number from 0 to 10. I expected that if I typed a letter, _val1 would get the ASCII value of that character (wich I could use later for my pourposes). But instead _val1 geta value '0' and the letter is automatically passed to my next variable call (wich is _naipe1).
How can I solve that?
That means, how cam I use scanf to get either a integer value or the ASCII value of a character?
short int _val1, _val2;
char _naipe1, _naipe2;
printf("Qual a 1ª carta?\n Valor:");
scanf(" %hd", &_val1);
printf("Valor 1 = %hd \n", _val1 );
printf(" Naipe:");
scanf(" %c", &_naipe1);
Upvotes: 1
Views: 13290
Reputation: 23218
First, there are 52 cards to a typical poker deck, These are split into 4 suits: hearts, diamonds, spades and clubs. This kind of suggests that user input will be something like: 10s, Ad, 3c, etc (meaning 10 of spades, Ace of diamonds and 3 of clubs) So, not only must you determine the value of the individual card, you also must determine the suit.
This will not solve all of those requirements, but it will at least answer your most direct question, how to read an int or a char using scanf()
.
This will demonstrate that:
#include <stdio.h>
int main(int argc, char** argv)
{
int aNumber;
char aChar;
printf("\nEnter a number:");
scanf("%d", &aNumber);
printf("\nEnter a character:");
scanf("%c", &aChar);
printf("\nThe number entered is %d\n", aNumber);
printf("\nThe character entered is %c\n", aChar);
return 0;
}
You can also simply have all the values in a string such as
char cards[]={"Ad Js 10c 2c Qh"};
Then parse it using strtok()
, then test each token for its ascii content, using functions like isdigit()
or isalpha()
Note: you will have to map each card to a value to keep them straight, something like this abbreviated enum may work:
enum {
AD = 1, //start enum values at 1 for the diamonds suit
2D,
3D,
...//fill in rest of cards here
JC,
QC,
KC, // last card == 52, with the clubs suit
};
Upvotes: 1
Reputation: 123468
I'm trying to put it in an integer variable called "_val1". This work for any number from 0 to 10. I expected that if I typed a letter, _val1 would get the ASCII value of that character (wich I could use later for my pourposes). But instead _val1 geta value '0' and the letter is automatically passed to my next variable call (wich is _naipe1)
The problem is that the %d
conversion specifier only recognizes strings of decimal digits (with an optional leading +
or -
) and will stop reading at the first non-digit character; if you type in something other than a digit, then the input operation will fail and that character will be left in the input stream.
Your best bet is to read your input as text, then convert it to a numerical value manually, something like the following:
#include <ctype.h>
#include <stdlib.h>
/**
* Reads a card's face value (2-10,J,Q,K,A) from standard input
* Returns 0 on error
*/
short get_card_value( void )
{
char buf[4]; // large enough to hold a 2-digit string plus newline plus 0 terminator
short val = 0;
if ( fgets( buf, sizeof buf, stdin ) != NULL )
{
char *chk;
short tmp = (short) strtol( buf, &chk, 0 );
if ( isspace( *chk ) || *chk == 0 )
{
if ( tmp >= 2 && tmp <= 10 )
val = tmp;
}
else
{
switch( tolower( *chk ) )
{
case 'j': val = 11; break;
case 'q': val = 12; break;
case 'k': val = 13; break;
case 'a': val = 11; break;
default: break;
}
}
}
// else read error
return val;
}
You'd call this as
val1 = get_card_value();
if ( val1 == 0 )
// error on input
This code doesn't do any length checking on input, so if you enter a card value of 1234567890, that won't be handled gracefully.
Don't use leading underscores in your variable names; names with leading underscores are reserved for the implementation.
Upvotes: 0
Reputation: 153508
To read in "A", "2", "3", ... "10", "J",... "K", use fgetc()
and strchr()
.
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
short GetCardRank(void) {
static const char rank[] = "A234567891JQK";
short val = -1;
int ch = fgetc(stdin);
while (isspace(ch)) ch = fgetc(stdin); // Skip leading white-space
char *p = strchr(rank, toupper(ch)); // Use toupper() to make case insensitive
if (ch != EOF && p != NULL && *p != '\0') {
short val = (short) (p - rank + 1);
if (val != 10) return val;
ch = fgetc(stdin);
if (ch == '0') return val;
val = 1; // Allow a lone '1' to act like an 'A'
}
ungetc(ch, stdin); // Put back unused char for next IO function
return val;
}
Upvotes: 0
Reputation: 430
The reason your output from _val1 is 0 when entering a letter lies in the fact that you've declared _val1 as an short int. You should be using a char. Then you can assign and compare their ascii values.
char card;
int value;
scanf("%c", card);
if(card < 58 && card > 49)
value = card - 48;
else {
switch(card) {
case 'a': value = 1;
case '0': value = 10;
case 'j': value = 11;
case 'q': value = 12;
case 'k': value = 13;
default: printf("Must enter 0-9 (0 for 10 card), or a, j, q, k\n");
}
}
Upvotes: 0
Reputation: 24812
well, if I were you I'd try to simplify the problem:
'2'
to '9'
and 'J','Q','K','A'
; there you can simply use a scanf("%c")
or even better a getchar()
operation.then either you keep using the ASCII representation of your cards throughout your algorithm, or you can translate it using a mapping function such as:
int map(char card) {
switch (card) {
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return card-'0';
case 'A':
return 1;
case 'J':
return 10;
case 'Q':
return 11;
case 'K':
return 12;
}
}
Upvotes: 1