Here are a few loops from my program I'm working on. The program seems to stop advancing after printf("TEST2");. Everything checks out at a glance. Is there something I'm missing?
I'm expecting the loop to repeat after setting the values in the switch-statement. I know it's getting through it at least once.
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
char *names[] = { "Denise", "Inja", "Jane", "Karen", "Maggie", "Margaret", "MJ", "Queen", "Sherri", NULL }; //ptr for names, 9 nurses
const char days[5][10] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
int randomNurse();
#define total_nurses 9 //number of nurses on staff
#define days_in_week 5 //number of work days in a week
int main() {
srand(time(NULL));
int day, pos, candidate, i, j;
int slackers[4] = { 1, 1, 1, 1 }; //array that holds the selections for who isn't working
char **name_ptr = names;
/*0 = Denise, 1 = Inja, 2 = Jane, 3 = Karen, 4 = Maggie, 5 = Margaret, 6 = MJ, 7 = Queen, 8 = Sherri*/
int avail_nurses[total_nurses] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; //holds the status of each nurse, 0 = unavailable, 1 = available
/*prints names */
int temp_counter = 1; //counter
while (*name_ptr) {
printf("%i) %s\n", temp_counter, *name_ptr);
name_ptr++;
temp_counter++;
}
/*this assumes that no more than FOUR nurses will be away on any given week*/
printf("\nEnter numbers that correspond to the nurses who won't be available for the week.\nType up to four numbers, each separated by a space.\n");
printf("When you are done, press \"Enter\".\n");
printf("If less than four nurses will be on leave, type a \"0\" in place of a selection.\n");
printf("Example: 1 2 5 0\n\n\n");
/*week selection of unavailable nurses*/
do {
printf("Who won't be here? ");
} while (scanf("%i %i %i %i", &slackers[0], &slackers[1], &slackers[2], &slackers[3]) != 4);
/*checks the selections made, and sets the available nurses to the correct value, zero if they are slacking||vacationing*/
for (int n = 0; n < 4; n++) {
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker] = -1;
}
/*-----WEEKLY_ASSIGNMENT-----*/
int pos_per_day[days_in_week] = { 5, 9, 9, 8, 5 }; //number of nurses needed each day
int selection[days_in_week][total_nurses]; //the selected nurses per day
for (i = 0; i < days_in_week; i++) {
for (j = 0; j < total_nurses; j++) {
selection[i][j] = -1; //initialize to -1 which means no nurse is selected
}
}
//fill all the days of week
for (day = 0; day < days_in_week; day++) {
for (pos = 0; pos < pos_per_day[day]; pos++) { //for every position needed that day
do {
candidate = randomNurse();
} while (!avail_nurses[candidate]); //looks for available nurses (phrasing)
avail_nurses[candidate] = 0; //change nurses status to not available
selection[day][pos] = candidate; //fill the output array with appropriate nurse
}
for (i = 0; i < total_nurses; i++) {
avail_nurses[i] = 1; //initialize the nurses status for next day use
}
for (int n = 0; n < 4; n++) { //make sure we shame the slackers...
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker] = -1;
}
}
/*-----PRINTS SCHEDULE FOR WEEK-----*/
for (i = 0; i < days_in_week; i++) {
printf("%-10s: ", days[i]);
for (j = 0; j < total_nurses; j++) {
if (selection[i][j] != -1)
printf("%-10s ", names[selection[i][j]]);
}
printf("\n");
}
return 0;
}
/*function to generate random nurse*/
int randomNurse() {
return rand() % 9; //random number 0-8, to pick nurse
}
You have Undefined Behaviour. The second value in pos_per_day is 9, which is outside the bounds of the select array. Subtracting one from each value in that array may be enough to fix it.
Other bad problems:
you need to validate the input data after scanf.
the switch statement is completely unnecessary. Replace it by a calculation.
don't use UPPER CASE for variables. By convention, that's only for defined constants.
don't hard code numbers like 5 and 9. Replace them by DEFINED CONSTANTS.
You must learn how to debug simple programs like this, using the debugger available to you.
Related
I need to store data from a tournament. I need to know how many teams will play(n) and the number of games they will play (n!). Then, the team's names and their results. Something like this:
Input:
3 6
TeamX
TeamY
TeamZ
TeamX 0 - TeamY 3
TeamX 1 - TeamZ 0
TeamY 1 - TeamX 0
TeamY 0 - TeamZ 0
TeamZ 0 - TeamX 0
TeamZ 3 - TeamY 1
The output will be something like:
This winner is TeamY, with 7 point(s)
Won 2 game(s), tied 1 game(s) e lost 1 game(s)
Scored 5 goal(s) e suffered 3 goal(s)
EDIT2:
THIS is what I have until now. But it won't work at the scanf.... I can't type the team's names after the number of teams and games. Can you run it and try to understand?
Guide: I have game and team structs, first I add team names to theTeams array of structs, then I add the games to the games array of structs. Then, if/else blocks to do the maths of wins, losses, etc and finally see and printf the winner.
#include <stdio.h>
#include <string.h>
struct game {
const char *teamA;
int scoreA;
const char *teamB;
int scoreB;
};
struct team {
const char *teamA;
int score;
int wins;
int losses;
int ties;
int scored;
int suff;
};
struct team team_new(const char *teamA, int score, int wins, int losses, int ties, int scored, int suff)
{
struct team t;
t.teamA = strdup(teamA);
t.score = score;
t.wins = wins;
t.losses = losses;
t.ties = ties;
t.scored = scored;
t.suff = suff;
return t;
};
struct game game_new(const char *teamA, int scoreA, const char *teamB, int scoreB)
{
struct game g;
g.teamA = strdup(teamA);
g.scoreA = scoreA;
g.teamB = strdup(teamB);
g.scoreB = scoreB;
return g;
};
int main(void)
{
int i, j, teams, nrgames, biggestScore, whichTeam;
scanf("Teams and number of games %d %d", &teams, &nrgames);
//add team names to theTeamss struct
struct team theTeams[teams];
size_t num_teams = 0;
for (i = 0; i < teams; ++i)
{
char teamA[20];
if (scanf("%s", teamA) != 1)
exit(0);
theTeams[++num_teams] = team_new(teamA, 0, 0, 0, 0, 0, 0);
}
struct game games[nrgames]; //add games
size_t num_games = 0;
for (i = 0; i < sizeof games / sizeof *games; ++i)
{
char teamA[20], teamB[20];
int scoreA, scoreB;
if (scanf(" %s %d - %s %d", teamA, &scoreA, teamB, &scoreB) != 4)
exit(0);
games[++num_games] = game_new(teamA, scoreA, teamB, scoreB);
}
//run through games[] to change values of theTeams[] scores
//games - A against B
for (i = 0; i < sizeof games / sizeof *games; ++i)
{
for (j = 0; j < sizeof theTeams / sizeof *theTeams; ++j)
{
if ((games[i].teamA == theTeams[j].teamA)) //team(A)
{
//if A wins
if(games[i].scoreA > games[i].scoreB)
{
theTeams[j].score += 3;
theTeams[j].wins += 1;
theTeams[j].scored = games[i].scoreA;
}
//if A loses
else if (games[i].scoreA < games[i].scoreB)
{
theTeams[j].score += 0;
theTeams[j].losses += 1;
theTeams[j].suff = games[i].scoreB;
}
else //tied
{
theTeams[j].score += 1;
theTeams[j].ties += 1;
theTeams[j].suff = games[i].scoreA;
}
}
if ((games[i].teamB == theTeams[j].teamA))//team(B)
{
//if B wins
if(games[i].scoreB > games[i].scoreA)
{
theTeams[j].score += 3;
theTeams[j].wins += 1;
theTeams[j].scored = games[i].scoreB;
}
//if B loses
else if (games[i].scoreB < games[i].scoreA)
{
theTeams[j].score += 0;
theTeams[j].losses += 1;
theTeams[j].suff = games[i].scoreA;
}
else //tied
{
theTeams[j].score += 1;
theTeams[j].ties += 1;
theTeams[j].suff = games[i].scoreB;
}
}
}
}
//accessing to the winner team
biggestScore = theTeams[0].score;
whichTeam = 0;
for (i = 0; i < sizeof theTeams / sizeof *theTeams; ++i){
if (theTeams[i].score > biggestScore){
biggestScore = theTeams[i].score;
whichTeam = i;
}
}
//output
printf("\n This winner is %s, with %d point(s), Won %d game(s), tied %d game(s) and lost %d game(s), Scored %d goal(s) e suffered %d goal(s)\n", theTeams[whichTeam].teamA, theTeams[whichTeam].score, theTeams[whichTeam].wins, theTeams[whichTeam].losses, theTeams[whichTeam].ties, theTeams[whichTeam].scored, theTeams[whichTeam].suff);
return 0;
}
There are no "problems" with C language and strings; you can do whatever you want. It's just a bit more responsibility than in other languages.
You seem to need an array of structures, yes. I would recommend modelling it as just an array of games played, where each game records the teams that took part, and their scores. No need to first record a list of "available" teams, it's easier to just extract that from the game data afterwards.
struct game {
const char *teamA;
int scoreA;
const char *teamB;
int scoreB;
};
struct game game_new(const char *teamA, int scoreA, const char *teamB, int scoreB)
{
struct game g;
g.teamA = strdup(teamA);
g.scoreA = scoreA;
g.teamB = strdup(teamB);
g.scoreB = scoreB;
return g;
}
and then in the man program:
int main(void)
{
struct game games[100];
size_t num_games = 0;
for (size_t i = 0; i < sizeof games / sizeof *games; ++i)
{
char teamA[100], teamB[100];
int scoreA, scoreB;
if (scanf(" %s %d - %s %d", teamA, &scoreA, teamB, &scoreB) != 4)
break;
games[++num_games] = game_new(teamA, scoreA, teamB, scoreB);
}
}
C like all programming languages is only as good as the plan you have laid out to model the data
For this, an array of arrays that stores the data can work.
Might want to also consider a database for relationships based on teams. Then you can also add metadata and the like (for example, timestamps). Though its only good if you don't mind externalising application beyond C.
I am working on a game of Yahtzee and one part of the game is the user can choose which dice out of 5 they wish to re-roll. I don't really know how to approach this besides writing a ton of if if-else statements, but there has to be a more efficient way to re-roll the specific die/ dice. I wrote out a snippet of what I am trying to accomplish, its not exactly like this in my actual code, but hopefully it is enough to answer the question :)
#include<stdio.h>
int main(void)
{
int die1 = 0, die2 = 0, die3 = 0, die4 = 0, die5 = 0;
int *ptr_die1 = &die1, *ptr_die2 = &die2, *ptr_die3 = &die3, *ptr_die4 = &die4, *ptr_die5 = &die5;
int choice = 0;
int die[5] = { 0 };
for (int i = 0; i < 5; i++)
{
die[i] = rand() % 6 + 1;
}
printf("Die[1] = %d\n", die[0]);
printf("Die[2] = %d\n", die[1]);
printf("Die[3] = %d\n", die[2]);
printf("Die[4] = %d\n", die[3]);
printf("Die[5] = %d\n", die[4]);
choice = printf("Please select which die to reroll\n");
scanf("%d", &choice);
printf("%d\n", choice);
for (int i = 0; i < 5; i++)
{
die[choice-1] = rand() % 6 + 1;
}
printf("Die[1] = %d\n", die[0]);
printf("Die[2] = %d\n", die[1]);
printf("Die[3] = %d\n", die[2]);
printf("Die[4] = %d\n", die[3]);
printf("Die[5] = %d\n", die[4]);
return 0;
}
after this I am really lost on how to change the die because the user could want to change just 1, or all 5 or any combination in between...
You have way too many variables that are not really needed.
int main(int argc, char **argv)
{
int i;
int choice;
int dices[5];
srand(time(NULL));
while(1){
for (i = 0; i < 5; i++)
dices[i] = rand() % 6 + 1;
choice = printf("Please select which die to reroll (or enter 0 to quit)");
scanf("%d", &choice);
if (choice == 0) // end the game
break;
if (choice < 1 || choice > 5 ){ // make sure that input is valid
fprintf(stderr, "error, input should be between 1 to 5 (inclusive)\n");
return -1;
}
printf("dice shows: %d", dices[choice-1]);
}
return 0;
}
You need to ask the user for the ending it, e.g. "Enter 0 to end the game". Otherwise it would be an infinite loop.
You could have the user input a comma-separatd list of die, instead of a single integer, which it looks like you're doing now. Then just parse the input, check that you have between 1 and 5 valid integers less than 6, and index into each die.
Or you could do like kaylum suggested and loop until the user inputs a special string indicating they're done, or prompt for 1, 2, ... 5 and ask for a yes or no answer to each.
Just use an array of int values to represent the set of dice:
#define DICE_COUNT 6
void rollDice(int* diceArray, size_t diceIndex) {
assert( 0 <= diceIndex && diceIndex < DICE_COUNT );
diceArray[ diceIndex ] = rand() % 6 + 1;
}
int main(int argc, char* argv[]) {
// Seed the RNG:
srand( (unsigned)time(&t) );
int dice[DICE_COUNT];
for(size_t i = 0; i < DICE_COUNT; i++) {
rollDice( dice, i );
}
while( true ) {
printf("Please select which die to reroll. Enter -2 to quit. (%d to %d inclusive)", 1, DICE_COUNT);
int selection = -1;
scanf("%d", &selection);
if( selection == -2 ) break;
if( 1 <= selection && selection <= DICE_COUNT ) {
selection--; // convert from 1-6 to 0-5.
rollDice( dice, selection );
}
}
return EXIT_SUCCESS;
}
I don't see any if..else statements in your code above. I will say, in this chunk of code:
for (int i = 0; i < 5; i++)
{
die[choice-1] = rand() % 6 + 1;
}
You don't need the for loop. You are not using the index, and rand() should work the first time through. I know rand() isn't the best written function, but if you seed it first, it should give you a pseudo-random number.
#include <time.h>
...
/* initialize random seed: */
srand ( time(NULL) );
...
die[choice-1] = rand() % 6 + 1;
Hope this was helpful, if you are still even working on that project!
Let's say I have an array with [2,4,6,7, 7, 4,4]
I want a program that can iterate through, and then print out something like this:
Value: Count:
2 1
4 3
6 1
7 2
I don't want it to print out ex 4 three times.
What I got so far:
for (int i = 0; i < numberOfInts; i++)
{
dub[i] = 0;
for (int y = 0; y < numberOfInts; y++)
{
if (enarray[i] == enarray[y])
{
dub[i]++;
}
}
}
So basically I check each element in the array against all the elements, and for every duplicate I add one to the index in the new array dub[].
So if I ran this code with the example array above, and then printed it out with I'd get something like this:
1,3,1,2,2,3,3. These are pretty confusing numbers, because I don't really know which numbers these belong to. Especially when I'll randomize the numbers in the array. And then I have to remove numbers so I only have one of each. Anyone got a better solution?
You can iterate through the array while checking for each element if it has been repeated in which case you increment it's count (the loop checks only values a head saving processing time). This let you accomplish what you needed without creating any extra buffer array or structure.
The bool 'bl' prevents repeated printing
int main() {
int arr[] = { 2, 4, 6, 7, 7, 4, 4 };
int size = (sizeof(arr) / sizeof(int));
printf("Value:\tCount\n");
for (int i = 0; i < size; i++) {
int count = 0, bl = 1; //or 'true' for print
//check elements ahead and increment count if repeated value is found
for (int j = i; j < size; j++) {
if (arr[i] == arr[j]) {
count++;
}
}
//check if it has been printed already
for (int j = i-1; j >= 0; j--) {
if (arr[i] == arr[j]) {
bl = 0; //print 'false'
}
}
if (bl) { printf("%d\t\t%d\n", arr[i], count); }
}
return 0;
}
Given the char array only contains '0' to '9', you may utilize a trivial lookup table like this:
#include <stdio.h>
typedef struct
{
char c;
int num;
} TSet;
TSet my_set[] =
{
{ '0', 0 },
{ '1', 0 },
{ '2', 0 },
{ '3', 0 },
{ '4', 0 },
{ '5', 0 },
{ '6', 0 },
{ '7', 0 },
{ '8', 0 },
{ '9', 0 },
};
int main()
{
char a[] = {'2','4','6','7','7', '4','4'};
int i;
for( i = 0; i < sizeof(a) / sizeof(char); i++ )
{
my_set[ a[i] - '0' ].num++;
}
printf( "%-10s%-10s\n", "Value:", "Count:" );
for( i = 0; i < sizeof(my_set) / sizeof(TSet); i++ )
{
if( my_set[i].num != 0 )
{
printf( "%-10c%-10d\n", my_set[i].c, my_set[i].num );
}
}
}
Output:
Value: Count:
2 1
4 3
6 1
7 2
I don't understand the complexity here. I think there are two approaches that are performant and easy to implement:
Counting Sort
requires int array of size of the biggest element in your array
overall complexity O(n + m) where m is the biggest element in your array
qsort and enumeration
qsort works in O(n * log(n)) and gives you a sorted array
once the array is sorted, you can simply iterate over it and count
overall complexity O(n*log(n))
sort the array, typically by using the qsort() function
iterate over all elements counting successively equal elements and if the next different element is detected print the count of the former
This works on any number of different elements. Also no second array is needed.
You have the general idea. In addition to your input array, I would suggest three more arrays:
a used array that keeps track of which entries in the input have already been counted.
a value array that keeps track of the distinct numbers in the input array.
a count array that keeps track of how many times a number appears.
For example, after processing the 2 and the 4 in the input array, the array contents would be
input[] = { 2,4,6,7,7,4,4 };
used[] = { 1,1,0,0,0,1,1 }; // all of the 2's and 4's have been used
value[] = { 2,4 }; // unique numbers found so far are 2 and 4
count[] = { 1,3 }; // one '2' and three '4's
Put a print statement in the outer for loop to print value and repetition
for (int i = 0; i < numberOfInts; i++)
{
dub[i] = 0;
for (int y = 0; y < numberOfInts; y++)
{
if (enarray[i] == enarray[y])
{
dub[i]++;
}
}
printf("%d%d",enarray[i], dub[i]);
}
What you're asking for is strange. Normally, I'd create a struct with 2 members, like 'number' and 'count'. But let's try exactly what you're asking for (unidimensional array with each number followed by it's count):
int
i,
numberOfInts = 7,
numberOfDubs = 0,
enarray[7] = {2,4,6,7,7,4,4},
dub[14]; // sizeof(enrray) * 2 => maximum number of dubs (if there are no duplicates)
// For every number on enarray
for(i = 0; i < numberOfInts; i++)
{
int jump = 0;
// Check if we have already counted it
// Only check against pairs: Odds are the dub counter
for(int d = 0; d < numberOfDubs && !jump; d += 2)
{
if(dub[d] == enarray[i])
{
jump = 1;
}
}
// If not found, count it
if(!jump)
{
// Assign the new number
dub[numberOfDubs] = enarray[i];
dub[numberOfDubs + 1] = 1;
// We can begin from 'i + 1'
for(int y = i + 1; y < numberOfInts; y++)
{
if(enarray[i] == enarray[y])
{
dub[numberOfDubs + 1]++;
}
}
// Increment dub's counter by 2: number and it's counter
numberOfDubs += 2;
}
}
// Show results
for(i = 0; i < numberOfDubs; i += 2)
{
printf("%d repeated %d time%s\n", dub[i], dub[i + 1], (dub[i + 1] == 1 ? "" : "s"));
}
I have a doozy of a conundrum. Conceptually, I think I know what I need to do. Code-wise, I'm not so sure.
I want to go through the AVAIL_NURSE_W1[] array (which holds the number that corresponds to which nurse is available on Week_1), generate a random number to decide on a slot in that array (if the slot holds a zero value, then generate another random number and try again), take that number (which is a nurse), and put it into the MONDAY[] array.
Related-code:
int main() {
int randomNurse();
srand(time_t(NULL));
/*0 = Denise, 1 = Inja, 2 = Jane, 3 = Karen, 4 = Maggie, 5 = Margaret, 6 = MJ, 7 = Queen, 8 = Sherri*/
/*-----WEEKLY_ASSIGNMENT-----*/
int AVAIL_NURSE_W1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //holds the numerical values of the nurses that CAN work each week
/*scans in first week*/
for (int column = 0; column < 4; column++) {
for (int num = 0; num < 9; num++) {
if (AVAIL_NURSE_W1[num] == select[0][column])
AVAIL_NURSE_W1[num] = 0;
}
}
/*-----MONDAY-----*/
int MONDAY[5]; //days of the week, number of jobs on a given day
for (int e = 0; e < 5; e++) { //loop for positions on monday
while (MONDAY[e] == 0) {
int temp_assign = randomNurse();
if (AVAIL_NURSE_W1[temp_assign] != 0) { //if the nurse IS available...
MONDAY[e] = AVAIL_NURSE_W1[temp_assign];
AVAIL_NURSE_W1[temp_assign] = 0; //we don't want to repeat nurses
} else {
continue;
}
}
}
return 0;
}
/*function to generate random nurse*/
int randomNurse() {
return rand() % 9; //random number 0-8, to pick nurse
}
My Question:
How do I take care of getting the available nurses from the AVAIL_NURSE_W1[] array, generate a random number which decides which slot to take a value from, takes that value, stores it in a new array MONDAY[]; if the value in the AVAIL_NURSE_W1[] array is a ZERO, then repeat the above process until it's selected a non-zero value; after I've selected a value, I will change the selected value to a ZERO and then go through the loop again.
Desired result
The MONDAY[] array should contain five non-zero integers. No repeats.
So far, it seems the while loop condition never changes.
Let me know if there is anything else that needs saying. I hope I've given enough information.
Here you go :
#include<stdio.h>
#include <stdlib.h>
const char names[9][10] = {"Denise", "Inja", "Jane", "Karen", "Maggie", "Margaret", "MJ", "Queen", "Sherri"};
const char days[5][10] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
int randomNurse();
int main() {
srand(time(NULL));
int day, e, pos, candidate;
int i,j;
/*0 = Denise, 1 = Inja, 2 = Jane, 3 = Karen, 4 = Maggie, 5 = Margaret, 6 = MJ, 7 = Queen, 8 = Sherri*/
/*-----WEEKLY_ASSIGNMENT-----*/
int AVAIL_NURSE_W1[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; //holds the status of each nurse, 1:available 0:unavailable
int pos_per_day[5] = {2, 5, 7, 4, 3}; // number of needed nurses per day, Monday:2 nurses, tuesday: 5 nurses ...
int select[5][9]; // the selected nurses per day
for(i=0; i<5; i++)
for(j=0; j<9;j++) select[i][j] = -1; // initialize to -1 which means no nurse is selected
// fill all the days of week
for (day = 0; day<5; day++) // for every day
{
for(pos = 0; pos<pos_per_day[day]; pos++ ) // for every position needed that day
{
do
{
candidate = randomNurse();
}while(!AVAIL_NURSE_W1[candidate]); // look for available nurse
AVAIL_NURSE_W1[candidate] = 0; // change her status to not available
select[day][pos] = candidate; // fill the output array with appropriate nurse
}
for(i=0; i< 9; i++)
{
AVAIL_NURSE_W1[i] = 1; // initialize the nurses status for next day use
}
}
for(i=0; i<5; i++) // display
{
printf("%-10s: ", days[i]);
for(j=0; j<9;j++)
{
if(select[i][j] != -1) printf("%-10s ", names[select[i][j]]);
}
printf("\n");
}
return 0;
}
/*function to generate random nurse*/
int randomNurse() {
return rand() % 9; //random number 0-8, to pick nurse
}
In the code below, the user is supposed to be able to define what nurses won't be available for work that week. The user has a list of the names, and they are supposed to type a number that corresponds to the name. Once that value is stored into the slackers[4] array, it should be using those user supplied values to remove those nurses from being selected come making selections. It doesn't seem to be honoring those selected values, despite avail_nurses[9] having the correct values at any point in time (I tested using printf statements).
Everything seems to be in good shape except that essential piece of the puzzle. I would appreciate some constructive critique and useful suggestions. If you can avoid it, don't write the code for me--I gotta learn somehow. Thanks in advance!
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
char *names[] = { "Denise", "Inja", "Jane", "Karen", "Maggie", "Margaret", "MJ", "Queen", "Sherri", NULL }; //ptr for names, 9 nurses
/*0 = Denise, 1 = Inja, 2 = Jane, 3 = Karen, 4 = Maggie, 5 = Margaret, 6 = MJ, 7 = Queen, 8 = Sherri*/
const char days[5][10] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
int randomNurse();
#define total_nurses 9 //number of nurses on staff
#define days_in_week 5 //number of work days in a week
int main() {
srand(time(NULL));
int day, pos, rand_num, i, j;
int slackers[4] = { 0, 0, 0, 0 }; //array that holds the selections for who isn't working
int avail_nurses[total_nurses] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; //holds the status of each nurse, 0 = unavailable, 1 = available
/*this allows the user to repeat the program easily! flag determines if we run the program multiple times*/
while (char flag = 'y') {
/*prints names */
int temp_counter = 1; //counter
char **name_ptr = names;
while (*name_ptr) {
printf("%i) %s\n", temp_counter, *name_ptr);
name_ptr++;
temp_counter++;
}
/*this assumes that no more than FOUR nurses will be away on any given week*/
printf("\nEnter numbers that correspond to the nurses who won't be available for the week.\nType up to four numbers, each separated by a space.\n");
printf("When you are done, press \"Enter\".\n");
printf("If less than four nurses will be on leave, type a \"0\" in place of a selection.\n");
printf("Example: 1 2 5 0\n\n\n");
/*week selection of unavailable nurses*/
do {
printf("Who won't be here? ");
} while (scanf("%i %i %i %i", &slackers[0], &slackers[1], &slackers[2], &slackers[3]) != 4);
/*checks the selections made, and sets the available nurses to the correct value, zero if they are slacking||vacationing*/
for (int n = 0; n < 4; n++) {
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker - 1] = -1;
}
/*-----WEEKLY_ASSIGNMENT-----*/
int pos_per_day[days_in_week] = { 5, 9, 9, 8, 5 }; //number of nurses needed each day
int selection[days_in_week][total_nurses]; //the selected nurses per day
for (i = 0; i < days_in_week; i++) {
for (j = 0; j < total_nurses; j++) {
selection[i][j] = -1; //initialize to -1 which means no nurse is selected
}
}
//fill all the days of week
for (day = 0; day < days_in_week; day++) {
for (pos = 0; pos < pos_per_day[day]; pos++) { //for every position needed that day
do {
rand_num = randomNurse();
} while (!avail_nurses[rand_num]); //looks for available nurses (phrasing)
avail_nurses[rand_num] = 0; //change nurses status to not available
selection[day][pos] = rand_num; //fill the output array with appropriate nurse
}
for (i = 0; i < total_nurses; i++) {
avail_nurses[i] = 1; //initialize the nurses status for next day use
}
for (int n = 0; n < 4; n++) { //make sure we shame the slackers...
int slacker = slackers[n];
if (slacker >= 1 && slacker <= 9)
avail_nurses[slacker - 1] = -1;
}
/*DEBUGGING PRINTFs
printf("\n\nSELECTION:\n");
for (int x = 0; x < days_in_week; x++) {
for (int y = 0; y < total_nurses; y++) {
printf("%i\t", selection[x][y]);
}
printf("\n");
}*/
}
printf("\n");
/*-----PRINTS SCHEDULE FOR WEEK-----*/
for (i = 0; i < days_in_week; i++) {
printf("%-10s: ", days[i]);
for (j = 0; j < total_nurses; j++) {
if (selection[i][j] != -1)
printf("%-10s ", names[selection[i][j]]);
}
printf("\n");
}
fflush(stdin);
/*asks user if they want the program to run again*/
printf("\n\nDo you want to run the program again? (y/n) ");
scanf("%c", &flag);
if (flag == 'n' || flag == 'N') {
printf("\n");
break;
}
else {
printf("\n\n\n");
continue;
}
}
return 0;
}
/*function to generate random nurse*/
int randomNurse() {
return rand() % 9; //random number 0-8, to pick nurse
}
Your avail_nurses array uses the value 1 to indicate a nurse that's available, the value 0 to indicate a nurse that's not available as that nurse has already been assigned, and -1 to indicate a nurse that's not available because that nurse is a slacker. You then test whether or not a nurse is available with !avail_nurses[rand_num]. This statement is true if avail_nurses[rand_num] is 0 and is false if it's any other value. The means when avail_nurses[rand_num] is -1 it will exit the loop just like it does when it's 1.
To fix this bug either change the test to avail_nurses[rand_num] <= 0 or use only 0 to indicate unavailable nurses regardless of the reason why.