I'm going through some c programming questions and I'm currently stuck on a pointer related question
Q: Write a function that takes the values of a two-card blackjack HAND as input, and returns the point total of the hand. The value
of the cards '2' through '9' is equal to their face value, the cards 'T', 'K', 'Q', 'J' are worth 10 points and the ace ('A') is worth 11 points
unless it comes with another ace, then that second ace is worth 1 point. The program should be able to catch incorrect input.
Examples:
Enter cards: A Q
The score is 21
Enter cards: A A
The score is 12
I've tackled this question before, but this time I'd have to use pointers which I'm still fairly new towards. Getting card values and calculating cards must be done in one function. Here's what i have so far:
#include <stdio.h>
#define HAND 2
struct player_hand
{
char card1;
char card2;
};
void getHandValue(struct player_hand * hnd_ptr, char size, char size2)
{
int first_card;
int second_card;
//get cards from user
scanf("%c %c",&hnd_ptr->card1, &hnd_ptr->card2);
printf("Enter Cards: %c %c", &hnd_ptr->card1, &hnd_ptr->card2);
//check value of first card in hand
if(hnd_ptr->card1<='9' && hnd_ptr->card1>='2')
{
first_card=(int)hnd_ptr->card1 -48;
}
//check for special cards: king, queen, jack, ten
else if(hnd_ptr->card1=='T'||hnd_ptr->card1=='K'||hnd_ptr->card1=='Q'||hnd_ptr->card1=='J')
{
first_card=10;
}
//if first card is Ace
else if(hnd_ptr->card1=='A')
{
first_card=11;
}
else
{
//card not valid
printf("Not a valid card: %c",hnd_ptr->card1);
return;
}
//check value of 2nd card
if(hnd_ptr->card2<='9' && hnd_ptr->card2>='2')
{
second_card=(int)hnd_ptr->card2 -48;
}
//if 2nd card is a special kind
else if(hnd_ptr->card2=='T'||hnd_ptr->card2=='K'||hnd_ptr->card2=='Q'||hnd_ptr->card2=='J')
{
second_card=10;
}
//if 2nd card is Ace
else if(hnd_ptr->card2=='A')
{
if(hnd_ptr->card1=='A')
second_card=1;
else
second_card=11;
}
else
{
//if 2nd card not valid
printf("Not a valid card: %c",hnd_ptr->card2);
return;
}
add cards
printf("\nThe total card value is: %d",first_card+second_card);
}
//call function, test if works
//calling it wrong?
int main(void)
{
struct player_hand hnd [HAND] = { {'A', 'A'}};
getHandValue (hnd, HAND);
return;
}
You have a few bugs.
Incorrect call in main.
The function doesn't need size arguments and if it did they should be int.
Bad return from main.
In the function, the printf is wrong.
Things are much more complicated than they need to be because the struct uses two scalars instead of an array.
I've created two versions of your program. One with bugs annotated. And another that cleans things up.
Here's the annotated version:
#include <stdio.h>
#define HAND 2
struct player_hand {
char card1;
char card2;
};
// NOTE/BUG: use 'int' for size and size2
void
getHandValue(struct player_hand *hnd_ptr, char size, char size2)
{
int first_card;
int second_card;
// get cards from user
scanf("%c %c", &hnd_ptr->card1, &hnd_ptr->card2);
// NOTE/BUG: this would print the _address_ of the values vs. the values
printf("Enter Cards: %c %c", &hnd_ptr->card1, &hnd_ptr->card2);
// NOTE/BUG [sort of]: the code below is cut-n-paste replication because you
// have separate card1 and card2 in the struct -- this "cries out" for an
// array and a loop. Consider the general case where you have 5 cards in the
// hand (e.g. five card charlie). The code would be easier even with an array
// of only two
// check value of first card in hand
if (hnd_ptr->card1 <= '9' && hnd_ptr->card1 >= '2') {
first_card = (int) hnd_ptr->card1 - 48;
}
// check for special cards: king, queen, jack, ten
else if (hnd_ptr->card1 == 'T' || hnd_ptr->card1 == 'K' || hnd_ptr->card1 == 'Q' || hnd_ptr->card1 == 'J') {
first_card = 10;
}
// if first card is Ace
else if (hnd_ptr->card1 == 'A') {
first_card = 11;
}
else {
// card not valid
printf("Not a valid card: %c", hnd_ptr->card1);
return;
}
// check value of 2nd card
if (hnd_ptr->card2 <= '9' && hnd_ptr->card2 >= '2') {
second_card = (int) hnd_ptr->card2 - 48;
}
// if 2nd card is a special kind
else if (hnd_ptr->card2 == 'T' || hnd_ptr->card2 == 'K' || hnd_ptr->card2 == 'Q' || hnd_ptr->card2 == 'J') {
second_card = 10;
}
// if 2nd card is Ace
else if (hnd_ptr->card2 == 'A') {
if (hnd_ptr->card1 == 'A')
second_card = 1;
else
second_card = 11;
}
else {
// if 2nd card not valid
printf("Not a valid card: %c", hnd_ptr->card2);
return;
}
printf("\nThe total card value is: %d", first_card + second_card);
}
//call function, test if works
//calling it wrong?
int
main(void)
{
// NOTE: based on usage, this is only an array because you're not using &hnd
// below
struct player_hand hnd[HAND] = {
{'A', 'A'}
};
// NOTE/BUG: too few arguments to function, but why pass count at all?
getHandValue(hnd, HAND);
// NOTE/BUG: need to return value (e.g. return 0)
return;
}
Here's the cleaned up version:
#include <stdio.h>
#define CARDS_PER_HAND 2
struct player_hand {
char card[CARDS_PER_HAND];
};
void
getHandValue(struct player_hand *hnd_ptr)
{
int idx;
int card;
int sum;
int count[CARDS_PER_HAND];
// get cards from user
printf("Enter Cards:");
fflush(stdout);
for (idx = 0; idx < CARDS_PER_HAND; ++idx)
scanf(" %c", &hnd_ptr->card[idx]);
// print cards
printf("Cards entered:");
for (idx = 0; idx < CARDS_PER_HAND; ++idx)
printf(" %c", hnd_ptr->card[idx]);
printf("\n");
for (idx = 0; idx < CARDS_PER_HAND; ++idx) {
card = hnd_ptr->card[idx];
// simple cards
if (card <= '9' && card >= '2') {
count[idx] = (card - '2') + 2;
continue;
}
switch (card) {
case 'A':
count[idx] = 11;
if ((idx == 1) && (count[0] == 11))
count[idx] = 1;
break;
case 'T':
case 'K':
case 'Q':
case 'J':
count[idx] = 10;
break;
default:
printf("Not a valid card: %c", card);
return;
break;
}
}
sum = 0;
for (idx = 0; idx < CARDS_PER_HAND; ++idx)
sum += count[idx];
printf("The total card value is: %d\n", sum);
}
int
main(void)
{
struct player_hand hnd;
getHandValue(&hnd);
return 0;
}
If, in addition to the other answers, your intent was to pass a 2-hand array, you would need to handle both hands within a loop in your scoring function. For example:
#include <stdio.h>
#define HAND 2
struct player_hand
{
char card1;
char card2;
};
void getHandValue (struct player_hand *hnd_ptr, int size)
{
int first_card;
int second_card;
/* get cards from user */
for (int i = 0; i < size; i++) {
printf ("\nenter cards for hand %d (card1 card2): ", i);
/* you must handle the '\n' that remains after last char */
if (scanf ("%c %c%*c", &hnd_ptr[i].card1, &hnd_ptr[i].card2) != 2) {
fprintf (stderr, "error: invalid entry.\n");
return;
}
printf ("you entered: %c %c\n", hnd_ptr[i].card1, hnd_ptr[i].card2);
}
for (int i = 0; i < size; i++)
{
/* check value of first card in hand */
if(hnd_ptr[i].card1 <= '9' && hnd_ptr[i].card1 >= '2')
{
first_card = (int)hnd_ptr[i].card1 - '0';
}
/* check for special cards: king, queen, jack, ten */
else if (hnd_ptr[i].card1 == 'T' || hnd_ptr[i].card1 == 'K' ||
hnd_ptr[i].card1 == 'Q' || hnd_ptr[i].card1 == 'J')
{
first_card = 10;
}
/* if first card is Ace */
else if (hnd_ptr[i].card1 == 'A')
{
first_card = 11;
}
else
{
/* card not valid */
printf("Not a valid card: %c",hnd_ptr[i].card1);
return;
}
/* check value of 2nd card */
if(hnd_ptr[i].card2 <= '9' && hnd_ptr[i].card2 >= '2')
{
second_card=(int)hnd_ptr[i].card2 - '0';
}
/* if 2nd card is a special kind */
else if (hnd_ptr[i].card2 == 'T' || hnd_ptr[i].card2 == 'K' ||
hnd_ptr[i].card2 == 'Q' || hnd_ptr[i].card2 == 'J')
{
second_card = 10;
}
/* if 2nd card is Ace */
else if (hnd_ptr[i].card2 == 'A')
{
if (hnd_ptr[i].card1 == 'A')
second_card = 1;
else
second_card = 11;
}
else
{
/* if 2nd card not valid */
printf ("Not a valid card: %c", hnd_ptr[i].card2);
return;
}
/* add cards */
printf ("\nThe total cards value (hand %d) is: %d\n",
i, first_card + second_card);
}
}
int main(void)
{
struct player_hand hnd[HAND] = { {'A', 'A'}, {'A', 'A'} };
getHandValue (hnd, HAND);
return 0;
}
Example Use/Output
$ ./bin/cards
enter cards for hand 0 (card1 card2): A A
you entered: A A
enter cards for hand 1 (card1 card2): 8 K
you entered: 8 K
The total cards value (hand 0) is: 12
The total cards value (hand 1) is: 18
If your intent was not to pass an array of struct, then obviously looping would not be necessary. Note: two loops were used. The first to get the cards for both hands, the second to compute the scores for both. (you could do it with one, but it looked as if you intended to have all cards entered before scoring) Look things over and let me know if you have further questions.
You're not passing the address of hnd to the function getHandValue(). To do this you have to pass the address using the & operator getHandValue(&hnd).
You're also not initializing struct player_hand hnd correctly. There's one set of {} too many.
Here's an edited version of your main() code that works, just some minor edits to how your pointer is set up.
// main
int main(void)
{
// minor edits to fix the code here
struct player_hand hnd = {'A', 'A'};
struct player_hand *hndPtr = &hnd;
getHandValue (hndPtr);
return 0;
}
Related
I'm trying to verify that what a user inputs in to one section of a union is actually an integer. I have been trying to use the isdigit function (see below) but I am having no success. All I need to do is make sure the user enters ONLY numbers for the date, but I am having a lot of trouble with it.
My code:
#define STRSIZE 30
#define PROFSIZE 30
#define NBRASSI 2
#define TRUE 1
#define FALSE 0
struct assignment
{
char name[STRSIZE];
char prof[PROFSIZE];
int duedate;
float value;
};
.
.
.
struct assignment populate_structure(struct assignment assi[], int assi_nbr)
{
int count;
int date_check = FALSE;
for (count = 0; count < assi_nbr; count++)
{
flushall();
printf("Enter Assignment #%d name (max %d chars):\n", count + 1,
STRSIZE);
gets(assi[count].name);
while (date_check == FALSE)
{
printf("Enter due date for Assignment #%d (YYYYMMDD):\n",
count + 1);
scanf("%d", &assi[count].duedate);
if (isdigit(assi[count].duedate))
{
date_check = TRUE;
}
else
{
printf("Invalid");
date_check = FALSE;
}
}
printf("Enter %% of final grade for Assignment #%d:\n", count + 1);
scanf("%f", &assi[count].value);
flushall();
printf("Enter Professor's name for Assignment #%d (max %d chars):\n",
count + 1, PROFSIZE);
gets(assi[count].prof);
printf("\n\n");
}
return assi[count];
}
It gives me no errors in Visual Studio, but when I run the program I get an Abort error whenever ANY value is input for assi[].duedate
If I remove if (isdigit(assi[count].duedate)), the program runs fine (so long as they only input an integer for duedate). Any help is greatly appreciated.
As the commenters already noted: isdigit() is for single characters only. Also: the way you use scanf() already assures the result to be a number.
But you should read a string instead, it is easier to test. For example
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
int c;
int position = 0;
int res;
char date[9] = {'\0'};
char input[20] = {'\0'};
puts("try if date is in the format \"YYYYMMDD\"");
res = scanf("%19s",input);
if(res != 1){
fprintf(stderr,"input was a mess, aborting\n");
goto __FAILURE;
}
c = input[position];
while(c != '\0'){
switch(position){
case 0:
if( c == '2' || c == '1' ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 1:
if( c == '9' || c == '0' ){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 2:
if( isdigit(c) ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 3:
if( isdigit(c) ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 4: // month
if( c == '0' || c == '1' ){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 5: // month
if( isdigit(c) ){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 6: // day
if( c == '0' || c == '1' || c == '2' || c == '3'){
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
case 7: // day
if( isdigit(c)){
// check valid digit by looking back here
// (not implemented)
date[position] = (char) c;
} else {
goto __FAILURE;
}
break;
default:
break;
}
c = input[++position];
}
printf("Date was correct and is %s\n",date);
exit(EXIT_SUCCESS);
__FAILURE:
printf("Date was wrong at position %d with character %c or just too short/long\n",position,c);
exit(EXIT_FAILURE);
}
Fill out the rest (check if date is valid and in the correct range). You could also part the date into individual year/month/day sections instead of putting the string into another string and convert them into numbers via atoi ( you can use atoi `because you already made sure to have a valid number) or by converting manually inside the switch without extra variables and functions. Checking ranges arithmetically is simpler than comparing strings/characters.
Here is my offering - any invalid entry calls exit(1) though a better error handler would be preferred. The data is entered as a string, and then extracted and validated.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct {
int year;
int month;
int day;
} mydate_t;
int main(void){
int i;
mydate_t dat = {0};
int dayspermon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char str[12];
printf("Enter a date (YYYYMMDD): ");
fflush(stdout);
if(fgets(str, sizeof str, stdin) == NULL) {
exit(1);
}
for(i=0; i<8; i++) {
if(!isdigit(str[i])) {
exit(1); // also fails when the string is too short
}
}
// extract
for(i=0; i<4; i++) {
dat.year = dat.year * 10 + str[i] - '0';
}
for(i=4; i<6; i++) {
dat.month = dat.month * 10 + str[i] - '0';
}
for(i=6; i<8; i++) {
dat.day = dat.day * 10 + str[i] - '0';
}
// validate
if(dat.year < 2000 || dat.year > 3000) // arbitrary range
exit(1);
if(dat.year % 4 == 0 && (dat.year % 100 != 0 || dat.year % 400 == 0)) {
dayspermon[1]++; // leap year adjustment
}
if(dat.month < 1 || dat.month > 12)
exit(1);
if(dat.day < 1 || dat.day > dayspermon[dat.month - 1])
exit(1);
printf("Date: %04d %02d %02d\n", dat.year, dat.month, dat.day);
}
/*
*
*Program for finding total number of holes in a string.
*For example total number of holes in "ANUBHAV" is 4 and in "GOURAV" is 3
*
*/
#include <stdio.h>
#include<string.h>
// start of main function
int main(void) {
int t,i = 0,hole = 0; // variable declaration
` char str[100];
scanf("%d",&t); // input number of test cases
while(t--)
{
scanf("%s",str); // input string
while(i < strlen(str))
{
if(str[i] == 'B')
{
hole += 2;
}
else if(str[i] == 'A' || str[i] == 'D' || str[i] == 'O' || str[i] == 'P' || str[i] == 'Q' || str[i] == 'R' )
{
hole += 1;
}
i = i + 1;
}
printf("%d",hole); //printing the total number of holes
}
return 0;
}
This code outputs correctly in the first test case(t), But produces wrong output for next test cases. What is the problem in the code?
Please Help!
Thanks in Advance!
You need to initialize hole every time a new string is input. Your code also can be improved a lot, check this
/*
*
*Program for finding total number of holes in a string.
*For example total number of holes in "ANUBHAV" is 4 and in "GOURAV" is 3
*
*/
#include <stdio.h>
#include <string.h>
// start of main function
int main(void)
{
int hole; // variable declaration
int count;
char str[100];
if (scanf("%d", &count) != 1)
return -1; // Input Error
for (int i = 0 ; i < count ; ++i)
{
hole = 0;
if (scanf("%99s", str) != 1)
return -1; // Input Error
for (int j = 0 ; str[j] != '\0' ; ++j)
{
switch (str[j])
{
case 'B':
hole += 2;
break;
case 'A':
case 'D':
case 'O':
case 'P':
case 'Q':
case 'R':
hole += 1;
break;
}
}
printf("Holes in %s -> %d\n", str, hole); //printing the total number of holes
}
return 0;
}
Solution:-
In your code, you should initialize hole inside the loop,
while (t--) {
int hole = 0;
.
.
}
Explanation:-
The count of hole is distinctive for each test case. If it is not initialized at 0 for each test case, the count shown will add up previous count, resulting in an erroneous result.
For example, if test_case_0 had 2 holes, hole is set to 2 then, if test_case_1 had 3 holes, and hole is not reset to 0, the final result will be hole set to 5 for test_case_1, which is causing the error.
Hope that helps.
You should have to make value of hole=0 inside while statement and after printf function.Because your hole value does not change for next test case.
The code is from Absolute beginner's guide to C, and I get this error ./BlackJack.c<41> : warning C4047: '==' : 'int' differes in levels of indirection from 'char [2]' when I try to compile it in Visual Studio. This is the main function of a Blackjack game.
Line <41> is if (ans == "H") {
main()
{
int numCards; /* Equals 52 at the beginneing */
int cards[52], playerPoints[2], dealerPoints[2], total[2];
/* For user Hit/Stand or Yes/No response */
do { initCardsScreen(cards, playerPoints, dealerPoints, total, &numCards);
dealerGetsCard(&numCards, cards, dealerPoints);
printf("\n");
playerGetsCard(&numCards, cards, playerPoints);
playerGetsCard(&numCards, cards, playerPoints);
do {
ans = getAns("Hit or stand (H/S)? ");
if (ans == "H") {
platerGetsCard(&numCards, cards, playerPoints);
}
}
while ( ans != 'S');
totalIt(playerPoints, total, PLAYER);
/* Player's total */
do {
dealerGetsCard(&numCards, cards, dealerPoints);
} while (dealerPoints[ACEHIGH] < 17);
/* 17: Dealer stop */
totalIt(dealerPoints, total, DEALER);
/* Dealer's total */
findWinner(total);
ans = getAns("\nPlay again (Y/N)? ");
} while (ans == 'Y');
return;
}
(Update): Here is the entire code.
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>
#define BELL '\a'
#define DEALER 0
#define PLAYER 1
#define ACELOW 0
#define ACEHIGH 1
int askedForName = 0;
/****************************
This program specific prototype
****************************/
void dispTitle(void);
void initCardsScreen(int cards[52], int playerPoints[2], int dealerPoints[2], int total[2], int * numCards);
int dealCard(int * numCards, int cards[52]);
void dispCard(int cardDrawn, int points[2]);
void totalIt(int points[2], int total[2], int who);
void dealerGetsCard(int *numCards, int cards[52], int dealerPoints[2]);
void playerGetsCard(int *numCards, int cards[52], int playerPoints[2]);
char getAns(char mesg[]);
char ans;
void findWinner(int total[2]);
main()
{
int numCards; /* Equals 52 at the beginneing */
int cards[52], playerPoints[2], dealerPoints[2], total[2]; /* For user Hit/Stand or Yes/No response */
do { initCardsScreen(cards, playerPoints, dealerPoints, total, &numCards);
dealerGetsCard(&numCards, cards, dealerPoints);
printf("\n");
playerGetsCard(&numCards, cards, playerPoints);
playerGetsCard(&numCards, cards, playerPoints);
do {
char ans = getAns("Hit or stand (H/S)? ");
if (ans == "H") {
playerGetsCard(&numCards, cards, playerPoints);
}
}
while ( ans != 'S');
totalIt(playerPoints, total, PLAYER);
/* Player's total */
do {
dealerGetsCard(&numCards, cards, dealerPoints);
} while (dealerPoints[ACEHIGH] < 17);
/* 17: Dealer stop */
totalIt(dealerPoints, total, DEALER);
/* Dealer's total */
findWinner(total);
ans = getAns("\nPlay again (Y/N)? ");
} while (ans == 'Y');
return;
}
void initCardsScreen(int cards[52], int playerPoints[2], int dealerPoints[2], int total[2], int *numCards)
{
int sub, val=1; /* This function's Work variables */
char firstName[15]; /* Holds user's first name */
*numCards = 52; /* Holds running total of number of cards */
for (sub = 0; sub <= 51; sub++) { /* Counts from 0 to 51 */
val = (val == 14) ? 1 : val; /* If val is 14 reset to 1 */
cards[sub] = val;
val++; }
for (sub = 0; sub <= 1; sub++) { /* Counts from 0 to 1 */
playerPoints[sub] = dealerPoints[sub] = total[sub]=0; }
dispTitle();
if (askedForName ==0) { /* Name asked for nly once */
printf("\nWhat is your first name? ");
scanf_s(" %s", firstName);
askedForName = 1; /* Don't ask prompt again */
printf("Ok, %s, get ready for casino action!\n\n", firstName);
getchar(); /* Discards newline. You can safely */
} /* ignore compiler warning here. */
return;
}
/*** This function gets a card for the player and updates the player's points. ***/
void playerGetsCard(int *numCards, int cards[52], int playerPoints[2])
{
int newCard;
newCard = dealCard(numCards, cards);
printf("You draw: ");
dispCard(newCard, playerPoints);
}
/*** This function gets a card for the dealer and updates the dealer's poimts. ***/
void dealerGetsCard(int *numCards, int cards[52], int dealerPoints[2])
{
int newCard;
newCard = dealCard(numCards, cards);
printf("The dealer draws: ");
dispCard(newCard, dealerPoints);
}
/*** This function gets a card from the deck and stores it in either the dealer's or the player's hold of cards ***/
int dealCard(int * numCards, int cards[52])
{
int cardDrawn, subDraw;
time_t t; /* Gets time for a random value */
srand((unsigned int)(time(&t))); /* Seeds random-number generator */
subDraw = (rand() % (*numCards)); /* From 0 to numcards */
cardDrawn = cards[subDraw];
cards[subDraw] = cards[*numCards -1]; /* Puts top card */
(*numCards); /* in place of drawn one */
return cardDrawn;
}
/*** Displays the last drawn card and updates points with it. ***/
void dispCard(int cardDrawn, int points[2])
{
switch (cardDrawn) {
case(11) : printf("%s\n", "Jack");
points[ACELOW] += 10;
points[ACEHIGH] += 10;
break;
case(12) : printf("%s\n", "Queen");
points[ACELOW] += 10;
points[ACEHIGH] += 10;
break;
case(13) : printf("%s\n", "King");
points[ACELOW] += 10;
points[ACEHIGH] += 10;
break;
default : points[ACELOW] += cardDrawn;
if (cardDrawn == 1)
{
printf("%s\n", "Ace");
points[ACEHIGH] += 11;
}
else
{
points[ACEHIGH] += cardDrawn;
printf("%d\n", cardDrawn);
}
} return;
}
/*** Figure the total for player or dealer to see who won. This function takes into account the fact that Ace is either 1 or 11. ***/
void totalIt(int points[2], int total[2], int who)
{
/* The following routine first looks to see if the total points counting Aces as 1 is equal to the total points couning Aces as 11. If so,
or if the total points counting Aces as 11 is more than 21, the program uses the total with Aces as 1 only */
if ((points[ACELOW] == points[ACEHIGH]) || (points[ACEHIGH] > 21)) {
total[who] = points[ACELOW]; /* Keeps all Aces as 1 */
}
else {
total[who] = points[ACEHIGH]; /* Keeps all Aces as 11 */
}
if (who == PLAYER) /* Determines the message printed */ {
printf("You have a total of %d\n\n", total[PLAYER]);
}
else {
printf("The house stands with a total of %d\n\n", total[DEALER]);
}
return;
}
/*** Prints the winning player. ***/
void findWinner(int total[2])
{
if (total[DEALER] == 21) {
printf("The house wins.\n");
return;
}
if ((total[DEALER] > 21) && (total[PLAYER] > 21)) {
printf("%s", "Nobody wins.\n");
return;
}
if ((total[DEALER] >= total[PLAYER]) && (total[DEALER] < 21)) {
printf("The house wins.\n");
return;
}
if ((total[PLAYER] > 21) && (total[DEALER] < 21)) {
printf("The house wins.\n");
return;
}
printf("%s%c", "You win!\n", BELL);
return;
}
/*** Gets the user's uppercase, single-character response. ***/
char getAns(char mesg[])
{
char ans;
printf("%s", mesg); /* Prints the prompt message passed */
ans = getchar();
getchar(); /* Discards newline. You can safely ignore compiler warning here. */
return toupper(ans);
}
/*** Clears everything off the screen. ***/
void dispTitle(void)
{
int i=0;
while (i < 25) { /* Clears screen by printing 25 blank lines to 'push off' stuff that
might be left over on the screen before this program */
printf("\n");
i++;
}
printf("\n\n*Step right up to the Blackjack tables*\n\n");
return;
}
Notice how all of your other comparisons have single quotes?
while (ans == 'Y')
There, you're comparing a single character (which is a number, and thus comparable to another number).
In the code that's failing, on the other hand, you're using double quotes.
ans == "H"
So you're comparing to a string, which is an array of chars. The array is two characters long to accommodate the null terminator.
"H" (in double quotes) is a string, not a character. To get a character constant containing the letter H, you need 'H' (in single quotes.) So, your line should read if( ans == 'H' ).
What will also work is if( ans == "H"[0] ). This will compare ans against the first (zero-th) character of the string "H".
I agree that this is an insanely cryptic message for a simple type mismatch error. Blame it on C and C compilers. (May I suggest that you use some more modern language like C# or Java?)
The compiler reports your ans as an int while you may have declared it as a char. (I do not know how you have declared it, because you seem to have omitted its declaration from the source code that you posted.) If that is happening, it is because the compiler implicitly converts the char to int while trying to compare it with something else.
The compiler also reports your "H" as a char[2], and it might not be immediately obvious why: C uses null-terminated strings, so the literal "H" is represented as a 2-character array, where the first character is 'H' and the second character is the null character. ('\0').
And then the compiler mumbles something about different levels of indirection instead of telling you that the types you are trying to compare are incompatible. That's because in trying to perform the comparison the compiler considers "H" not as an array of characters, but as a pointer to the first character of the array, but that still does not help, because what it ends up with is a pointer to a character, (one level of indirection,) while it needs a character. (Zero levels of indirection.)
This has stumped me for a few days now. I have tried searching but have turned up mostly just definitions for struct...
In an if loop I set 2 struct variables, but neither of them come out correct. guests[x].plusone is stuck at 0 and guests[x].plusonefood is simply empty. If I set them (with the same line) outside of the loop, however, there are no issues. My compiler shows no warnings or errors. What am I missing?
This is my first project with C, so please point out anything else you notice, too.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct guestinfo
{
char name[50];
short int plusone;
char food[50];
char plusonefood[50];
};
char temp[5];
char setfood (int f)
{
char foodtemp[f];
int x;
for (x=0; x < f; x++)
{
printf("Food option %d:\n", (x+1));
fgets(&foodtemp[x],100,stdin);
}
return *foodtemp;
}
int main ()
{
int number_of_rsvp=0;
int number_of_food=0;
printf("Number of food choices:\n");
fgets(temp,5,stdin);
number_of_food = atoi (temp);
while (number_of_food <= 0)
{
printf("Please enter a number greater than 0\n");
fgets(temp,5,stdin);
number_of_food = atoi (temp);
}
char food [50] [number_of_food];
**food = setfood(number_of_food);
printf("Number of RSVPs:\n");
fgets(temp,5,stdin);
number_of_rsvp = atoi (temp);
while (number_of_rsvp <= 0)
{
printf("\nPlease enter a number greater than 0\n");
fgets(temp,5,stdin);
number_of_rsvp = atoi (temp);
};
struct guestinfo guests[number_of_rsvp];
int x;
int f;
for (x=0; x < number_of_rsvp; x++)
{
// add input validation to this section
printf("Guest Number %d:\n\nGuest Name:\n", (x+1));
fgets(guests[x].name,50,stdin);
printf("Food Choice #:\n");
fgets(temp,3,stdin);
f = atoi(temp);
f--;
*guests[x].food = food [50] [f];
printf("Plus One? Y/N\n");
fgets(temp,3,stdin);
}
if (strchr (temp,'Y') != NULL || strchr (temp,'y') != NULL) //This loop
{
guests[x].plusone = 1;
printf("Plus one food choice #:\n");
fgets(temp,3,stdin);
f = atoi(temp);
f--;
*guests[x].plusonefood = food [50] [f];
}
else if (strchr (temp,'N') != NULL || strchr (temp,'n') != NULL)
{
guests[x].plusone = 0;
};
FILE *guestlist = fopen ("guestlist.txt","w");
// debugging
printf("%d\n",guests[0].plusone);
printf("%s\n",guests[0].plusonefood);
for (x=0; x < number_of_rsvp; x++)
{
fprintf(guestlist,"Guest Number %d:\n\nName: %s\nFood Choice: %s\n",(x+1),guests[x].name,guests[x].food);
switch (guests[x].plusone)
{
case 1:
{
fprintf(guestlist,"Plus One: Yes\n\tPlus One Food: %s\n\n",guests[x].plusonefood);
break;
}
case 0:
{
fprintf(guestlist,"Plus One: No\n\n");
break;
}
default:
{
break;
}
}
}
fclose (guestlist);
printf("Printing Guest List...\n");
return 0;
}
The problem is that you are accessing an invalid memory place.
The array has number_of_rsvp elements.
Your for() loop interates over the variable x up to the value number_of_rsvp and exits.
After that, the value of x is equal to number_of_rsvp.
Since the index of the array only can go from 0 to number_of_rsvp - 1, the element guests[x], which is guests[number_of_rsvp], is out-of-bound.
this is both my first time asking a question and also one of my first times writting such a big programm. As you might guess im new at programming.
Alright the source code:
#include <stdio.h>
typedef struct{
int **a;
int size;
}_board;
typedef _board* board;
typedef struct{
int row,col;
}position;
int main () {
int i, j, turn=1, victory = 0, num=0;
_board b;
char P1symbol, P2symbol, mark, boardarray[b.size][b.size];
position p;
printf("WELCOME TO THE GAME OF TIC TAC TOE!\n");
do {
printf("\nwill player one, use X or O as his symbols? select by pressing x or o\n");
scanf(" %c", &P1symbol);
if (P1symbol == 'x' || P1symbol == 'o') {
num = 1;
}
} while ( num == 0);
if (P1symbol == 'x') {
P2symbol = "o";
}
else {
P2symbol = "x";
}
do {
printf("\n now choose the size of the game board, type a numeral and press enter");
scanf("%d", &b.size);
}while (b.size <= 0);
for (i=0; i=b.size; i++){
for (j=0; j=b.size; j++){
boardarray[i][j] = "-";
}
}
do {
do {
boardsketch(boardarray, b.size);
if (turn%2 == 1) {
printf("player 1, please choose a box to input you mark on");
mark = P1symbol;
}else{
printf("player 2, please choose a box to input you mark on");
mark = P2symbol;
}
printf("type the coordinates i,j, which correspond to the row and collumn number");
printf("make sure the numbers are valid, not taken, and between 0 and %d", b.size);
scanf("%d %d", &p.row, &p.col);
}while (p.row > b.size && p.row < 0 && p.col > b.size && p.col <0 && boardarray[p.row][p.row] != "-");
turn++;
boardarray[p.row][p.col] = mark;
} while (wincheck(boardarray, p.row, p.col, b.size) != 1);
return 0;
}
int wincheck(int row, int col, int size, char boardarray[size][size])
{
if (boardarray[row][col] = boardarray[row -1][col -1] = boardarray[row +1][col +1]) {
return 1;
}
if (boardarray[row][col] = boardarray[row -1][col] = boardarray[row +1][col]) {
return 1;
}
if (boardarray[row][col] = boardarray[row][col -1] = boardarray[row][col +1]){
return 1;
}
if (boardarray[row][col] = boardarray[row -1][col +1] = boardarray[row +1][col -1]){
return 1;
}
}
void boardsketch(int size, char boardarray[size][size]) {
int i, j;
for (i=0; i=size; i++) {
for (j=0; j=size; j++) {
if (boardarray[i][j] == '-') {
printf("| ");
} else {
printf("%c |", &boardarray[i][j]);
}
}
}
}
Now the program's purpose is to simulate a game of tic tac toe (with the addition of the user, deciding the size of the game board). My problem is that, altough compilation IS achieved the program does 2 wierd behaviors when reaching a specific line, that line being:
do {
printf("\n now choose the size of the game board, type a numeral and press enter");
scanf("%d", &b.size);
}while (b.size <= 0);
If i input a value that doesnt obey to b.size <= 0, the printf above, repeats indefinately, if i DO put a correct value, the programm doesnt resume. What am i doing wrong? again im new at programming sooooo... go easy on me :D
There are compiler errors in your code. I don't know how you got it to compile and build it the first place.
Compiler errors:
You have:
P2symbol = "o";
Type of "o" is char const*. The type of P2symbol is char. What you need is
P2symbol = `o`;
Few lines after that, you have:
P2symbol = "x";
That needs to be changed to:
P2symbol = `x`;
Few lines after that, you have:
boardarray[i][j] = "-";
It suffers from the same compiler error. You need to change it to:
boardarray[i][j] = `-`;
Your declaration and definition of boardsketch does not match with the way you are calling it. Your call is:
boardsketch(boardarray, b.size);
You have defined it as:
void boardsketch(int size, char boardarray[size][size]) {
....
}
You need to change either the call or the function definition so that they match. Also, you should declare the function before it is used. Add
void boardsketch(int size, char boardarray[size][size]);
before the start of main.
The definition and call of wincheck suffers from the same error. It also should have a declaration before it's usage.
A few lines after that call to boardarray, you have the line:
}while (p.row > b.size && p.row < 0 && p.col > b.size && p.col <0 && boardarray[p.row][p.row] != "-");
The last part of that statement suffers from the char and char const* mismatch. You need to change it to:
}while (p.row > b.size && p.row < 0 && p.col > b.size && p.col <0 && boardarray[p.row][p.row] != '-');
Run Time Errors:
You have:
_board b;
char P1symbol, P2symbol, mark, boardarray[b.size][b.size];
The problem with that is b.size is not initialized. It could be anything. Using it to declare broadarray is problem. Imagine the chaos that will ensue if the b.size were to be initialized to a negative number. For sane and predictable behavior, you should initialize b properly before using its data.
A few lines below, you are asking for size to be input by the user.
do {
printf("\n now choose the size of the game board, type a numeral and press enter");
scanf("%d", &b.size);
}while (b.size <= 0);
There is a logic error here. You are asking for the size of the board after you have already created boardarray. What you could do is gather the initial input and use them to call another function where the core of the game play happens.
/* Function that contains the core part of playing the game */
void playgame(char P1symbol, char P2symbol, int size)
{
int i, j, turn=1, victory = 0;
char mark, boardarray[size][size];
position p;
for (i=0; i=size; i++){
for (j=0; j=size; j++){
boardarray[i][j] = '-';
}
}
do {
do {
boardsketch(size, boardarray);
if (turn%2 == 1) {
printf("player 1, please choose a box to input you mark on");
mark = P1symbol;
}else{
printf("player 2, please choose a box to input you mark on");
mark = P2symbol;
}
printf("type the coordinates i,j, which correspond to the row and collumn number");
printf("make sure the numbers are valid, not taken, and between 0 and %d", size);
scanf("%d %d", &p.row, &p.col);
}while (p.row > size && p.row < 0 && p.col > size && p.col <0 && boardarray[p.row][p.row] != '-');
turn++;
boardarray[p.row][p.col] = mark;
} while (wincheck(p.row, p.col, size, boardarray) != 1);
}
Now, main can be simplified to:
int main () {
char P1symbol;
char P2symbol;
int size;
int num = 0;
printf("WELCOME TO THE GAME OF TIC TAC TOE!\n");
do {
printf("\nwill player one, use X or O as his symbols? select by pressing x or o\n");
scanf(" %c", &P1symbol);
if (P1symbol == 'x' || P1symbol == 'o') {
num = 1;
}
} while ( num == 0);
if (P1symbol == 'x') {
P2symbol = 'o';
}
else {
P2symbol = 'x';
}
do {
printf("\n now choose the size of the game board, type a numeral and press enter");
scanf("%d", &size);
}while (size <= 0);
playgame(P1symbol, P2symbol, size);
return 0;
}
Ah, the problem is your for loop after the do while. You are assigning your counters instead of evaluating the limits. Asigning them will result to true every time. Try this instead:
for (i=0; i<b.size; i++){
for (j=0; j<b.size; j++){
boardarray[i][j] = "-";
}
}
Also, do not create an array with undefine value b.size...