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.)
Related
I am making a sorting program for a final assignment. It takes the account number, last name, and balance of the account and sorts it in ascending order based on the account number. The issue I am having with my program is that once it gets to the for loop to output the information, it completely skips it. I believe it might have to do with my bubble sort function, but I am not sure how to fix it. We haven't been taught quick sort, so I am not using it. I am receiving an error: incompatible type for argument 1 of `sort', but I cannot change the array to type struct without it causing more issues. Here is my code:
#include <stdio.h>
/* Define structure */
struct account
{
int number;
char full_name[30];
float balance;
};
/* Function prototype */
void sort (int[], int);
/* Begin main function */
int main()
{
/* Declare variables */
struct account person[5];
int x=0, i=0, count=0;
printf("Enter account number, last name, and balance.\n");
printf("Enter -999 to end input:\n\n");
/* Create loop for user information */
while(1)
{
scanf("%i", &person[x].number);
if(person[x].number == -999) /*Break when -999 is input */
{
count = x;
break;
}
if(person[x].number < 1 || person[x].number >1000)
{
printf("***Invalid account number. Please enter 1 - 1000 or -999 to exit***\n");
x--;
continue;
}
scanf("%s", person[x].full_name);
scanf("%f", &person[x].balance);
if(person[x].balance < 0)
{
printf("*** Invalid balance amount. Please enter a positive value. ***\n");
x--;
continue;
}
}/* End of while loop */
/* Call to sort function to sort information */
sort(person[x].number, count);
/* Display the information in ascending order */
printf("ACCOUNT\tLAST NAME\tBALANCE\n");
/* Create for loop to output the sorted information */
for(x=0; x < count; x++)
{
printf("%d\t%s\t%f\n",person[x].number,person[x].full_name,person[x].balance);
} /* End of for loop */
}/* End of main */
/* Start sort function */
void sort(int p[], int count)
{
/* Declare variables.*/
char changed = 'T'; /* a "flag" to indicate if a swap was made.*/
int x, temp;
while (changed == 'T')
{
changed = 'F';
/* Create for loop for swaping information */
for (x = 0; x < count-1; x++)
{
if ( p[x] > p[x + 1])
{
/* Swap needs to be made.*/
temp = p[x];
p[x] = p[x+1];
p[x+1] = temp;
/* Set flag indicating that a swap was made. This ensures that */
/* processing will continue, until nothing needs to be swapped. */
changed = 'T';
}
} /* end for loop */
} /* end while loop*/
} /* end function sort */
Here is my output:
Enter account number, last name, and balance.
Enter -999 to end input:
10 Happy 55.00
15 Day 60.00
35 Man 75.00
-999
ACCOUNT LAST NAME BALANCE
Press any key to continue . . .
I appreciate your assistance and the time you are taking to help!
first as mentioned in comments add x++ at the end of your while-loop to scan data.
also you should know that by sending one member of struct (number) to your sort function , and sorting it , other members won't be sorted (only another number will be replaced with theirs).
also note here sort(person[x].number, count); you are sending one element of member number from struct to function . while in declaration of function ,you said you will send an array of integer to it.
this should be sort(person, count); and in function deceleration you should
use sort(struct account p[],int count); also you have to change function by using p[x].number.
also note that to add x++ at the end of your while-loop , you have to remove those continue , otherwise when you do x-- you won't reach x++.
I wrote another sort function which I think is more logical.
struct account
{
int number;
char full_name[30];
float balance;
};
void sort(struct account p[], int count);
int main()
{
struct account person[5];
int x = 0, i = 0, count = 0;
printf("Enter account number, last name, and balance.\n");
printf("Enter -999 to end input:\n\n");
while (1)
{
scanf("%i", &person[x].number);
if (person[x].number == -999)
{
count = x;
break;
}
if (person[x].number < 1 || person[x].number >1000)
{
printf("***Invalid account number. Please enter 1 - 1000 or -999 to exit***\n");
x--;
//remove continue
}
scanf("%s", person[x].full_name);
scanf("%f", &person[x].balance);
if (person[x].balance < 0)
{
printf("*** Invalid balance amount. Please enter a positive value. ***\n");
x--;
//remove continue
}
x++;//add x++
}
sort(person, count);//new function sort
printf("ACCOUNT\tLAST NAME\tBALANCE\n");
for (x = 0; x < count; x++)
{
printf("%d\t%s\t%f\n", person[x].number, person[x].full_name, person[x].balance);
}
}
void sort(struct account p[], int count)
{
char changed = 'T';
int x, temp;
float btemp;
char ntemp[30];// btemp for balance and ntemp for full_name
while (changed == 'T')
{
changed = 'F';
for (x = 0; x < count - 1; x++)
{
if (p[x].number > p[x + 1].number)
{
temp = p[x].number;
p[x].number = p[x + 1].number;
p[x + 1].number = temp;
btemp = p[x].balance;
p[x].balance = p[x + 1].balance;
p[x + 1].balance = btemp;
strcpy(ntemp , p[x].full_name);
strcpy(p[x].full_name , p[x + 1].full_name);
strcpy(p[x + 1].full_name , ntemp);
changed = 'T';
}
}
}
}
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;
}
I am new to programming so this is difficult for me. I need the program to end if the user's first input is -999, if not then they go on to input the account_num, last_name, and balance. But if the user enters -999 after the first input then it ends their input and displays the results. I cannot figure out how to get this whole -999 part to work while making my client[x].account_num be sorted in ascending order.. My code is below.
#include <stdio.h>
void bubble_sort(int[], int);
struct information
{
int account_num;
char last_name[30];
float balance;
};
int main()
{
/* declare variables */
struct information client[5];
int i, x, temp;
char c;
/* Prompt user */
printf ("Enter account number, last name, and balance.\n");
printf ("Enter -999 to end input:\n\n");
/* prompt user to enter number of people */
x = 0;
while (client[x].account_num != -999)
{
int tmp;
scanf ("%i", &tmp);
/* if types -999 as their first input program ends */
if (tmp == -999)
{
break;
}
else if (tmp < 1 || tmp > 1000)
{
printf ("*** Invalid account number. Please enter 1 - 1000 or -999 to exit ***\n");
}
else
{
client[x].account_num = tmp;
x ++;
}
bubble_sort(client[x].account_num, i);
scanf("%s", client[x].last_name);
while ( (c = getchar() != '\n') && c != EOF); /* clear input buffer. */
scanf("%.2f", &client[x].balance);
}
for (x = 0; x < 5; x++)
printf("%i\n", &client[x].account_num);
return 0;
}
void bubble_sort(int list[], int i)
{
int e, d, t;
for (e = 0; e < (i - 1); e++)
{
for (d = 0; d < i - e - 1; d++)
{
if (list[d] > list[d + 1])
{
/* swapping */
t = list[d];
list[d] = list[d + 1];
list[d + 1] = t;
}/* end for*/
}/*end for*/
}/* end for */
}/* end function */
There are several issues here. First, you don't want to index account_num and balance in the struct, unless you want to have several account numbers and balances per account holder. I also suggest replacing the for with a while loop so you don't have to fiddle with the loop counter x in case the user enters an invalid account number. Finally, for the sake of clarity I introduced a temporary variable tmpfor input and performed all tests on it, assigning the content to the account structure only if all validity tests were passed. tmpis only needed inside the whileloop which is why I declared it there, instead of making it part of the declarations in main().
#include <stdio.h>
#define MAX_CLIENTS 5
#define MAX_ACCOUNTS 1000
struct information
{
int account_num;
char last_name[30];
float balance;
};
int main()
{
/* declare variables */
struct information client[MAX_CLIENTS];
int i, x, people;
char c;
/* Prompt user */
printf ("Enter account number, last name, and balance.\n");
printf ("Enter -999 to end input:\n\n");
/* prompt user to enter number of people */
x = 0;
while (x < MAX_CLIENTS)
{
int tmp;
scanf ("%i", &tmp);
/* if types -999 as their first input program ends */
if (tmp == -999)
{
break;
}
else if (tmp < 1 || tmp > MAX_ACCOUNTS)
{
printf ("*** Invalid account number. Please enter 1 - %d or -999 to exit ***\n", MAX_ACCOUNTS);
}
else
{
client[x].account_num = tmp;
x ++;
}
}
return 0;
}
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.
I've been working on a hangman game for a class course and I'm almost done. However, I've stumbled upon a problem that I can't seem to fix.
First, the computer choose a random word from a text file, takes the lenght of that word and with that length creates a masked copy of the original word. Then the game start. The player types in letters and if the word is completed before he/she fails six times, he wins. Otherwise, he/she loose. I think the problem with my code is when I create my mask of the word chosen by the computer, but I'm not sure.
If I run the program it looks something like this:
Chosen word: strand (first control of word chosen by computer)
Chosen word: strand (second control to see if the same word is copied from the function to the string in the main)
Chosen word: monster (this is printed by the free() function. for some reason it's one word higher)
Chosen word: strand (third control is done before the lenght of the word is copied, in order to see if it's the right word being copied, which it is)
Wordlenght: 6 (control to see if the lenght matches the word, which it does)
Mask: _ _ _ _ _ _ N (ignore the spaces between the underscores, they are only there to make it easier to see. this is where i think the problem is, because of the extra character added in the end, the "N" in this case. the number of underscores match the number of letters which is good)
Mask: _ _ _ _ _ _ N (printed by the second free() function)
Then the actual game starts. Everything else works fine (if the player aborts or looses and if the player wants or doesn't want to play again). I checked if the actual strcmp() in the int resultat (char* word, char* mask, int count) function worked, and it did. So the fault has be with the strings being compared. I think it's when I get the lenght of the chosen word with strlen(). When I get the length, I subtract with one because otherwise I would get a lenght which is too long(for example, paper would give a lenght of 6, but when I subtract with one I get 5).
If someone could help me or maybe give me some hints I would be very grateful!
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<time.h>
#define MAX_WORD_LEN 20
char* datorns_val();
int ordlengd(char* word);
char* datorns_val_mask(char* word, int len);
int spel(char* word, char* mask, int len, int count, int result);
int resultat (char* word, char* mask, int count);
char get_user_choice();
void hangman(int count, int result);
const int MAX_GUESS = 6;
const char ABORT_CH = '0';
const int LOOSE = 0;
const int WIN = 1;
const int ABORTED = 2;
/************************************************************
*
* MAIN
*
*
************************************************************/
int main ()
{
char word[MAX_WORD_LEN];
char mask[MAX_WORD_LEN];
int ch;
int len;
int result;
int count;
/* -------------------- Programstart -----------------*/
srand(time(NULL));
while (true)
{
result = 5;
count = 0;
strcpy(word,datorns_val());
printf("Valt ord 2: %s", word);
free(datorns_val());
len = ordlengd(word);
strcpy(mask,datorns_val_mask(word,len));
printf("\nMask 2: %s <-----", mask);
free(datorns_val_mask(word,len));
printf( "\nV\x84lkommen till HANGMAN 2014!\n");
printf( "Du har %d gissningar p\x86 dig (avbryt med 0)\n", MAX_GUESS );
printf( "Datorn har nu valt ett ord p\x86 %d bokst\x84ver\n", len );
/* GAME MAIN LOOP */
while (count < 6)
{
count=spel(word,mask,len,count,result);
result=resultat(word,mask,count);
hangman(count,result);
}
/* END MAIN GAME LOOP */
if( result == WIN )
{
printf("\nGrattis du vann!\n");
}
else if( result == LOOSE )
{
printf("\nTyv\x84rr du f\x94rlorade! Ordet var: %s\n", word);
}
else
{
printf("Avbrutet\n");
}
printf("Vill du spela igen? (j/n)");
ch = get_user_choice();
if (ch == 'n' || ch == 'N')
{
break;
}
}
}
/***********************************************************
*
* --------- Funktionsdefinitioner ----------------
*
***********************************************************/
char get_user_choice()
{
char tkn;
scanf(" %c", &tkn);
return tkn;
}
char* datorns_val()
{
char ordlista[20];
char* valt_ord = malloc(20);
int random;
int raknare = 0;
random = rand()%4+1;
FILE *ptr_file;
ptr_file =fopen("hangman.dat","r");
if (!ptr_file)
{
printf("Filen kunde inte öppnas!");
}
while (fgets(ordlista,20, ptr_file)!= NULL)
{
if (raknare == random)
{
strcpy(valt_ord, ordlista);
break;
}
raknare=raknare+1;
}
printf("Valt ord 1: %s",valt_ord);
fclose(ptr_file);
return valt_ord;
}
int ordlengd(char* word)
{
printf("Valt ord 3: %s", word);
int ordlengd;
ordlengd=strlen(word)-1;
printf("Ordlengd 1: %i", ordlengd);
return ordlengd;
}
char* datorns_val_mask(char* word, int len)
{
int j;
char* gissning = malloc(20);
for (j=0; j<len; j++)
{
gissning[j]='_';
}
printf("\nMask 1: %s <----", gissning);
return gissning;
}
int spel(char* word, char* mask, int len, int count, int result)
{
int j;
char bokstav;
int ratt = 0;
printf("\nSkriv en bokstav: ");
scanf(" %c", &bokstav);
for(j=0; j<len; j++)
{
if(bokstav==word[j])
{
mask[j]=bokstav;
ratt = 1;
}
else if(bokstav=='0')
{
count = 7;
return count;
}
}
if (ratt == 0)
{
printf("\nBokstaven finns inte i ordet!\n");
count=count+1;
}
printf("Antal fel: %i\n\n", count);
ratt = 0;
for (j=0; j<len; j++)
{
printf("%c", mask[j]);
printf(" ");
}
return count;
}
void hangman(int count, int result)
{
const char* str[20];
int j;
str[0]="\n_______ \n";
str[1]=" | \n";
str[2]=" O \n";
str[3]="//|\\\\\n";
str[4]=" | \n";
str[5]="// \\\\\n";
if(result != ABORTED)
{
for (j=0; j<count; j++)
{
printf("%s", str[j]);
}
}
}
int resultat (char* word, char* mask, int count)
{
char* a = "Hej";
char* b = "Hej";
if (count == 6)
{
return LOOSE;
}
else if (count < 6 && strcmp(mask,word) == 0)
{
return WIN;
}
else if (count == 7)
{
return ABORTED;
}
}
There are some things around the code:
1) The first free() call in pointless:
free(datorns_val());
This reserves memory for a string and deletes it without making any use of it. So get rid of it.
2) Using fgets() to read strings from a file stores also the '\n' character at the end of the line into your string, so you must get rid of it. As a hint, I have used this sentence:
while(fscanf(ptr_file,"%s", ordlista) >0)
that does not store '\n' characters.
3) In ordlengd(char* word) function, you had problem with an extra character (the above mentioned '\n') so the length is the same as the one returned by strlen(), not the
strlen(word) - 1
you had written.
4) You have think about another condition to end the while loop of the main function. I would suggest to add
else return 5;
at the end of resultat() function and the check this value en the while loop of the main function
while (count < 6 && result == 5)
Hope it helps