Intermittent Failure with Blackjack code - c

The purpose of this code is to play a simulated game of Blackjack. The 'Dealer' is automated and will deal two cards to itself and stop when it wins/busts or hits 17. Then the user draws until he/she is satisfied. Then a winner is determined.
I've run into a brick wall because the code compiles fine, but when it runs it will either work (and by work I mean not work as intended but it will run) or it will crash.
I have no idea how this can happen only some of the time and not all of the time and I need some help.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 52
#define LIMIT 21
enum faces{Ace = 0, Jack = 10, Queen, King};
char * facecheck(int d);
void shuffle( int deck[]);
int draw(int deck[SIZE]);
void printcards(int hand[], int numCards);
int dealer(int deck[]);
int player(int deck[]);
int value(int yourhand[]);
int victory(int d, int p);
int i, numCards = 1;
int top = 52;
int preValue = 0;
int count = 2;
int main()
{
int deck[SIZE], i, a;
int d, p;
char suits[4][9] =
{
"Hearts",
"Diamonds",
"Clubs",
"Spades"};
srand( time( NULL ) ) ;
for(i = 0; i<SIZE; i++)
{
deck[i] = i;
};
shuffle(deck);
d = dealer(deck);
p = player(deck);
victory(d, p);
return 0;
}
char * facecheck(int d)
{
static char * face[] =
{
"Ace",
"Jack",
"Queen",
"King" };
if(d == Ace)
return face[0];
else
{
if(d == Jack)
return face[1];
else
{
if(d == Queen)
return face[2];
else
{
if(d == King)
return face[3];
}
}
}
}
void shuffle( int deck[])
{
int i, j, temp;
for(i = 0; i < SIZE; i++)
{
j = rand() % SIZE;
temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
printf("The deck has been shuffled \n");
}
int draw(int deck[SIZE])
{
int numCards = 1;
int i;
int hand[numCards];
int card;
for(i = 0; i < numCards && top > 0; i++)
{
card = deck[top-1];
hand[i] = card;
top--;
}
return card;
}
void printcards(int hand[], int numCard)
{
char suits[4][9] =
{
"Hearts",
"Diamonds",
"Clubs",
"Spades"};
for(i = 0; i < numCard; i++)
{
int card = hand[i];
if(card%13 == 0 || card%13 == 10 || card%13 == 11 || card%13 == 12)
printf("%s ", facecheck(card%13) );
else
printf("%d ", card%13+1);
printf("of %s \n", suits[card/13]);
}
}
int dealer(int deck[])
{
int x;
int a;
int yourhand[10];
int handIndex = 0;
int cardLimit;
int dealerValue;
yourhand[handIndex] = draw(deck);
yourhand[handIndex] = draw(deck);
printf("The Dealers second card is:");
printcards(yourhand, handIndex+1);
cardLimit = value(yourhand);
do
{
if(cardLimit == LIMIT)
{
printcards(yourhand, handIndex+1);
dealerValue = cardLimit;
return dealerValue;
}
if(cardLimit > LIMIT)
{
printcards(yourhand, handIndex+1);
dealerValue = cardLimit;
return dealerValue;
}
if(cardLimit == 17)
{
printcards(yourhand, handIndex+1);
dealerValue = cardLimit;
return dealerValue;
}
if(cardLimit <= 16)
{
yourhand[handIndex] = draw(deck);
cardLimit = value(yourhand);
}
}
while(cardLimit <= LIMIT);
handIndex++;
}
int player(int deck[])
{
int x;
int a;
int yourhand[10];
int cardLimit;
int playerValue;
int handIndex = 2;
yourhand[handIndex] = draw(deck);
yourhand[handIndex] = draw(deck);
cardLimit = value(yourhand);
printf("Your hand is: /n");
printcards(yourhand, handIndex+1);
printf("%d /n" , cardLimit);
do
{
if(cardLimit == LIMIT)
{
printcards(yourhand, handIndex+1);
playerValue = cardLimit;
return playerValue;
}
if(cardLimit > LIMIT)
{
printcards(yourhand, handIndex+1);
playerValue = cardLimit;
return playerValue;
}
else
{
printf("What would you like to do: Press 1 to Hit. 2 to Stay. \n");
scanf("%d" , &x);
if(x == 1)
{
yourhand[handIndex] = draw(deck);
cardLimit == value(yourhand);
}
else
{
printf("Player choses to stay \n");
return playerValue;
}
}
}
while(cardLimit <= LIMIT);
handIndex++;
}
int value(int yourhand[])
{
int faceValue = 10;
int cardValue[count];
int aceValue = 11;
int card[count];
int value;
int curvalue;
for(i = 0; i < count; i++)
{
card[i] = yourhand[i];
}
for(i = 0; i < count; i++)
{
cardValue[i] = card[i]%13;
}
if(cardValue[0] >= 10 && cardValue[1] >= 10)
{
value = 20;
}
if(cardValue[0] < 10 && cardValue[1] < 10)
{
value = cardValue[0] + cardValue[1];
}
if(cardValue[0] >= 10 && cardValue[1] < 10)
{
value = faceValue + cardValue[1];
}
if(cardValue[0] < 10 && cardValue[1] >= 10)
{
value = faceValue + cardValue[0];
}
if(cardValue[0] == 0 && cardValue[1] == 0)
{
value = 12;
}
if(cardValue[0] == 0 && cardValue[1] >= 10)
{
value = 21;
}
if(cardValue[1] == 0 && cardValue[0] >= 10)
{
value = 21;
}
if(cardValue[0] == 0 && cardValue[1] < 10)
{
value = aceValue + cardValue[1];
}
if(cardValue[1] == 0 && cardValue[0] < 10)
{
value = aceValue + cardValue[0];
}
preValue = value;
if(count > 2)
{
if(cardValue[count] != 0)
{
value = curvalue;
value = preValue + curvalue;
}
else
{
if(cardValue[count] + preValue > LIMIT)
{
value = preValue + 1;
}
else
{
value = cardValue[count] + aceValue;
}
}
}
count++;
return value;
}
int victory(int d, int p)
{
if(d > p)
printf("Dealer Wins \n");
else
printf("Player Wins");
}

In your code
int dealer(int deck[])
{
int handIndex = 0;
int yourhand[10];
yourhand[handIndex] = draw(deck);
yourhand[handIndex] = draw(deck);
you never change handIndex, so these two assignments are to the same element (ie, the second draw overwrites the first)
cardLimit = value(yourhand);
now, having written to yourhand[0] twice, and without initialising any other elements, you call value which expects yourhand[0] and yourhand[1] to be initialised.
This should be visible under valgrind (you're reading random values from uninitialized memory).

Related

How to get rid of error C1083: Cannot open include file: 'unistd.h'?

I'm trying to run this code on Visual Studio 2022, but it gives an error:
C1083: Cannot open include file: 'unistd.h': No such file or directory.
As I understood that the code was written for the UNIX system, but I would like to run it on Windows.
Snake game
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
#include<time.h>
#include<ctype.h>
#include <time.h>
#include <windows.h>
#include <process.h>
#include <unistd.h>
#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
int length;
int bend_no;
int len;
char key;
void record();
void load();
int life;
void Delay(long double);
void Move();
void Food();
int Score();
void Print();
void gotoxy(int x, int y);
void GotoXY(int x, int y);
void Bend();
void Boarder();
void Down();
void Left();
void Up();
void Right();
void ExitGame();
int Scoreonly();
struct coordinate {
int x;
int y;
int direction;
};
typedef struct coordinate coordinate;
coordinate head, bend[500], food, body[30];
int main()
{
char key;
Print();
system("cls");
load();
length = 5;
head.x = 25;
head.y = 20;
head.direction = RIGHT;
Boarder();
Food(); //to generate food coordinates initially
life = 3; //number of extra lives
bend[0] = head;
Move(); //initialing initial bend coordinate
return 0;
}
void Move()
{
int a, i;
do {
Food();
fflush(stdin);
len = 0;
for (i = 0; i < 30; i++)
{
body[i].x = 0;
body[i].y = 0;
if (i == length)
break;
}
Delay(length);
Boarder();
if (head.direction == RIGHT)
Right();
else if (head.direction == LEFT)
Left();
else if (head.direction == DOWN)
Down();
else if (head.direction == UP)
Up();
ExitGame();
} while (!kbhit());
a = getch();
if (a == 27)
{
system("cls");
exit(0);
}
key = getch();
if ((key == RIGHT && head.direction != LEFT && head.direction != RIGHT) || (key == LEFT && head.direction != RIGHT && head.direction != LEFT) || (key == UP && head.direction != DOWN && head.direction != UP) || (key == DOWN && head.direction != UP && head.direction != DOWN))
{
bend_no++;
bend[bend_no] = head;
head.direction = key;
if (key == UP)
head.y--;
if (key == DOWN)
head.y++;
if (key == RIGHT)
head.x++;
if (key == LEFT)
head.x--;
Move();
}
else if (key == 27)
{
system("cls");
exit(0);
}
else
{
printf("\a");
Move();
}
}
void gotoxy(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void GotoXY(int x, int y)
{
HANDLE a;
COORD b;
fflush(stdout);
b.X = x;
b.Y = y;
a = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(a, b);
}
void sleep(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
void load() {
int row, col, r, c, q;
gotoxy(36, 14);
printf("loading...");
gotoxy(30, 15);
for (r = 1; r <= 20; r++) {
sleep(200);//to display the character slowly
printf("%c", 177);
}
getch();
}
void Down()
{
int i;
for (i = 0; i <= (head.y - bend[bend_no].y) && len < length; i++)
{
GotoXY(head.x, head.y - i);
{
if (len == 0)
printf("v");
else
printf("*");
}
body[len].x = head.x;
body[len].y = head.y - i;
len++;
}
Bend();
if (!kbhit())
head.y++;
}
void Delay(long double k)
{
Score();
long double i;
for (i = 0; i <= (10000000); i++);
}
void ExitGame()
{
int i, check = 0;
for (i = 4; i < length; i++) //starts with 4 because it needs minimum 4 element to touch its own body
{
if (body[0].x == body[i].x && body[0].y == body[i].y)
{
check++; //check's value increases as the coordinates of head is equal to any other body coordinate
}
if (i == length || check != 0)
break;
}
if (head.x <= 10 || head.x >= 70 || head.y <= 10 || head.y >= 30 || check != 0)
{
life--;
if (life >= 0)
{
head.x = 25;
head.y = 20;
bend_no = 0;
head.direction = RIGHT;
Move();
}
else
{
system("cls");
printf("All lives completed\nBetter Luck Next Time!!!\nPress any key to quit the game\n");
record();
exit(0);
}
}
}
void Food()
{
if (head.x == food.x && head.y == food.y)
{
length++;
time_t a;
a = time(0);
srand(a);
food.x = rand() % 70;
if (food.x <= 10)
food.x += 11;
food.y = rand() % 30;
if (food.y <= 10)
food.y += 11;
}
else if (food.x == 0)/*to create food for the first time coz global variable are initialized with 0*/
{
food.x = rand() % 70;
if (food.x <= 10)
food.x += 11;
food.y = rand() % 30;
if (food.y <= 10)
food.y += 11;
}
}
void Left()
{
int i;
for (i = 0; i <= (bend[bend_no].x - head.x) && len < length; i++)
{
GotoXY((head.x + i), head.y);
{
if (len == 0)
printf("<");
else
printf("*");
}
body[len].x = head.x + i;
body[len].y = head.y;
len++;
}
Bend();
if (!kbhit())
head.x--;
}
void Right()
{
int i;
for (i = 0; i <= (head.x - bend[bend_no].x) && len < length; i++)
{
//GotoXY((head.x-i),head.y);
body[len].x = head.x - i;
body[len].y = head.y;
GotoXY(body[len].x, body[len].y);
{
if (len == 0)
printf(">");
else
printf("*");
}
/*body[len].x=head.x-i;
body[len].y=head.y;*/
len++;
}
Bend();
if (!kbhit())
head.x++;
}
void Bend()
{
int i, j, diff;
for (i = bend_no; i >= 0 && len < length; i--)
{
if (bend[i].x == bend[i - 1].x)
{
diff = bend[i].y - bend[i - 1].y;
if (diff < 0)
for (j = 1; j <= (-diff); j++)
{
body[len].x = bend[i].x;
body[len].y = bend[i].y + j;
GotoXY(body[len].x, body[len].y);
printf("*");
len++;
if (len == length)
break;
}
else if (diff > 0)
for (j = 1; j <= diff; j++)
{
/*GotoXY(bend[i].x,(bend[i].y-j));
printf("*");*/
body[len].x = bend[i].x;
body[len].y = bend[i].y - j;
GotoXY(body[len].x, body[len].y);
printf("*");
len++;
if (len == length)
break;
}
}
else if (bend[i].y == bend[i - 1].y)
{
diff = bend[i].x - bend[i - 1].x;
if (diff < 0)
for (j = 1; j <= (-diff) && len < length; j++)
{
/*GotoXY((bend[i].x+j),bend[i].y);
printf("*");*/
body[len].x = bend[i].x + j;
body[len].y = bend[i].y;
GotoXY(body[len].x, body[len].y);
printf("*");
len++;
if (len == length)
break;
}
else if (diff > 0)
for (j = 1; j <= diff && len < length; j++)
{
/*GotoXY((bend[i].x-j),bend[i].y);
printf("*");*/
body[len].x = bend[i].x - j;
body[len].y = bend[i].y;
GotoXY(body[len].x, body[len].y);
printf("*");
len++;
if (len == length)
break;
}
}
}
}
void Boarder()
{
system("cls");
int i;
GotoXY(food.x, food.y); /*displaying food*/
printf("F");
for (i = 10; i < 71; i++)
{
GotoXY(i, 10);
printf("!");
GotoXY(i, 30);
printf("!");
}
for (i = 10; i < 31; i++)
{
GotoXY(10, i);
printf("!");
GotoXY(70, i);
printf("!");
}
}
void Print()
{
//GotoXY(10,12);
printf("\tWelcome to the mini Snake game.(press any key to continue)\n");
getch();
system("cls");
printf("\tGame instructions:\n");
printf("\n-> Use arrow keys to move the snake.\n\n-> You will be provided foods at the several coordinates of the screen which you have to eat. Everytime you eat a food the length of the snake will be increased by 1 element and thus the score.\n\n-> Here you are provided with three lives. Your life will decrease as you hit the wall or snake's body.\n\n-> YOu can pause the game in its middle by pressing any key. To continue the paused game press any other key once again\n\n-> If you want to exit press esc. \n");
printf("\n\nPress any key to play game...");
if (getch() == 27)
exit(0);
}
void record() {
char plname[20], nplname[20], cha, c;
int i, j, px;
FILE* info;
info = fopen("record.txt", "a+");
getch();
system("cls");
printf("Enter your name\n");
scanf("%[^\n]", plname);
//************************
for (j = 0; plname[j] != '\0'; j++) { //to convert the first letter after space to capital
nplname[0] = toupper(plname[0]);
if (plname[j - 1] == ' ') {
nplname[j] = toupper(plname[j]);
nplname[j - 1] = plname[j - 1];
}
else nplname[j] = plname[j];
}
nplname[j] = '\0';
//*****************************
//sdfprintf(info,"\t\t\tPlayers List\n");
fprintf(info, "Player Name :%s\n", nplname);
//for date and time
time_t mytime;
mytime = time(NULL);
fprintf(info, "Played Date:%s", ctime(&mytime));
//**************************
fprintf(info, "Score:%d\n", px = Scoreonly());//call score to display score
//fprintf(info,"\nLevel:%d\n",10);//call level to display level
for (i = 0; i <= 50; i++)
fprintf(info, "%c", '_');
fprintf(info, "\n");
fclose(info);
printf("wanna see past records press 'y'\n");
cha = getch();
system("cls");
if (cha == 'y') {
info = fopen("record.txt", "r");
do {
putchar(c = getc(info));
} while (c != EOF);
}
fclose(info);
}
int Score()
{
int score;
GotoXY(20, 8);
score = length - 5;
printf("SCORE : %d", (length - 5));
score = length - 5;
GotoXY(50, 8);
printf("Life : %d", life);
return score;
}
int Scoreonly()
{
int score = Score();
system("cls");
return score;
}
void Up()
{
int i;
for (i = 0; i <= (bend[bend_no].y - head.y) && len < length; i++)
{
GotoXY(head.x, head.y + i);
{
if (len == 0)
printf("^");
else
printf("*");
}
body[len].x = head.x;
body[len].y = head.y + i;
len++;
}
Bend();
if (!kbhit())
head.y--;
}
I tried to find information on how to fix the code, but I did not succeed.

Array of structures lose data while passing it in C

I don't understand why printq() function prints 0, but when I access it back in main() it prints. I don't understand what I am doing wrong, I tried using pointers, but I get some different error in the priority queue. I want to print elements in array pq[10].
EDIT: I realized that the elements are stored but when I use pq[R].data it prints
but when I use pq[i].data in printq() and put it inside for loop, it prints zero.
#include <stdio.h>
int F = -1, R = -1;
int item, max = 10;
struct prioq {
int data;
int prio;
};
struct prioq pq[10] = { 0 };
void printq()
{
int i = 0;
printf("%d,", pq[i].data);
printf("QUEUE :");
for (i = 0; i < max; i++) {
printf("%d,", pq[i].data);
}
printf("\n");
printf("PRIO :");
for (i = 0; i < max; i++) {
printf("%d,", pq[i].prio);
}
}
void enqueue(int item, int p, struct prioq pq[])
{
if (F == -1 && R == -1 || F > R) {
F == 0;
R == 0;
pq[R].data = item;
pq[R].prio = p;
printf("%d", pq[R].data);
printf("%d", pq[R].prio);
printq();
} else if (R == max-1 || R > max) {
printf("overflow\n");
} else if (R < max) {
R++;
pq[R].data = item;
pq[R].prio = p;
printq();
}
}
void dequeue(struct prioq pq[])
{
int large = 0;
if (F == -1) {
printf("underflow\n");
} else {
int i;
for (i = 0; i < max; i++) {
if (pq[i].prio > large) {
large = i;
}
}
}
item = pq[large].data;
pq[large].prio = 0;
pq[large].data = 0;
printf("item deleted: %d\n", item);
printq();
}
void main()
{
int item = 0;
int c = 0, p = 0;
do {
printf("choose your option\n");
printf("1.Insert, 2.Delete, 3.Exit\n" );
scanf("%d", &c);
switch (c) {
case 1:
printf("Enter the priority and element to insert\n");
scanf("%d %d", &item, &p);
enqueue(item,p,pq);
printf("%d", pq[R].data);
printf("%d", pq[R].prio);
break;
case 2:
dequeue(pq);
break;
default:
c = 3;
break;
}
} while (c != 3);
printf("exited\n");
}
In your enqueue function, change the == in the F and R assignments to =.
void enqueue(int item, int p, struct prioq pq[])
{
if (F == -1 && R == -1 || F > R) {
F = 0; // Here
R = 0; // And here
pq[R].data = item;
pq[R].prio = p;
printf("%d", pq[R].data);
printf("%d", pq[R].prio);
printq();
} else if (R == max-1 || R > max) {
printf("overflow\n");
} else if (R < max) {
R++;
pq[R].data = item;
pq[R].prio = p;
printq();
}
}

Why do I get a segmentation fault accessing a struct?

Edit: added the rest of my code so it's easier to see
I'm receiving a segmentation fault when trying to access certain values of a struct in a header file.
Here's courses.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "structs.h"
void createStudents () {
int random, i;
for (i = 0; i < 12; i++) {
students[i].firstName = firstName[i];
students[i].lastName = lastName[i];
random = 10000 + rand() % 89999;
students[i].num.studentNum = random;
printf("%d - %s, %s \n", students[i].num.studentNum, students[i].lastName, students[i].firstName);
}
}
void createCourses () {
int numbers[999];
int numbersLeft = 999;
char courseCode[512];
char courseCode1[512];
char courseCode2[512];
int numCourses = 3;
int random, i, j;
for (i = 0; i < 999; i++) {
numbers[i] = i;
}
for (j = 0; j < 1; j++) {
random = rand() % numbersLeft;
if (random < 10) {
snprintf(courseCode, sizeof courseCode, "CS00%d", random);
courses[0].cCode = courseCode;
}
else if (random < 100 && random > 9) {
snprintf(courseCode, sizeof courseCode, "CS0%d", random);
courses[0].cCode = courseCode;
}
else if (random > 99){
snprintf(courseCode, sizeof courseCode, "CS%d", random);
courses[0].cCode = courseCode;
}
courses[0].cName = courseName[0];
courses[0].cDescription = courseDescription[0];
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
random = 4 + rand() % 4;
courses[0].maxRegister = random;
}
for (j = 0; j < 1; j++) {
random = rand() % numbersLeft;
if (random < 10) {
snprintf(courseCode1, sizeof courseCode1, "CS00%d", random);
courses[1].cCode = courseCode1;
}
else if (random < 100 && random > 9) {
snprintf(courseCode1, sizeof courseCode1, "CS0%d", random);
courses[1].cCode = courseCode1;
}
else if (random > 99){
snprintf(courseCode1, sizeof courseCode1, "CS%d", random);
courses[1].cCode = courseCode1;
}
courses[1].cName = courseName[1];
courses[1].cDescription = courseDescription[1];
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
random = 4 + rand() % 4;
courses[1].maxRegister = random;
}
for (j = 0; j < 1; j++) {
random = rand() % numbersLeft;
if (random < 10) {
snprintf(courseCode2, sizeof courseCode2, "CS00%d", random);
courses[2].cCode = courseCode2;
}
else if (random < 100 && random > 9) {
snprintf(courseCode2, sizeof courseCode2, "CS0%d", random);
courses[2].cCode = courseCode2;
}
else if (random > 99){
snprintf(courseCode2, sizeof courseCode2, "CS%d", random);
courses[2].cCode = courseCode2;
}
courses[2].cName = courseName[2];
courses[2].cDescription = courseDescription[2];
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
random = 4 + rand() % 4;
courses[2].maxRegister = random;
}
}
void regiserStudents () {
int checkSum = 0, checkSum1 = 0, checkTemp = 0, count0 = 0, count1 = 0, count2 = 0;
int wCount0 = 0, wCount1 = 0, wCount2 = 0;
int v, i, j, random, max0, max1, max2;
max0 = courses[0].maxRegister;
max1 = courses[1].maxRegister;
max2 = courses[2].maxRegister;
for (i = 0; i < 2; i++) {
checkTemp = count0;
for (j = 0; j < 12; j++) {
random = rand() % 3;
if (random == 0) {
if (count0 == 0) {
courses[random].registered[count0] = &students[j];
count0++;
}
else {
checkSum1 = students[j].num.studentNum;
for (v = 0; v < checkTemp; v++) {
checkSum = courses[0].registered[v]->num.studentNum;
if (checkSum == checkSum1) {
/*Do Nothing*/
}
else if (count0 == max0) {
courses[random].waitlisted[count0] = &students[j];
wCount0++;
}
else {
courses[random].registered[count0] = &students[j];
count0++;
}
/*}*/
}
}
}
if (random == 1) {
if (count1 == 0) {
courses[random].registered[count1] = &students[j];
count1++;
}
else {
checkSum1 = students[j].num.studentNum;
for (v = 0; v < checkTemp; v++) {
checkSum = courses[1].registered[v]->num.studentNum;
if (checkSum == checkSum1) {
/*Do Nothing*/
}
else if (count1 == max1) {
courses[random].waitlisted[count1] = &students[j];
wCount1++;
}
else {
courses[random].registered[count1] = &students[j];
count1++;
}
}
}
}
if (random == 2) {
if (count2 == 0) {
courses[random].registered[count2] = &students[j];
count2++;
}
else {
checkSum1 = students[j].num.studentNum;
for (v = 0; v < checkTemp; v++) {
checkSum = courses[2].registered[v]->num.studentNum;
if (checkSum == checkSum1) {
/*Do Nothing*/
}
else if (count2 == max2) {
courses[random].waitlisted[count2] = &students[j];
wCount2++;
}
else {
courses[random].registered[count2] = &students[j];
count2++;
}
}
}
}
}
}
courses[0].studentRegistered = count0;
courses[1].studentRegistered = count1;
courses[2].studentRegistered = count2;
courses[0].studentWaitlisted = wCount0;
courses[1].studentWaitlisted = wCount1;
courses[2].studentWaitlisted = wCount2;
}
void printCourses () {
int i;
printf("\n%s - %s: %s\nRegistered Students (%d/%d):\n", courses[0].cCode, courses[0].cName, courses[0].cDescription, courses[0].studentRegistered, courses[0].maxRegister);
for (i = 0; i < courses[0].studentRegistered; i++) {
printf("* %d - %s, %s \n", courses[0].registered[i]->num.studentNum, courses[0].registered[i]->lastName, courses[0].registered[i]->firstName);
}
printf("Waitlisted Students (%d)", courses[0].studentWaitlisted);
if (courses[0].studentWaitlisted == 0) {
printf("\n");
}
else {
for (i = 0; i < courses[0].studentWaitlisted; i++) {
printf("* %d - %s, %s \n", courses[0].waitlisted[i]->num.studentNum, courses[0].waitlisted[i]->lastName, courses[0].waitlisted[i]->firstName);
}
}
printf("\n%s - %s: %s\nRegistered Students (%d/%d):\n", courses[1].cCode, courses[1].cName, courses[1].cDescription, courses[1].studentRegistered, courses[1].maxRegister);
for (i = 0; i < courses[1].studentRegistered; i++) {
printf("* %d - %s, %s \n", courses[1].registered[i]->num.studentNum, courses[1].registered[i]->lastName, courses[1].registered[i]->firstName);
}
printf("\n%s - %s: %s\nRegistered Students (%d/%d):\n", courses[2].cCode, courses[2].cName, courses[2].cDescription, courses[2].studentRegistered, courses[2].maxRegister);
for (i = 0; i < courses[2].studentRegistered; i++) {
printf("* %d - %s, %s \n", courses[2].registered[i]->num.studentNum, courses[2].registered[i]->lastName, courses[2].registered[i]->firstName);
}
}
And here's my header file
structs.h
#ifndef STRUCTS_H_
#define STRUCTS_H_
char *firstName[] = {
"Emma", "Liam", "Olivia",
"Noah", "Ava", "Logan",
"Sophia", "Lucas", "Isabella",
"Mason", "Shaylyn", "Jack"
};
char *lastName[] = {
"Smith", "Johnson", "Williams",
"Brown", "Jones", "Miller",
"Davis", "Garcia", "Rodriguez",
"Wilson", "Seguin", "Loveday"
};
typedef struct{
int studentNum;
}studentNumber;
typedef struct{
char *firstName;
char *lastName;
studentNumber num;
}studentID;
studentID students[12];
char *courseName[] = {"Web Programming", "Technical Communication", "Processor Architecture"};
char *courseDescription[] = {"Learn the language of HTML, and how to create websites.", "Learn the essentials of communication skills, and how to apply them on the job.", "Learn the basics of circuits and Machine Language coding."};
typedef struct {
int maxRegister;
char *cCode;
char *cName;
char *cDescription;
studentID *registered[8];
studentID *waitlisted[12];
int studentRegistered;
int studentWaitlisted;
}course;
course courses[3];
#endif
Printing the values of the registered students works fine, but when I print the waitlisted students I get a segmentation error. I used gdb and found it was on this line but couldn't figure out why:
printf("%d - %s, %s \n", courses[0].waitlisted[i]->num.studentNum, courses[0].waitlisted[i]->lastName, courses[0].waitlisted[i]->firstName);
studentID *waitlisted[12]; That means they will hold the address of variable of type structure studentID. You simply didn't do this but start to access those pointer variables. You have passed them to scanf which invokes undefined behavior due to trying to read an unintialized pointer variable.
So what you need to do here -
courses[i].waitlisted = malloc(sizeof *courses[i].waitlisted * courses[i].studentWaitlisted);
Same goes for the studentID also. Here fistName is a char* you need to allocate some meory to access it otherwise it's UB.
Or
typedef struct{
char firstName[100]; //you are considering that name length would be 100
//at max.
char lastName[100];
studentNumber num;
}studentID;
After OP edited question:
The seg fault you get is because of accessing a local variable after it's lifetime ended.
courses[0].cCode = courseCode;
What you can do is
courses[0].cCode = strdup(courseCode);
Initialize array int numbers[999]={0}; otherwise you might access garbage value as the indexing is result of random number geneartion.
if( random < 999){
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
}
else{
fprintf(stderr, "%s\n","Error" );
}
Lots of repeated code. You should remove repeated code. And also there is no need for single-iteration-for-loop.

Having trouble coming up with a 'display function' or added functionality - c

Finishing up a program and been told that I need to have the cards be displayed after the user quits.
Tried having draw return the hand variable and printing that, and storing each result of the draw(), which I had turned to int; although I am showing you the working function, which is void.
So far nothing works and I am lost.
void draw(int deck[SIZE], int a) {
int numCards = 10;
int i;
int hand[numCards];
int card;
for(i = 0; i < numCards && top > 0; i++) {
card = deck[top-1];
hand[i] = card;
top--;
}
if(a != 0) {
printcards(card);
} else {
for(i = 0; i < numCards && top > 0; i++)
printcards(card);
}
}
Program can print off cards as drawn and edited version looks like:
int draw(int deck[SIZE], int a) {
int numCards = 10;
int i;
int hand[numCards];
int card;
for(i = 0; i < numCards && top > 0; i++) {
card = deck[top-1];
hand[i] = card;
top--;
}
if(a != 0) {
printcards(card);
} else {
for(i = 0; i < numCards && top > 0; i++)
printcards(card);
}
return card; /* or return hand */
}
void printcards(int card) {
char suits[4][9] = {
"Hearts",
"Diamonds",
"Clubs",
"Spades"
};
if(card%13 == 0 || card%13 == 10 || card%13 == 11 || card%13 == 12) {
printf("%s ", facecheck(card%13) );
} else {
printf("%d ", card%13+1);
}
printf("of %s \n", suits[card/13]);
}
This function is the actual printing of cards:
void players(int deck[]) {
int x;
int a;
int yourhand[10];
a = 1;
printf("Player 1 \n");
printf("Your Hand is: \n");
draw(deck, a);
draw(deck, a);
while(a == 1) {
printf("What would you like to do: Press 1 to Draw. 2 to Stay. \n");
scanf("%d" , &x);
if(x == 1) {
draw(deck, a);
} else {
a--;
}
}
}
This function calls the draw() with user input, then need to add a display() after the else, before a-- or store result of draw into your hand and print result. So far nothing has worked.

Pointers and Dynamic Memory

I have a function that returns a pointer to an array. I'm running it in a loop and free() seems to be giving me problems. I'm not sure where, but it appears that somewhere in the main loop the memory that I'm trying to free is being used. I'm using Xcode 3.2.1 in 10.6 | Debug | x86_64 build.
The program will run through the main loop one time; the second time it encounters the free() it gives me the following error:
malloc: *** error for object 0x100100180: incorrect checksum for freed object -
object was probably modified after being freed.
Can someone point out (no pun intended) what I'm doing wrong with pointers here?
Here is the program:
int main(int argc, char **argv) {
int *partition;
int lowerLimit;
int upperLimit;
// snip ... got lowerLimit and upperLimit from console arguments
// this is the 'main loop':
for (int i = lowerLimit; i <= upperLimit; i += 2) {
partition = goldbachPartition(i);
printOutput(partition[0], partition[1], i);
free(partition); // I get problems on the second iteration here
}
return 0;
}
int *goldbachPartition(int x) {
int solved = 0;
int y, z;
int *primes;
int *result;
result = intAlloc(2);
primes = atkinsPrimes(x);
for (int i = intCount(primes)-1; i >= 0; i--) {
y = primes[i];
for (int j = 0; j < y; j++) {
z = primes[j];
if (z + y >= x) {
break;
}
}
if (z + y == x) {
solved = 1;
result[0] = y;
result[1] = z;
break;
} else if (y == z) {
result[0] = 0;
result[1] = 0;
break;
}
}
free(primes);
return result;
}
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int counter = 0;
int sqrtLimit;
int xLimit;
int resultsSize;
primes = intAlloc(limit+1);
intFillArray(primes, limit+1, 0);
sqrtLimit = floor(sqrt(limit));
xLimit = floor(sqrt((limit+1) / 2));
// these loops are part of the Atkins Sieve implementation
for (int x = 1; x < xLimit; x++) {
int xx = x*x;
for (int y = 1; y < sqrtLimit; y++) {
int yy = y*y;
int n = 3*xx + yy;
if (n <= limit && n % 12 == 7) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
n += xx;
if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
if (x > y) {
n -= xx + 2*yy;
if (n <= limit && n % 12 == 11) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
}
}
}
for (int n = 5; n < limit; n++) {
if (primes[n] == 1) {
for (int k = n*n; k < limit; k += n*n) {
primes[k] = 0;
}
}
}
initialPrimes = intAlloc(2);
if (limit >= 2) {
initialPrimes[counter++] = 2;
}
if (limit >= 3) {
initialPrimes[counter++] = 3;
}
filtered = intFilterArrayKeys(primes, limit+1);
results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered);
results[resultsSize] = 0;
return results;
}
int trueCount(int *subject, int arraySize) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
count++;
}
}
return count;
}
int intCount(int *subject) {
// warning: expects 0 terminated array.
int count = 0;
while (*subject++ != 0) {
count++;
}
return count;
}
void intFillArray(int *subject, int arraySize, int value) {
for (int i = 0; i < arraySize; i++) {
subject[i] = value;
}
}
int *intFilterArrayKeys(int *subject, int arraySize) {
int *filtered;
int count = 0;
filtered = intAlloc(trueCount(subject, arraySize));
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
filtered[count++] = i;
}
}
return filtered;
}
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
int *merge;
int count = 0;
merge = intAlloc(arraySize1 + arraySize2);
for (int i = 0; i < arraySize1; i++) {
merge[count++] = subject1[i];
}
for (int i = 0; i < arraySize2; i++) {
merge[count++] = subject2[i];
}
return merge;
}
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if (ptr == NULL) {
printf("Error: NULL pointer\n");
}
return ptr;
}
void printOutput(int num1, int num2, int rep) {
if (num1 == 0) {
printf("%d: No solution\n", rep);
exit(0);
} else {
printf("%d = %d + %d\n", rep, num1, num2);
}
}
Why is intAlloc not returning int* ?
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if(ptr == NULL) {
printf("Error: NULL pointer\n");
exit(1);
}
return ptr; //like this
}
EDIT (after your update):
On atkinsPrimes() where is filtered being intAlloc()ed?
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int resultsSize;
primes = intAlloc(limit+1);
// ...
initialPrimes = intAlloc(2);
// ...
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered); // Where was it intAlloc()ed?
results[resultsSize] = 0; // make the array 0-terminated to make it easier to work with
return results;
}
EDIT (after your N-th update):
This is a compilable version of your code. It ran smooth on my machine, no crashes. Compiled with g++ (due to declarations of variables inside the for statement):
g++ (Debian 4.3.2-1.1) 4.3.2
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int *goldbachPartition(int x);
int *atkinsPrimes(int limit);
int trueCount(int *subject, int arraySize);
int intCount(int *subject) ;
void intFillArray(int *subject, int arraySize, int value);
int *intFilterArrayKeys(int *subject, int arraySize);
int *intAlloc(int amount);
void printOutput(int num1, int num2, int rep) ;
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2);
int main(int argc, char **argv) {
if (argc < 3) {
printf("Usage: ./program <lower> <upper>\n");
return 0;
}
int *partition;
int lowerLimit = atoi(argv[1]);
int upperLimit = atoi(argv[2]);
// snip ... got lowerLimit and upperLimit from console arguments
// this is the 'main loop':
for (int i = lowerLimit; i <= upperLimit; i += 2) {
partition = goldbachPartition(i);
printOutput(partition[0], partition[1], i);
free(partition); // I get problems on the second iteration here
}
return 0;
}
int *goldbachPartition(int x) {
int solved = 0;
int y, z;
int *primes;
int *result;
result = intAlloc(2);
primes = atkinsPrimes(x);
for (int i = intCount(primes)-1; i >= 0; i--) {
y = primes[i];
for (int j = 0; j < y; j++) {
z = primes[j];
if (z + y >= x) {
break;
}
}
if (z + y == x) {
solved = 1;
result[0] = y;
result[1] = z;
break;
} else if (y == z) {
result[0] = 0;
result[1] = 0;
break;
}
}
free(primes);
return result;
}
int *atkinsPrimes(int limit) {
int *primes;
int *initialPrimes;
int *filtered;
int *results;
int counter = 0;
int sqrtLimit;
int xLimit;
int resultsSize;
primes = intAlloc(limit+1);
intFillArray(primes, limit+1, 0);
sqrtLimit = floor(sqrt(limit));
xLimit = floor(sqrt((limit+1) / 2));
for (int x = 1; x < xLimit; x++) {
int xx = x*x;
for (int y = 1; y < sqrtLimit; y++) {
int yy = y*y;
int n = 3*xx + yy;
if (n <= limit && n % 12 == 7) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
n += xx;
if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
if (x > y) {
n -= xx + 2*yy;
if (n <= limit && n % 12 == 11) {
primes[n] = (primes[n] == 1) ? 0 : 1;
}
}
}
}
for (int n = 5; n < limit; n++) {
if (primes[n] == 1) {
for (int k = n*n; k < limit; k += n*n) {
primes[k] = 0;
}
}
}
initialPrimes = intAlloc(2);
if (limit >= 2) {
initialPrimes[counter++] = 2;
}
if (limit >= 3) {
initialPrimes[counter++] = 3;
}
filtered = intFilterArrayKeys(primes, limit+1);
results = intMergeArrays(initialPrimes, filtered, counter, trueCount(primes, limit+1));
resultsSize = counter + trueCount(primes, limit+1);
free(primes);
free(initialPrimes);
free(filtered);
results[resultsSize] = 0;
return results;
}
int trueCount(int *subject, int arraySize) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
count++;
}
}
return count;
}
int intCount(int *subject) {
// warning: expects 0 terminated array.
int count = 0;
while (*subject++ != 0) {
count++;
}
return count;
}
void intFillArray(int *subject, int arraySize, int value) {
for (int i = 0; i < arraySize; i++) {
subject[i] = value;
}
}
int *intFilterArrayKeys(int *subject, int arraySize) {
int *filtered;
int count = 0;
filtered = intAlloc(trueCount(subject, arraySize));
for (int i = 0; i < arraySize; i++) {
if (subject[i] == 1) {
filtered[count++] = i;
}
}
return filtered;
}
int *intMergeArrays(int *subject1, int *subject2, int arraySize1, int arraySize2) {
int *merge;
int count = 0;
merge = intAlloc(arraySize1 + arraySize2);
for (int i = 0; i < arraySize1; i++) {
merge[count++] = subject1[i];
}
for (int i = 0; i < arraySize2; i++) {
merge[count++] = subject2[i];
}
return merge;
}
int *intAlloc(int amount) {
int *ptr;
ptr = (int *)malloc(amount * sizeof(int));
if (ptr == NULL) {
printf("Error: NULL pointer\n");
}
return ptr;
}
void printOutput(int num1, int num2, int rep) {
if (num1 == 0) {
printf("%d: No solution\n", rep);
exit(0);
} else {
printf("%d = %d + %d\n", rep, num1, num2);
}
}
Since you are still omitting some source, I can only imagine that the problem is hidden there.
EDIT: (my last update)
To assist your debugging, you should replace your main() function by the one below:
int main(int argc, char **argv)
{
int *primes = NULL;
primes = atkinsPrimes(44); // Evil magic number
free(primes);
return 0;
}
Having a minimal example to reproduce the behavior you pointed out is much better then the whole thing. Have fun with atkinsPrimes(44)

Resources