int run_me(unsigned long prime, unsigned long max, int *ary) {
unsigned long i;
printf("\nI am %d", prime);
if(prime > sqrt(max)) {
return 1; /* do no run */
}
for(i = 3; i*prime < max; i+=2) {
ary[i*prime - 1] = 1;
}
return 0;
}
typedef struct Args {
unsigned long max, prime;
int *ary;
} args;
void *thread_runner(void *all_args) {
args *my_args = all_args;
run_me(my_args->prime, my_args->max, my_args->ary);
return 0;
}
unsigned long *sieve_of_eratosthenes(unsigned long begin, unsigned long end) {
unsigned long i, j, arylen, *ary_to_ret;
unsigned long current_primes[4] = {3, 5, 7, 11}; /* holds primes being used by threads*/
int *ary_of_all;
pthread_t threads[4];
args *curr;
curr = malloc(sizeof(args));
ary_of_all = calloc(end, sizeof(int));
arylen = end - begin + 2;
ary_to_ret = calloc(arylen, sizeof(unsigned long));
ary_of_all[0] = 1;
/*mark all even numbers*/
for(i = 1; 2 * i < end; i++) {
ary_of_all[2*i - 1] = 1;
}
while(current_primes[3] < sqrt(end)) {
/*run threads with current primes*/
for(i = 0; i < 4; i++) {
curr->prime = current_primes[i];
curr->max = end;
curr->ary = ary_of_all;
pthread_create(&threads[i], NULL, thread_runner, curr);
}
/* join all threads */
for(i = 0; i < 4; i++) {
pthread_join(threads[i], NULL);
}
j = 0; /* number of primes found */
/*find new primes*/
for(i = current_primes[3] + 2; i < end && j < 4; i+=2) {
if(ary_of_all[i - 1] == 0) {
current_primes[j] = i;
j++;
}
}
}
/*run threads one more time*/
if(current_primes[0] <= sqrt(end)) {
for(i = 0; i < 4; i++) {
curr->prime = current_primes[i];
curr->max = end;
curr->ary = ary_of_all;
pthread_create(&threads[i], NULL, thread_runner, curr);
}
/* join all threads */
for(i = 0; i < 4; i++) {
pthread_join(threads[i], NULL);
}
}
/*create the array to be returned*/
j = 0; /*pos in *ary_to_ret*/
for(i = begin; i <= end; i++) {
if(ary_of_all[i-1] == 0) {
ary_to_ret[j] = i;
j++;
}
}
ary_to_ret[j] = 0; /* null terminate */
ary_to_ret = realloc(ary_to_ret, (j+1) * sizeof(unsigned long));
return ary_to_ret;
}
I am running the above code in order to get a list of primes given a high and low value using the Sieve of Eratosthenes. I have the code mostly working, however when I run this code the thread which I create using the first element in my curr_primes array is never used and instead runs 5, 7, 11, 11. It does this every time it runs through the array and repopulates it. I was wondering if someone could explain to me why it runs in this way.
You are passing the same curr pointer to all the threads. You are lucky that it even works as well as you have observed as that is a huge race condition. Instead, the code needs to pass a seperate arg buffer to each thread. Here is one example:
/* doesn't really need to be dynamic memory in this simple example */
args curr[4];
for(i = 0; i < 4; i++) {
curr[i].prime = current_primes[i];
curr[i].max = end;
curr[i].ary = ary_of_all;
pthread_create(&threads[i], NULL, thread_runner, &curr[i]);
}
/* join all threads */
for(i = 0; i < 4; i++) {
pthread_join(threads[i], NULL);
}
Related
I have been given the homework of making 5 threads as "philosophers" and each of them has to lock "eat" 2 synchronization locks simultaneously. Each thread must do this a million times.
The other part of this homework is to make the "philosophers" processes, and the locks mutex's.
I have made this code for the threaded part, and while it does technically work, the result isn't what I'd expect. The code has a logging system in which a red [NUM-x] means NUM thread attempted to lock two locks and failed to do so. And a green [NUM1-NUM2] means NUM1 thread successfully locked and unlocked 2 threads for the NUM2'd time.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
#define CHOPSTICKS 5
#define PEOPLE 5
#define EAT_AMOUNT 1000000
#define MIN 2
#define INVALID -1
#define PAUSE printf("\n\n"); system("pause")
CRITICAL_SECTION chopsticks[CHOPSTICKS];
HANDLE chopsticksMutex[CHOPSTICKS]; // used for the mutex part of this question
VOID WINAPI eatThreadCritSect(LPVOID params) {
int index[MIN] = { 0 };
int usage = 0;
BOOL usageFlag = FALSE;
for (int i = 0; i < MIN; i++) {
index[i] = INVALID;
}
for (int i = 0; i < EAT_AMOUNT; i++) {
while (usage != MIN) {
for (int j = 0; j < CHOPSTICKS; j++) {
for (int k = 0; k < MIN && !usageFlag; k++) {
if (index[k] == j) {
usageFlag = TRUE;
}
}
if (!usageFlag) {
for (int k = 0; k < MIN && !usageFlag; k++) {
if (index[k] == INVALID) {
if (TryEnterCriticalSection(&chopsticks[j])) {
index[k] = j;
usage++;
}
usageFlag = TRUE;
}
}
}
usageFlag = FALSE;
}
for (int j = 0; j < MIN; j++) {
if (index[j] != INVALID) {
LeaveCriticalSection(&chopsticks[index[j]]);
index[j] = INVALID;
}
}
if (usage != MIN) {
printf("\x1b[31m[%d-X]", (int)params + 1); // CHOPSTICKS UNAVAILABLE
usage = 0;
}
}
printf("\x1b[32m[%d-%d]", ((int)params + 1), i + 1); // ATE SUCCESSFULLY
usage = 0;
}
}
void criticalEat() {
HANDLE hThreads[PEOPLE];
time_t begin = time(NULL);
for (int i = 0; i < PEOPLE; i++) {
hThreads[i] = CreateThread(NULL, 0, eatThreadCritSect, i, 0, NULL);
}
for (int i = 0; i < PEOPLE; i++) {
if (hThreads[i]) {
WaitForSingleObject(hThreads[i], INFINITE);
CloseHandle(hThreads[i]);
}
}
time_t end = time(NULL);
printf("\n\n\x1b[0mThey're now very saturated. It took them %llu seconds to eat with critical sections.", (end - begin));
}
void mutexEat() { // used for the mutex part of this question
PROCESS_INFORMATION hProcesses[PEOPLE];
CHAR name[] = "philosopher.exe 0";
time_t begin = time(NULL);
for (int i = 0; i < PEOPLE; i++) {
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
name[strlen(name) - 1] = i + '0';
CreateProcessA("philosopher.exe", name, NULL, NULL, FALSE, 0, NULL, NULL, &si, &hProcesses[i]);
}
for (int i = 0; i < PEOPLE; i++) {
WaitForSingleObject(hProcesses[i].hProcess, INFINITE);
CloseHandle(hProcesses[i].hThread);
CloseHandle(hProcesses[i].hProcess);
}
time_t end = time(NULL);
printf("\n\n\x1b[0mThey're now extremely fat and about to explode. It took them %llu seconds to eat with mutex's.", (end - begin));
}
int main() {
// used for the mutex part of this question
CHAR name[] = { "STICK_0" };
for (int i = 0; i < CHOPSTICKS; i++) {
name[strlen(name) - 1] = '0' + (i + 1);
InitializeCriticalSection(&chopsticks[i]);
chopsticksMutex[i] = CreateMutexA(NULL, FALSE, name);
}
criticalEat();
PAUSE;
mutexEat();
for (int i = 0; i < CHOPSTICKS; i++) {
DeleteCriticalSection(&chopsticks[i]);
if (chopsticksMutex[i]) { // preventing annoying warning
CloseHandle(chopsticksMutex[i]);
}
}
printf("\n\nI'm honestly surprised they made it. Why are we torturing philosophers?");
PAUSE;
return 0;
}
If I run this code, it will in a very technical sense work. However, the logged results show only green success logs, leading me to believe one of the lock checks is flawed. However, if I try to run the program in debug mode with breakpoints, and run it very slowly, red unsuccessful logs do appear. The same thing happens if I add a Sleep(1). Red logs appear. I believe red logs should appear regardless of these slowing measures, since 5 threads are trying to access 5 locks at the same time, each thread taking 2 locks for themselves.
As for the mutex part, here it is:
#include <Windows.h>
#include <stdio.h>
#define CHOPSTICKS 5
#define MIN 2
#define INVALID -1
#define EAT_AMOUNT 1000000
int main(int argc, char** argv) {
HANDLE chopsticksMutex[CHOPSTICKS];
int index[MIN] = { 0 };
int usage = 0;
BOOL usageFlag = FALSE;
CHAR name[] = { "STICK_0" };
for (int i = 0; i < CHOPSTICKS; i++) {
name[strlen(name) - 1] = '0' + (i + 1);
chopsticksMutex[i] = CreateMutexA(NULL, FALSE, name);
}
for (int i = 0; i < MIN; i++) {
index[i] = INVALID;
}
for (int i = 0; i < EAT_AMOUNT; i++) {
while (usage != MIN) {
for (int j = 0; j < CHOPSTICKS; j++) {
for (int k = 0; k < MIN && !usageFlag; k++) {
if (index[k] == j) {
usageFlag = TRUE;
}
}
if (!usageFlag) {
for (int k = 0; k < MIN && !usageFlag; k++) {
if (index[k] == INVALID) {
if (WaitForSingleObject(chopsticksMutex[j], 0) != WAIT_ABANDONED) {
index[k] = j;
usage++;
}
usageFlag = TRUE;
}
}
}
usageFlag = FALSE;
}
for (int j = 0; j < MIN; j++) {
if (index[j] != INVALID) {
ReleaseMutex(chopsticksMutex[index[j]]);
index[j] = INVALID;
}
}
if (usage != MIN) {
printf("\x1b[31m[%c-X]", argv[1][0] + 1); // CHOPSTICKS UNAVAILABLE
usage = 0;
}
}
printf("\x1b[32m[%c-%d]", argv[1][0], i + 1); // ATE SUCCESSFULLY
usage = 0;
}
return 0;
}
Now, from what I've been taught, Mutex locks, in general, are slower. But here again, there are no red logs indicating that there was a failed attempt to lock 2 locks, and the Mutex implementation is faster, even though it makes no sense.
Does what I'm saying even make any sense? In multi-threaded programming, should I expect this behaviour? I'm pretty sure I should expect a couple of red logs, without intentionally bottlenecking the program.
I am relatively new to C and I am trying to get my Bankers Algorithm to work below. The logic is solid, but I am getting compilation errors that I can't quite work out. The main one is dealing with my struct that holds all of the consumers data for the algorithm. It reads:
"error: invalid type argument of ‘->’ (have ‘struct threadData’)
t->allocation[t->customer_num][i] = t->allocation[t->customer_num][i] - t->requestOrRelease[i];"
That is one of many similar errors.
I know you may find more, since I am not done yet, so if you do, shout them out.
I have been working on this forever and I am stuck. Any help would be awesome. Keep in mind, I know there are things I may not be doing the best possible, but I want my code below to work and then I will optimize.
I know the code is lengthy, but I greatly appreciate any help. Thank you!
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
#define cust 5
#define reso 3
struct threadData
{
int available[reso];
int maximum[cust][reso];
int allocation[cust][reso];
int need[cust][reso];
int requestOrRelease[reso];
int customer_num;
} ;
void request_resources(struct threadData *t);
void release_resources(struct threadData *t);
int isSafeState(int work[],int need[][cust],int allocation[][cust]);
int sumVector(int input[]);
int sumRowCol(int input[][cust],int index,char c);
void fillRequestRelease(int * array,int max0,int max1,int max2);
int main(int argc, const char **argv)
{
int available[reso]; //number of resources available of each type
int maximum[cust][reso]; //maximum demand of each process
int allocation[cust][reso]; //number of resources of each type currently allocated
int need[cust][reso]; //remaining resouce needs of each process : maximum-allocation
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL); //Create mutex lock
bool end = false;
//===========================================
srand(time(NULL));
int i,j,r;
for(i = 0;i < argc;i++) //Initialize values in available array
{
r = atoi(argv[i]);
available[i] = r;
}
for(i = 0;i < cust;i++) //Initialize values in maximum array
{
for(j = 0;j < reso;j++)
{
r = rand()%8; //Random int between 0 and 7
reso[i][j] = r;
}
}
for(i = 0;i < cust;i++) //Initialize values in allocation/need arrays
{
for(j = 0;j < reso;j++)
{
allocation[i][j] = 0;
need[i][j] = 0;
}
}
//===========================================
threadData data;
data.available = available;
data.maximum = maximum;
data.allocation = allocation;
data.need = need;
data.requestOrRelease = requestOrRelease;
data.customer_num = 0;
pthread_t custRequest0,custRequest1,custRequest2,custRequest3,custRequest4;
pthread_t custRelease0,custRelease1,custRelease2,custRelease3,custRelease4;
while(true)
{
data.customer_num = 0;
fillRequestRelease(data.requestOrRelease,data.need[0][0],data.need[0][1],data.need[0][2]);
pthread_create(&custRequest0,NULL,(void *)data);
data.customer_num = 1;
fillRequestRelease(data.requestOrRelease,data.need[1][0],data.need[1][1],data.need[1][2]);
pthread_create(&custRequest1,NULL,(void *)data);
data.customer_num = 2;
fillRequestRelease(data.requestOrRelease,data.need[2][0],data.need[2][1],data.need[2][2]);
pthread_create(&custRequest2,NULL,(void *)data);
data.customer_num = 3;
fillRequestRelease(data.requestOrRelease,data.need[3][0],data.need[3][1],data.need[3][2]);
pthread_create(&custRequest3,NULL,(void *)data);
data.customer_num = 4;
fillRequestRelease(data.requestOrRelease,data.need[4][0],data.need[4][1],data.need[4][2]);
pthread_create(&custRequest4,NULL,(void *)data);
pthread_join(custRequest0,NULL);
pthread_join(custRequest1,NULL);
pthread_join(custRequest2,NULL);
pthread_join(custRequest3,NULL);
pthread_join(custRequest4,NULL);
data.customer_num = 0;
fillRequestRelease(data.requestOrRelease,data.allocation[0][0],data.allocation[0][1],data.allocation[0][2]);
pthread_create(&custRelease0,NULL,(void *)data);
data.customer_num = 1;
fillRequestRelease(data.requestOrRelease,data.allocation[1][0],data.allocation[1][1],data.allocation[1][2]);
pthread_create(&custRelease1,NULL,(void *)data);
data.customer_num = 2;
fillRequestRelease(data.requestOrRelease,data.allocation[2][0],data.need[2][1],data.need[2][2]);
pthread_create(&custRelease2,NULL,(void *)data);
data.customer_num = 3;
fillRequestRelease(data.requestOrRelease,data.allocation[3][0],data.allocation[3][1],data.allocation[3][2]);
pthread_create(&custRelease3,NULL,(void *)data);
data.customer_num = 4;
fillRequestRelease(data.requestOrRelease,data.allocation[4][0],data.allocation[4][1],data.allocation[4][2]);
pthread_create(&custRelease4,NULL,(void *)data);
pthread_join(custRelease0,NULL);
pthread_join(custRelease1,NULL);
pthread_join(custRelease2,NULL);
pthread_join(custRelease3,NULL);
pthread_join(custRelease4,NULL);
int nonZeroCount = 0;
for(i = 0;i < cust;i++)
{
for(j = 0;j < reso;j++)
{
if(need[i][j] > 0)
nonZeroCount++;
}
}
if(nonZeroCount == 0)
break;
}
printf("Program done!")
}
//Determines if system is in safe state
//Returns 0 if in safe state, else -1
int isSafeState(int work[],int need[][cust],int allocation[][cust]) //work = available
{
int i,j;
int temp1,temp2,trueCount,notSafeCount;
bool finish[sizeof(need)/sizeof(int)];
for (i = 0;i < sizeof(need)/sizeof(int);i++)
finish[i] = false;
trueCount = 0;
bool iexists = false;
while(true)
{
for(i = 0;i < sizeof(finish)/sizeof(int);i++)
{
temp1 = sumRowCol(need,i,'r');
temp2 = sumRowCol(work,0,'r');
if(finish[i] == false && (temp1 <= temp2))
{
finish[i] = true;
for(j = 0;j < reso;j++)
work[j] = work[j] + allocation[i][j];
trueCount++;
iexists = true;
}
}
if(trueCount == sizeof(finish)/sizeof(int))
return 0;
else if(iexists == false)
return -1;
}
}
// Returns sum of given vector
int sumVector(int input[])
{
int sum = 0;
int i;
for(i = 0;i < sizeof(input)/sizeof(int);i++)
sum += input[i];
return sum;
}
//Returns sum of given input array row/column
int sumRowCol(int input[][cust],int index,char c)
{
int sum = 0;
int i;
if(c == 'r')
{
for(i = 0;i < sizeof(input)/sizeof(int);i++)
sum += input[index][i];
}
else
{
for(i = 0;i < sizeof(input)/sizeof(int);i++)
sum += input[i][index];=
}
return sum;
}
void request_resources(struct threadData t)
{
int i,j,safeState,custNum;
int tempAvailable[reso];
int tempMaximum[cust][reso];
int tempAllocation[cust][reso];
int tempNeed[cust][reso];
int tempRequest[reso];
bool end = false;
if(t->requestOrRelease[0] == 0 && t->requestOrRelease[1] == 0 && t->requestOrRelease[2] == 0)
return;
while(true)
{
custNum = t->customer_num;
for(int i = 0;i < reso;i++)
{
if(t->requestOrRelease[i] > t->need[custNum][i])
{
printf("Error: Request is greater than need. Aborting request to bank.");
pthread_mutex_unlock(&mutex);
return;
}
}
int passCount;
while(true)
{
passCount = 0;
for(int i = 0;i < reso;i++)
{
if(t->requestOrRelease[i] > t->available[i])
{
passCount--;
while(true)
{
if(t->requestOrRelease[i] <= t->available[i])
break;
}
}
passCount++;
}
if(passCount = reso)
break;
}
pthread_mutex_lock(&mutex); //get mutex lock
//Filling temporary arrays with current data
//===========================================
for(i = 0;i < cust;i++)
{
for(j = 0;j < reso;j++)
{
tempMaximum[i][j] = t->maximum[i][j];
tempAllocation[i][j] = t->allocation[i][j];
tempNeed[i][j] = t->need[i][j];
}
tempAvailable[i] = t->available[i];
tempRequest[i] = t->requestOrRelease[i];
}
//===========================================
//"Pretend" to allocate resources
for(i = 0;i < reso;i++)
{
tempAvailable[i] = tempAvailable[i] - tempRequest[i];
tempAllocation[custNum][i] = tempAllocation[custNum][i] + tempRequest[i];
tempNeed[custNum][i] = tempNeed[custNum][i] - tempRequest[i];
}
safeState = isSafeState(tempAvailable,tempNeed,tempAllocation);
if(safeState == 0)
{
for(i = 0;i < reso;i++)
{
t->available[i] = t->available[i] - tempRequest[i];
t->allocation[custNum][i] = t->allocation[custNum][i] + tempRequest[i];
t->need[custNum][i] = t->need[custNum][i] - tempRequest[i];
}
pthread_mutex_unlock(&mutex); //release mutex lock
end = true;
}
if(end == true)
break;
pthread_mutex_unlock(&mutex); //release mutex lock
}
printf("Request resources granted to consumer: %d",custNum);
}
void release_resources(struct threadData t)
{
int i;
pthread_mutex_lock(&mutex); //get mutex lock
for(i = 0;i < reso;i++)
{
t->available[i] = t->available[i] + t->requestOrRelease[i];
t->allocation[t->customer_num][i] = t->allocation[t->customer_num][i] - t->requestOrRelease[i];
}
pthread_mutex_unlock(&mutex); //release mutex lock
}
//Generates random integers for request and release vectors
void fillRequestRelease(int * array,int max0,int max1,int max2)
{
srand(time(NULL));
int r;
r = rand()%(max0+1);
array[0] = r;
r = rand()%(max1+1);
array[1] = r;
r = rand()%(max2+1);
array[2] = r;
}
As far as I can see, in your request_resources() function, t is not a pointer variable. So, instead of
t->requestOrRelease[0]
you should be using
t.requestOrRelease[0]
and so on.
t is not a pointer, so you must write t.field instead of t->field.
The important clue in the error message is "(have ‘struct threadData’)".
This means you are using the pointer dereference operator -> on a struct, instead of on a struct pointer. Use the member dereference operator . instead.
Hello i have a little problem trying to "mix" two string arrays, i have searched about it but i have only found how to merge them or concatenate them, but thats not what i need.
i have two int arrays like this:
int no_items = 5;
int parent1[no_items], parent2[no_items];
if the arrays contains for example:
parent1[0] = 1;
parent1[1] = 2;
parent1[2] = 3;
parent1[3] = 4;
parent1[4] = 5;
and:
parent2[0] = 5;
parent2[1] = 1;
parent2[2] = 2;
parent2[3] = 3;
parent2[4] = 4;
given a "cross" point, for example 2:
parent1 should have his 2 first elements and the rest of parent2, and parent2 should have his first 2 elements and the rest of parent1. So the result should be:
parent1: 1,2 | 5,3,4
parent2: 5,1 | 2,3,4
where "|" is the break point index and the rest of elements should not be repeated.
How can i get this kind of mixing two int arrays? Thanks you!
at the moment i have this:
for(i = 0; i < cross_point; i++)
{
sprintf(buffer, "%d,", parent1[i]);
strcat(line1, buffer);
}
for(i = 0; i < cross_point; i++)
{
sprintf(buffer, "%d,", parent2[i]);
strcat(line2, buffer);
}
but i don´t know how to go further than the cross point.
int *find(int *begin, int *end, int value)
{
int *p = begin;
for ( ; p != end; ++p)
if (*p == value) break;
return p;
}
int i, j;
int output1[no_items] = {0};
int output2[no_items] = {0};
int crosspoint = 3;
memcpy(output1, parent1, crosspoint * sizeof(int));
for (i = crosspoint, j = 0; i < no_items; ++i)
{
while (find(output1, output1+i, parent2[j]) != output1+i) ++j;
output1[i] = parent2[j];
}
memcpy(output2, parent2, crosspoint * sizeof(int));
for (i = crosspoint, j = 0; i < no_items; ++i)
{
while (find(output2, output2+i, parent1[j]) != output2+i) ++j;
output2[i] = parent1[j];
}
memcpy(parent1, output1, sizeof(parent1));
memcpy(parent2, output2, sizeof(parent2));
Demo: http://ideone.com/xUt6nQ
something like this should do it if you aren't concerned about creating temporaries:
int no_items = 5;
int output1[no_items];
int output2[no_items];
for (int i = 0; i < no_items; i++){
if(i < crosspoint){
output1[i] = parent1[i];
output2[i] = parent2[i];
}else{
output1[i] = parent2[i];
output2[i] = parent1[i];
}
}
If you are concerned about temporaries you need to swap the values, the logic should be fairly similar to above.
int no_items = 5;
int temp = 0;
for (int i = 0; i < no_items; i++){
if(i < crosspoint){
/* don't need to do anything here */
}else{
temp = parent1[i];
parent1[i] = parent2[i];
parent2[i] = temp;
}
}
I'm writing a small poker application in C and I have counters for the number of flushes, straights, etc.
Main function:
int main(void) {
int i, j;
int numHands = 0;
int flushCount = 0;
int straightCount = 0;
int xOfAKindCount = 0;
int straightFlushCount = 0;
int fullHouseCount = 0;
int isTwoPairCount = 0;
card deck[DECKSZ] = {0};
card hand[HAND_SIZE] = {0};
stack deckStack = {0};
stack handStack = {0};
initDeck(deck);
shuffleDeck(deck);
reset(&deckStack);
for (i = 0; i < DECKSZ; i++) {
push(deck[i], &deckStack);
}
do {
reset(&handStack);
for (i = 0; i < HAND_SIZE; i++) {
push(pop(&deckStack), &handStack);
if (isEmpty(&deckStack)) {
reset(&handStack);
shuffleDeck(deck);
reset(&deckStack);
for (j = 0; j < DECKSZ; j++) {
push(deck[j], &deckStack);
}
}
hand[i] = handStack.s[i];
}
numHands += 1;
arrangeHand(hand);
flushCount += isFlush(hand);
straightCount += isStraight(hand);
xOfAKindCount += isXOfAKind(hand, 2, 0);
straightFlushCount += isStraightFlush(hand);
fullHouseCount += isFullHouse(hand);
isTwoPairCount += isTwoPair(hand);
printf("Flushes:%d Straights:%d SF's:%d Number of Hands:%d\r",
flushCount, straightCount, straightFlushCount, numHands);
} while (1);
printf("\n");
return EXIT_SUCCESS;
}
My function for the number of flushes:
int isFlush(card hand[]) {
int i, count = 0, result = 0;
for (i = 0; i < HAND_SIZE-1; i++) {
if (hand[i].suits != hand[i+1].suits) {
count++;
}
}
if (count == HAND_SIZE)
result = 1;
return result;
}
When I run the program, the code in the do...while loop is supposed to infinitely loop. For every hand popped off the stack, I want to calculate if it is a flush, straight, etc using functions like my isFlush() function here. The issue is these counters, such as numFlushes, remain at a value of zero. Does anybody know why the counters remain at zero, and how to fix that? Thanks!
The for loop in your isFlush function can at most increment the count HAND_SIZE-1 times. Since count starts at 0, it is never more than HAND_SIZE-1.
One option is to start your count at 1, since the first card always counts as 1 towards your flush no matter what suit it is. Anther option is to compare count to HAND_SIZE-1 in your if statement. Then you can actually return a non-zero value from isFlush.
BTW, if you step through the code with a debugger, you should easily see that your if condition is never met.
I am making a program in the C90 standard using GCC in Ubuntu 10.04, that randomly generates a hand of 5 card structs and calculates if the hand is a flush, straight, etc.
My function to calculate straights is:
int isStraight(card hand[]) {
int i, count = 1, result = 0;
for (i = 0; i < HAND_SIZE-1; i++) {
if (hand[i].pips == ((hand[i+1].pips) + 1)) {
count++;
}
}
if (count == HAND_SIZE)
result = 1;
return result;
}
My main function:
int main(void) {
int i, j;
int numHands = 0;
int flushCount = 0;
int straightCount = 0;
int xOfAKindCount = 0;
int straightFlushCount = 0;
int fullHouseCount = 0;
int isTwoPairCount = 0;
card deck[DECKSZ] = {0};
card hand[HAND_SIZE] = {0};
stack deckStack = {0};
stack handStack = {0};
initDeck(deck);
shuffleDeck(deck);
reset(&deckStack);
for (i = 0; i < DECKSZ; i++) {
push(deck[i], &deckStack);
}
do {
reset(&handStack);
for (i = 0; i < HAND_SIZE; i++) {
push(pop(&deckStack), &handStack);
if (isEmpty(&deckStack)) {
reset(&handStack);
shuffleDeck(deck);
reset(&deckStack);
for (j = 0; j < DECKSZ; j++) {
push(deck[j], &deckStack);
}
}
hand[i] = handStack.s[i];
}
numHands += 1;
arrangeHand(hand);
flushCount += isFlush(hand);
straightCount += isStraight(hand);
xOfAKindCount += isXOfAKind(hand, 2, 0);
straightFlushCount += isStraightFlush(hand);
fullHouseCount += isFullHouse(hand);
isTwoPairCount += isTwoPair(hand);
printf("Flushes:%d Straights:%d SF's:%d Number of Hands:%d\r",
flushCount, straightCount, straightFlushCount, numHands);
} while (1);
printf("\n");
return EXIT_SUCCESS;
}
My issue is my variable declared inside my function, result, is never set to 1 to indicate whether or not the hand is a straight, which therefore means my straightCount variable always remains at a value of zero. I do not have access to a debugger and in my mind the code I have makes sense. I'm new to programming in C, so if anybody could help me point out what is wrong with my function, I'd appreciate it. Thanks!
int isStraight(card hand[]) {
int step = 0;
for(int i = 1;i < HAND_SIZE; i++)
if(hand[i].pip != hand[i-1].pip+1)
/* Substitute step with i!=1 if over-edge invalid */
if(step || hand->pip != 1 || hand[i].pip != hand[i-1].pip+13-HAND_SIZE)
return 0;
else
step = 1;
return 1;
}
Right, after reading the code again, there are not enogh cards...
for (i = 0; i < HAND_SIZE-1; ++i)
Then you care counting pairs, not just individual cards, so
If (count == HAND_SIZE-1)
for (i = 0; i < HAND_SIZE-1; i++) { means that you are testing HAND_SIZE-1 pairs (which is correct), with i from from 0 to HAND_SIZE-2, so count will never be HAND_SIZE.
You just need to change your test to if (count == HAND_SIZE-1)
Assuming that (a) pip values are 1=Ace, 2=Deuce, ... and (b) the hand is sorted before being passed to the function, and (c) hands are exactly five cards, here's a quick one:
int isStraight(card hand[]) {
int i;
// Handle Broadway special case
if (hand[0].pips == 13 && hand[1].pips == 12 && hand[2].pips == 11 &&
hand[3].pips == 10 && hand[4].pips == 1) return 1;
// This will handle the rest
for (i = 0; i < (HAND_SIZE-1); i += 1) {
if (hand[i].pips != hand[i+1].pips) return 0;
}
return 1;
}
Also, I wouldn't use a structure for cards. Using a single integer is much faster and more versatile. Check out http://etceterology.com/blog/2013/5/23/representing-playing-cards-in-software