Algorithm in C - who is the winner team - c

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.

Related

Kruskal alghoritm - working but difficult

I was working on Kruskal algorithm that will read input and based on this information it will find the shortest path between every two nodes.
Let me explain:
There are numbers on the input, for example:
7 6 1 5
1 7 20
7 2 5
2 3 9
4 2 4
5 2 7
6 5 3
On the first line there are 4 numbers = number of nodes, number of edges, beginning node (where to start), end node (where to end).
On the rest of lines are 3 numbers = one node(lets say x), second node(y), length between them.
The input will give me shortest path between the start and end node.
In this example case it would be number 32.
I have a fully working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct edge{
int goal, length;
struct edge *p_next;
} EDGE;
typedef struct node{
int name;
EDGE *p_edges, *last;
} NODE;
int helper;
int getDist(int size, NODE *nodes[size+1], int from, int act, int goal)
{
EDGE *p_act;
for(p_act = nodes[act]->p_edges; p_act != 0; p_act = p_act->p_next)
{
if (p_act->goal == goal)
{
return p_act->length;
}
if (p_act->goal != from)
{
helper = getDist(size, nodes, act, p_act->goal, goal);
}
if (helper != 0)
{
return helper + p_act->length;
}
}
return 0;
}
int main()
{
int numV, numH, start, goal, i, length, a, b;
EDGE *p_newEdge, *p_newEdge2;
scanf("%d %d %d %d", &numV , &numH, &start, &goal);
NODE *nodes [numV+1];
for(i = 0; i <= numV; i++)
{
nodes[i] = (NODE*)malloc(sizeof(NODE));
}
for(i = 0; i < numH; i++)
{
scanf("%d %d %d",&a,&b,&length);
p_newEdge = (EDGE*)malloc(sizeof(EDGE));
p_newEdge->length = length;
p_newEdge->goal = b;
p_newEdge2 = (EDGE*)malloc(sizeof(EDGE));
p_newEdge2->length = length;
p_newEdge2->goal = a;
if (nodes[a]->p_edges == 0)
{
nodes[a]->p_edges = p_newEdge;
nodes[a]->last = p_newEdge;
}
else if (nodes[a]->p_edges != 0)
{
nodes[a]->last->p_next = p_newEdge;
nodes[a]->last = nodes[a]->last->p_next;
}
if (nodes[b]->p_edges != 0)
{
nodes[b]->last->p_next = p_newEdge2;
nodes[b]->last = nodes[b]->last->p_next;
}
else if (nodes[b]->p_edges == 0)
{
nodes[b]->p_edges = p_newEdge2;
nodes[b]->last = p_newEdge2;
}
}
printf("%d\n",getDist(numV ,nodes, 0, start, goal));
return 0;
}
But my professor told me that it is very long and I should make it more simple (this was my third attempt and for my professor it is still too long and "complex").
I have no idea how to make it more simple.
Can someone help me with this?

Finding the largest difference between multiple sets of numbers

I've attempted to create a program which processes a list of outcomes for football games while also processing the results.
The way my program works is you input the number of matches that have been played then you list the results of each match.
Each row in the list has the form of HOME_TEAM_ID | AWAY_TEAM_ID | HOME_TEAM_GOALS | AWAY_TEAM_GOALS
So for example if the user entered (the first line is the number of matches):
2
0 1 5 0
2 3 0 5
My program will then output a row containing: team id, win ratio, win ratio on home games, average point difference in won games ( -1 in case of no home games.) The largest (in terms of point difference) win in a single game and then the ID of that opponent.
0 1.000 1.000 5.000
1 0.000 -1 -1
2 0.000 0.000 -1
3 1.000 -1 5.000
I've completed most of my program but I'm having difficulty implementing one last part. I want to find out the the largest (in terms of goal difference) win in a single game for each team and then the ID of the opponent which they had their largest win in terms of goal difference. (If there aren't any wins then it should simply output -1.)
My first thought was to just loop through the array, setting a variable to the largest win. For each element, check if its point difference is higher than the variable. If it is, replace the variable with the current element's difference.
However I'm getting a compiler error.
1079.c: In function 'main':
1079.c:153:11: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
maximum = resultTable[0];
^
1079.c:157:24: warning: comparison between pointer and integer
if (resultTable[n] > maximum)
^
1079.c:159:17: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
maximum = resultTable[n];
Any help about how to find the largest average point difference, over multiple games, against one particular opponent, would be greatly appreciated.
Here's my full code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//My local variables
int n;
int i;
int input = 0;
int TEAM_ID = 0, NUM_OF_GAMES = 1, WINS = 3, HOME_GAMES = 2, HOME_WINS = 4, HOME_WIN_RATIO = 6, WIN_RATIO = 5, GD = 7;
int homeTeamID, awayTeamID, homeGoals, awayGoals;
static const int NUM_COLUMNS = 10;
static const int NUM_TEAMS = 30;
double resultTable[30][10];
int BEST_WIN_DIFF = 8, BEST_WIN_OPPONENT = 9;
void takeInput();
void sortData();
void printer();
//This method takes the input from the user for homeTeamID, awayTeamID,homeGoals and awayGoals
void takeInput()
{
scanf("%d", &input);
for (n = 0; n < input; n++) {
scanf("%d %d %d %d", &homeTeamID, &awayTeamID, &homeGoals, &awayGoals);
//calls the sortData function
sortData();
}
}
//The table fnction which uses the resultTable variable to put the infomation in a table
void sortData()
{
int goalDiff = homeGoals - awayGoals;
//This will increment the home games,home game counter and the away game
resultTable[homeTeamID][NUM_OF_GAMES]++;
resultTable[homeTeamID][HOME_GAMES]++;
resultTable[awayTeamID][NUM_OF_GAMES]++;
//If the awaygoals is larger than the homegoals then it will set the winner in the results table
if (homeGoals < awayGoals) {
resultTable[awayTeamID][WINS]++; //increment away wins
}
//If the homegoals is larger than the awaygoals then it will set the winner in the results table
else if (homeGoals > awayGoals) {
resultTable[homeTeamID][WINS]++;
resultTable[homeTeamID][HOME_WINS]++; //increment home wins
}
//The goal difference for home and away
resultTable[homeTeamID][GD] = resultTable[homeTeamID][GD] + (homeGoals - awayGoals);
resultTable[awayTeamID][GD] = resultTable[awayTeamID][GD] + (awayGoals - homeGoals);
if (goalDiff > resultTable[homeTeamID][BEST_WIN_DIFF]) {
resultTable[homeTeamID][BEST_WIN_DIFF] = goalDiff;
resultTable[homeTeamID][BEST_WIN_OPPONENT] = awayTeamID;
}
if (-goalDiff > resultTable[awayTeamID][BEST_WIN_DIFF]) {
resultTable[awayTeamID][BEST_WIN_DIFF] = -goalDiff;
resultTable[awayTeamID][BEST_WIN_OPPONENT] = homeTeamID;
}
}
//Calculates the win ratio
void winRatio()
{
for (n = 0; n < 30; n++) {
//This if determines the home win ratio
if (resultTable[n][HOME_GAMES] > 0) {
resultTable[n][HOME_WIN_RATIO] = resultTable[n][HOME_WINS]
/ resultTable[n][HOME_GAMES];
}
if (resultTable[n][NUM_OF_GAMES] > 0) {
resultTable[n][GD] = resultTable[n][GD] / resultTable[n][NUM_OF_GAMES];
}
//This if determines the win ratio
if (resultTable[n][NUM_OF_GAMES] > 0) {
resultTable[n][WIN_RATIO] = resultTable[n][WINS]
/ resultTable[n][NUM_OF_GAMES];
}
}
}
//This method prints out the results
void printer()
{
for (n = 0; n < NUM_TEAMS; n++) {
if (resultTable[n][NUM_OF_GAMES] != 0) {
if (resultTable[n][HOME_WIN_RATIO] == -1) {
printf("%d %.3f %.0f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
else {
printf("%d %.3f %.3f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
}
}
}
//My main function which will be used to call everyother function
int main(void)
{
for (n = 0; n < NUM_TEAMS; n++) {
for (i = 1; i < NUM_COLUMNS; i++) {
resultTable[n][i] = 0;
}
resultTable[n][TEAM_ID] = n;
resultTable[n][HOME_WIN_RATIO] = -1;
resultTable[n][BEST_WIN_DIFF] = -HUGE_VAL;
}
int maximum, location = 1;
for (n = 0; n < 30; n++)
scanf("%d", &resultTable[n]);
maximum = resultTable[0];
for (n = 0; n < 30; n++)
{
if (resultTable[n] > maximum)
{
maximum = resultTable[n];
location = n+1;
}
}
printf("Maximum element is present at location %d and it's value is %d.\n", location, maximum);
return 0;
takeInput();
winRatio();
printer();
return EXIT_SUCCESS;
}
You can't get the information you want (the largest etcetera) from the data you enter into the array because you throw away information you need later to calculate this.
You need to store the input data unchanged into the array, then you can calculate anything from it you want.
In particular, with
//The goal difference for home and away
resultTable[homeTeamID][GD] = resultTable[homeTeamID][GD] + (homeGoals - awayGoals);
resultTable[awayTeamID][GD] = resultTable[awayTeamID][GD] + (awayGoals - homeGoals);
you remember the difference, but that is not enough to calculate the largest win in a single game for each team. Instead, store both homeGoals and awayGoalsand then later calculate the information you want.
Include math.h for HUGE_VAL.
#include <math.h>
Add two extra columns.
static const int NUM_COLUMNS = 10;
static const int NUM_TEAMS = 30;
double resultTable[NUM_TEAMS][NUM_COLUMNS];
int BEST_WIN_DIFF = 8, BEST_WIN_OPPONENT = 9;
Add them to the table function.
void table()
{
int i;
for (n = 0; n < NUM_TEAMS; n++) {
for (i = 1; i < NUM_COLUMNS; i++) {
resultTable[n][i] = 0;
}
resultTable[n][TEAM_ID] = n;
resultTable[n][HOME_WIN_RATIO] = -1;
resultTable[n][BEST_WIN_DIFF] = -HUGE_VAL;
}
}
Add the new code to the end of sortData.
void sortData()
{
...
int goalDiff = homeGoals - awayGoals;
if (goalDiff > resultTable[homeTeamID][BEST_WIN_DIFF]) {
resultTable[homeTeamID][BEST_WIN_DIFF] = goalDiff;
resultTable[homeTeamID][BEST_WIN_OPPONENT] = awayTeamID;
}
if (-goalDiff > resultTable[awayTeamID][BEST_WIN_DIFF]) {
resultTable[awayTeamID][BEST_WIN_DIFF] = -goalDiff;
resultTable[awayTeamID][BEST_WIN_OPPONENT] = homeTeamID;
}
}
and finally update printer to include the extra columns.
void printer()
{
for (n = 0; n < NUM_TEAMS; n++) {
if (resultTable[n][NUM_OF_GAMES] != 0) {
if (resultTable[n][HOME_WIN_RATIO] == -1) {
printf("%d %.3f %.0f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
else {
printf("%d %.3f %.3f %.3f %.0f %.0f\n", n,
resultTable[n][WIN_RATIO],
resultTable[n][HOME_WIN_RATIO],
resultTable[n][GD],
resultTable[n][BEST_WIN_DIFF],
resultTable[n][BEST_WIN_OPPONENT]);
}
}
}
}
double resultTable[30][10];
resultTable[x] is a pointer to double [10]
resultTable[x] is a pointer of double *
resultTable[x][y] is double
That is the reason you get the warning
You have more problems in your code
you scanf integers, but pass pointer to double etc etc.

C: Converting int to String [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In my code, I'd like to use string that denotes Will, Bob, Billy, Ryan or Ed instead of int. Specifically, using N strings S[1],S[2]...S[N] where S[I] the names above.
And also, input N is limited as following: (1 ≤ N ≤ 100,000)
#include <stdio.h>
int main(void)
{
int input_num=0;
int isWill = 0;
int isBob = 0;
int isBilly = 0;
int isRyan = 0;
int isEd = 0;
int n=0;
scanf("%d", input_num);
printf("%d", input_num);
for(n;n<input_num;n++)
{
char tmp[100,000];
scanf("%s", tmp);
if(tmp == "Will")
isWill = 1;
else if(tmp == "Bob")
isBob = 1;
else if(tmp == "Billy")
isBlue = 1;
else if(tmp == "Ryan")
isRyan = 1;
else if(tmp == "Ed")
isEd = 1;
}
//end of input
if(isWill == 0)
printf("Will\n");
if(isBob == 0)
printf("Bob\n");
if(isBilly == 0)
printf("Billy\n");
if(isRyan == 0)
printf("Ryan\n");
if(isEd == 0)
printf("Ed\n");
return 0;
}
To compare strings, you need to use the strcmp library function, which returns 0 if the two argument strings are equal:
if ( strcmp( tmp, "Will" ) == 0 )
// tmp contains the string "Will"
If you want an array of strings, you can do it one of two ways. You can declare a 2d array, where the first dimension is tne number of names, and the second dimension is the max length of a name:
char names[NUMBER_OF_NAMES][MAX_NAME_LENGTH+1];
To copy a string, use strcmp:
strcmp( names[0], "Will" );
strcmp( names[1], "Bob" );
// etc.
Or, you can declare a 1D array, where each element is a pointer to a string:
char *names[NUMBER_OF_NAMES];
names[0] = "Will";
names[1] = "Bob";
Note that you're assigning a pointer value to names[i]; you're not copying the string contents to names[i].
Finally, C doesn't recognize integer literals like 100,000; you'll want to declare your tmp buffer as
char tmp[100000];
although that's somewhat large for a string buffer.
Several things not quite as i would write them.
I had some minutes to spare and wrote a compiling example.
Maybe your problems can be solved by this.
char * colortext[] =
{
"unknown",
"white",
"black",
"blue",
"red",
"yellow"
};
typedef enum color {
unknown = 0,
white,
black,
blue,
red,
yellow
};
typedef struct
{
int number;
char name[200];
color team;
}Player;
typedef struct
{
char * name;
color team;
}Autoassign;
Autoassign autoassign[] =
{
{"Will", white},
{"Bob", black},
{"Billy", blue},
{"Ryan", red},
{"Ed", yellow}
};
int autoassignLength = sizeof(autoassign) / sizeof(autoassign[0]);
int Player_print(Player * player)
{
int e = 0;
printf("\n");
printf("Player %i Profile:\n", player->number);
printf("Name: '%s'\n", player->name);
printf("Team: '%s'\n", colortext[player->team]);
printf("\n");
return e;
}
int Player_scan(Player * player, int number)
{
int e = 0;
int i;
printf("Input Player Name: ");
scanf("%s", player->name);
player->number = number;
player->team = unknown;
for(i = 0; i < autoassignLength; ++i)
{
if(0 == strcmp(player->name,autoassign[i].name))
{
player->team = autoassign[i].team;
break;
}
}
return e;
}
int main(int argc, char ** argv)
{
int i;
int input_num, n;
Player players[10];
printf("How many Players? ");
scanf("%d", &input_num);
for(n = 0; n < input_num ; n++)
{
Player_scan(&players[n], n+1);
}
for(n = 0; n < input_num ; n++)
{
Player_print(&players[n]);
}
return 0;
}
If you want to make compare strings that's not the way to go.
Use string.h library to be able to use the function strcmp .
To use this functions type strcmp(string1, string2)
Just remember that strcmp will return 0 if the strings are equal.
So what you want to do is use if(!strcmp("Will", tmp)) to enter the if when the strings are the same.
You also need to change char tmp[100,000] to char tmp[100000], for this is the supported format in C.
Hope this helps.

User defined values aren't honored in program at later points

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.

Switch-Case statement seems to freeze my loops

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.

Resources