shampouya
asked on
Why isn't my scanf halting the execution of code in my C program?
I wrote the program below and started debugging. When I run the code, I expect the user to be prompted to enter an input once, but after the first prompt, there is an extra and redundant prompt in the subsequent cycles. It seems like scanf is not stopping the code from executing in order to give the user a change to enter an input. Why is that? How can I make sure that the user is asked to enter a value only once per cycle?
#include<stdio.h>
#include<stdlib.h>
int men_in_bathroom=0;
int women_in_bathroom=0;
int bathroom_capacity = 10;
int men_in_queue=0;
int women_in_queue=0;
int queue_capacity = 10;
int cycle=1;
char queueContents[1];
char eventInput;
void StatusCheck(){
printf("\nStatus of Bathroom:\nCycle: %d Women: %d Men: %d\n",cycle, women_in_bathroom, men_in_bathroom);
printf("Queue (last to first): ");
for (int i = 0; i < men_in_queue + women_in_queue; i++){
printf("%c ", queueContents[i]);
}
printf("\n");
}
void QueueReorganizer(){
}
void WomanWantsToEnter()
{
if (women_in_bathroom + men_in_bathroom >= bathroom_capacity){ //if the bathroom is at full capacity
if(men_in_queue + women_in_queue < queue_capacity){ //if the queue can accomodate more people
printf("The bathroom is full. One woman has been added to the queue.");
for (int i = 0; i < women_in_bathroom; i++){
if(queueContents[i] == NULL){
queueContents[i] = 'W';
women_in_queue++;
break;
}
}
StatusCheck();
}
else{ //if the queue is at full capacity
printf("Sorry, the bathroom and the queue are both full. No one can be added at this time.");
}
}
else if(men_in_bathroom != 0){ //if the bathroom can accomodate more people but there are men currently inside the bathroom
if(men_in_queue + women_in_queue < queue_capacity){ //if the queue can accomodate more people
printf("Men are currently inside the bathroom. One woman has been added to the queue.");
}
else{ //if the queue is at full capacity
printf("Men are currently inside the bathroom, and the queue is full. Cannot accomodate any women at the moment.");
}
}
else if(men_in_bathroom == 0){ //if the bathroom can accomodate more people and there are no men currently inside the bathroom
printf("A woman has entered the bathroom");
women_in_bathroom++;
StatusCheck();
cycle++;
}
}
void ManWantsToEnter()
{
if (women_in_bathroom + men_in_bathroom >= bathroom_capacity){ //if the bathroom is at full capacity
if(men_in_queue + women_in_queue < queue_capacity){ //if the queue can accomodate more people
printf("The bathroom is full. One man has been added to the queue.");
for (int i = 0; i < women_in_bathroom; i++){
if(queueContents[i] == NULL){
queueContents[i] = 'M';
men_in_queue++;
break;
}
}
StatusCheck();
}
else{ //if the queue is at full capacity
printf("Sorry, the bathroom and the queue are both full. No one can be added at this time.");
}
}
else if(women_in_bathroom != 0){ //if the bathroom can accomodate more people but there are women currently inside the bathroom
if(men_in_queue + women_in_queue < queue_capacity){ //if the queue can accomodate more people
printf("Women are currently inside the bathroom. One man has been added to the queue.");
}
else{ //if the queue is at full capacity
printf("Women are currently inside the bathroom, and the queue is full. Cannot accomodate any men at the moment.");
}
}
else if(women_in_bathroom == 0){ //if the bathroom can accomodate more people and there are no women currently inside the bathroom
printf("A man has entered the bathroom");
men_in_bathroom++;
StatusCheck();
cycle++;
}
}
void WomanLeaves()
{
if(women_in_bathroom == 0 )
{
printf("Invalid choice. There are already no women in the bathroom.");
}
else{
women_in_bathroom--;
for (int i = 10; i > 0; i--){
if(queueContents[i] == 'W'){
queueContents[i] = NULL;
break;
}
}
QueueReorganizer();
StatusCheck();
cycle++;
}
}
void ManLeaves()
{
if(men_in_bathroom == 0 )
{
printf("Invalid choice. There are already no women in the bathroom.");
}
else{
men_in_bathroom--;
for (int i = 10; i > 0; i--){
if(queueContents[i] == 'M'){
queueContents[i] = NULL;
break;
}
}
QueueReorganizer();
StatusCheck();
cycle++;
}
}
int main() {
while (cycle <= 20) {
printf("\nChoose one of the following events for cycle %d:\n", cycle);
printf("A) woman wants to enter\nB) man wants to enter\nC) woman leaves\nD) man leaves\n");
printf("Enter A,B,C or D here --> ");
scanf("%c", &eventInput);
if(eventInput == 'A'){
WomanWantsToEnter();
}
else if(eventInput == 'B'){
ManWantsToEnter();
}
else if(eventInput == 'C'){
WomanLeaves();
}
else if(eventInput == 'D'){
ManLeaves();
}
cycle++;
}
return 0;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Why isn't my scanf halting the execution of codeyou may consider to using the following code instead of scanf call
while ((eventInput = getch()) != -1)
{
if (!strchr("ABCDQabcdq", eventInput))
{
continue;
}
eventInput = toupper(eventInput);
printf("%c\n", eventInput);
break;
}
the getch gets one character from stdin but no echo. that allows to ignore invalid input and also to convert to upper case.
(note, i added also Q and q to the valid characters what allows the user to quit).
i added an else branch to handle the 'Q':
else if (eventInput == 'D') {
...
}
else {
break; // break from while loop
}
note, the 'break' wouldn't work if you have changed to switch-case control as evilrix suggested since the break would end the case but not the loop. you would need to break the loop by making the loop condition wrong, for example by setting the 'cycle' counter to maximum.
case 'Q':
cycle = 99;
break;
}
if the getch was not declared yet, you may include conio.h and ctype.h. the latter also provides a prototype of the toupper function. strchr is used to check whether the input is valid and is available thru <string.h>.
for windows platform you would either use _getch instead of getch or add
#ifdef WIN32
#define getch _getch
#endif
somewhere above main function.
one additional remark: your program currently compiles with c++ compiler but not with an ansi c compiler. that is due to for statements like 'for (int i = 0; ....' where you define variable i in the middle of a code block. in ansi c all variables must be defined at top of a block.
Sara
i dectected a few minor bugs:
if you test your code you will see that cycle was incremented twice for most cases. remove the cycle++ in the main function or (alternatively) in all the handler functions.
some printouts where stating woman where man is required.
Sara
if you test your code you will see that cycle was incremented twice for most cases. remove the cycle++ in the main function or (alternatively) in all the handler functions.
some printouts where stating woman where man is required.
Sara
Just note that the getch function isn't part of the C standard.
You can (sort of) fix this by placing the following line after your scanf:
Open in new window
This basically seeks forward through the stdin file stream until it hits EOF, which is the same as saying that it has skipped through all the unwanted characters. It's a bit of a work around rather than a solution because the problem here is that scanf is just a wholly unsafe function to use. In fact the C programming language doesn't provide any nice standard way of getting clean user input and you nearly always have to resort to using platform specific functions to do things properly.
Meanwhile, I note you are using lots of if/then/else constructs for your input. You realise you can "switch" on a char, right?
Open in new window