How to repeat a process in a while until enter is pressed? - c

I need to repeat a process and I'm using a while. I need to do antoher process when enter key is pressed and I'm using if(getchar()). The problem is that the while "pauses" when it gets to the if because it's checking if getchar() it's true. I need to know how to keep looping the while whithout it stopping to check if there's an enter.
I'm making a game in which you have 1 minute to guess as much names as you can. So the purpose of the while() is to countdown from 60 to 0 seconds (clears the screen and prints the new second and the name you're actually guessing every second). So I want it to keep running the while() so the timer keeps running, but if enter is pressed it only changes the guessed name to a new name and the timer keeps running. (I don't know if I was clear but this is the idea)
//program in c
while(//specific condition)
{
/*- here goes the code for a timer that every second it clears the
- terminal and prints the next number (in seconds).
-
-
-*/
if(getchar()) //the current program stops here and keeps running the loop
//until enter is pressed
{
//second process
}
}
I expect the while to keep looping until there's an enter. When that happens I want it to enter the if, exit the if and keep looping.

char buffer[100];
while (fgets(buffer, sizeof(buffer), stdin))
{
if (strlen(buffer) == 1)
break;
if (sscanf(buffer, "%f", &f) == 1)
{
total += f;
printf("Enter another number: ");
}
}

if you have conio.h available in your environment you can use kbhit
while(//specific condition)
{
/*--process to do
-
-
-
-*/
if(kbhit())
{
if (getchar() == 0x0d)
{
break;
}
}
//second process
}
In this loop, the second process will run without checking the enter key and only exit if enter key is pressed.

You cannot use if(getchar()=='\n')
so the program runs until an enter key is pressed
because buffer value of '\n' will be present and it'll alter the next iteration

char a;
printf("Enter charecter or press enter to exit:");
scanf("%c",&a);
while(1)
{
//process 1 loop
if (a == '\n')
{
// process 2 here, if process two has loop make it's own loop here
printf("we are in process 2\n");
break;
}
getchar();
printf("Enter charecter or press enter to exit:");
scanf("%c",&a);
}
You did't give enough code to understand what input stream you are working with but something like this will do it, if it's file stream or string do it accordingly by replacing scanf with fgets, or file stream inputs like fscanf or fread.

Related

Printf waiting for enter

int kr=0;
int ss =0;
while ((kr=getchar()) != EOF){
if(kr != '\n')
{
ss++;
}
printf("%d\n",ss);
}
With this code , printf is waiting until i press enter then printing all the sequential ss values at the same time like in this
. Can somebody explain this behavior ?
printf is not waiting it is getchar instead. getchar uses a buffer behind the scene. When that buffer is empty, getchar will read 1 line from stdin and then return the first caracter. If it is not empty, it will return the next caracter from the buffer immediatly.
That means that the getchar will wait the first time you call it. And thus your printf is never executed until you press enter

Make default statement not exit (C)

I am a beginner in C programming and I'm trying to do basic stuff. I'm trying to create a simple menu using a switch statement like this:
int disp(){
int check;
while(check!=1){
int choose;
printf("1 \n");
printf("5quit\n");
scanf("%d", &choose);
switch(choose)
{
case 1:func1();
break;
case 5: check = 1;
break;
default:
printf("wrong input");
}
return 0;
}
}
However, when either default or case 1 happen, I want to make it still loop the menu until a good input is made. For example, if I enter random stuff like "asdf", the program should say "wrong input" and then display the menu again and wait for user input. And if user enters "1", the program will run func1 and then go back to the menu and wait for the user to input a choice.
Currently, when a wrong input happens it just shuts down the program instead of displaying the menu again, and I don't know how to solve that.
Your return 0 statement is inside of your while loop. Move it down one line, outside of the loop.
This is one reason why proper indentation is important.
At this point, entering in non-numeric input results in an infinite loop because scanf isn't reading in anything. To remedy this, you call getchar in a loop after calling scanf to flush the buffer:
int c;
scanf(" %d", &choose);
while ((c=getchar()) != EOF && c != '\n');
This is correct and close to what you want
// Use a proper formatting standard to improve readability
int disp() {
int check = 0; // Initialize the loop variable
while (check != 1) {
int choose;
printf("1 \n");
printf("5quit\n");
scanf("%d\n", &choose); // Ask the scanf to swallow the newline
switch(choose) {
case 1:
func1();
break;
case 5:
check = 1;
break;
default:
printf("wrong input");
}
}
return 0; // Pull the statement out of the loop
}
EDIT: Since you are providing invalid input intentionally, it's better to check the return value of scanf to avoid errors.

Problems with restarting program

I've been introduced to C this year as part of my degree, during which I have to write simple programs and test them to be idiot-proof by running them over and over again, putting nonsense variables in, etc. and I had an idea to write a program with the ability to restart itself without having to run the program again.
I've tried writing a program to perform this function (which turned out to be harder than I first thought) and I now have it working, albeit using a goto function that are frowned upon. Now the only problem I have is a while loop to check for nonsense input, that seems determined to run at least once ignoring a prompt for a valid input.
Please could someone give me an idea why this is happening? (My compiler is Dev-C++ 4.9.9.2)
int main (void)
{
mainprogram:
printf("\nPROGRAM START\n");
//code copied from an exam, to check that the program performs a function
//when ran through again
int i,j,k;
printf("Please enter 7:");
scanf("%d",&i);
printf("Please enter 4:");
scanf("%d",&j);
printf("Please enter 0:");
scanf("%d",&k);
//this is to check that the program will take input when it is restarted
do {
switch (i%j) {
case 3:
i--;
k*=i;
break;
case 2:
i--;
k+=i;
default:
i--;
k++;
break;
}
printf("i is %d k is %d\n",i,k);
} while (i>0);
//end of copied code
char prompt='y';
printf("\nRestart program?");
scanf("%c",&prompt);
while (prompt != 'y' && prompt != 'Y' && prompt != 'n' && prompt != 'N')
{
//this is the problem section, when entering nonsense input, the error messages
//display twice before pausing for input, and when restarted, the program does
//run again but displays the error messages once before pausing for input
printf("\nERROR: INVALID INPUT");
printf("\n\nRestart program?");
prompt='y';
scanf("%c",&prompt);
}
if (prompt == 'y' || prompt == 'Y')
{
goto mainprogram;
}
//
return 0;
}
while(1){ //parent
printf("\n\nRun program?");
scanf("%c",&prompt);
if (prompt == 'n' || prompt == `N`)
{
printf("\nEXITINT")
return 0;
}
int i,j,k;
printf("Please enter 7:");
scanf("%d",&i);
printf("Please enter 4:");
scanf("%d",&j);
printf("Please enter 0:");
scanf("%d",&k);
switch (i%j)
{
case 3:
i--;
k*=i;
break;
case 2:
i--;
k+=i;
break;
default:
i--;
k++;
break;
}
printf("i is %d k is %d\n",i,k);
} //end while parent
//end of copied code
There are a couple of ways one could restart a program, or more generally loop over some code. Of course, all of that can be done with gotos, but that makes the code hard to understand, so C has equivalent structures for dealing with the most common patterns:
execute code if and as long as condition holds
while (condition)
{
/* code */
}
This means before executing the code, the condition is checked. If the condition holds (its value is non-zero), the code is executed and then looped back to the top. This is equivalent to:
top_of_while:
if (!condition)
goto done;
/* code */
goto top_of_while:
done:
execute code and redo while condition holds
do
{
/* code */
} while (condition)
This means execute code first and then check for a condition. If the condition holds, executed the code again. This is equivalent to:
top_of_do_while:
/* code */
if (condition)
goto top_of_do_while;
iteration
for (initialization; condition; iteration)
{
/* code */
}
This is a kind of while loop that happens a lot, in which there is an initialization, followed by a while loop, which on the bottom changes a variable to form some sort of iteration. This is equivalent to:
initialization;
while (condition)
{
/* code */
iteration;
}
To restart a program, most likely you want the do-while loop, since for sure you know that the program has to execute once. However, by properly initialization the condition variable of a while loop, you can also ensure that the loop is always entered the first time. It's a matter of style and your liking.
Where to actually use goto
Many people would tell you to never use goto. This roots from the fact that overuse of goto had led to a great number of overly complicated programs, the so-called spaghetti code. The reason is that it's hard to build a mental model of a program where the execution can jump around to any other part.
However, gotos are actually very useful in C, without which error-handling becomes a huge pain in the ... neck. This useful usage of goto is for handling errors and cleanup, which are always in the bottom of the function. An example would be:
int *read_nums(int n)
{
int *array, i;
array = malloc(n * sizeof *array);
if (array == NULL)
goto exit_no_mem;
for (i = 0; i < n; ++i)
if (scanf("%d", &array[i]) != 1)
goto exit_bad_input;
return array;
exit_bad_input:
free(array);
exit_no_mem:
return NULL;
}
This way, the code is not cluttered (much) with error handling and cleanup is done very nicely based on how far the function has executed.
I just reformatted your code and indeed # herohuyongtao is right, the break; for case 2 has moved at the end of default which is not useful there.
But there's something really shocking in your code, is that you use a goto. Just remember that rule: WHENEVER YOU USE GOTO, THERE'S A BETTER WAY TO DO IT!
#include <stdio.h>
short int read_input (void) {
printf("\nPROGRAM START\n");
//code copied from an exam, to check that the program performs a function
//when ran through again
int i,j,k;
printf("Please enter 7:");
scanf("%d",&i);
printf("Please enter 4:");
scanf("%d",&j);
printf("Please enter 0:");
scanf("%d",&k);
//this is to check that the program will take input when it is restarted
do {
switch (i%j) {
case 3:
i--;
k*=i;
break;
case 2:
i--;
k+=i;
break; // break at the right spot
default:
i--;
k++;
}
printf("i is %d k is %d\n",i,k);
} while (i>0);
// getchar(); // could be inserted here (discards one char)
// fflush(stdin); // could also do the job (discards all remaining chars in buffer)
char prompt='y';
// here the design choice is to let the user input whatever
// and not updated the output until the right character is given
// which will hide how many wrong chars has been previously in the buffer.
printf("\nRestart program? ");
do {
prompt = getchar();
} while (prompt != 'y' && prompt != 'Y' && prompt != 'n' && prompt != 'N');
if (prompt == 'y' || prompt == 'Y')
return 1;
return 0;
}
int main() {
while (read_input() == 1);
return 0;
}
Now that the code is clean, for your exact problem, you will get into a carriage return problem. Basically, what you do is get input until \n is hit, but when you hit carriage return, you actually send CR + LF. So there's one character that never gets read in the input buffer, that you need to discard.
So you should first read that SO question that sums up very well your problem, and you can either:
add a lone getchar(); just after your //end of copied code comment,
or a fflush(stdin) can do the job (cf the SO Question to learn more about it) but has been designed about flushing output buffers, not input ones,
add a fseek(stdin,0,SEEK_END); which is a bit dirty (and non-portable) but works,
or change your conditions and your use of scanf to take into account that you're actually having more chars in the buffer.
In the code I gave you, I chose the most simplistic solution, which is to discard any wrong input without printing anything.

Program ends with exit code 0 immediately - but it shouldn't get there without input

Build succeeds. If I open the output window, it reads:
Program ended with exit code: 0
But my program is such that this shouldn't be possible, without first having taken user input, done some stuff, and taken another user input, all in int main().
The first thing int main() does is loop through taking input for p, until the input is one (of two) desired options. So there's no way it should be able to exit immediately - it initialises p=0 and doesn't exit a while loop until p is 1 or 2.
Is there some hidden error that has allowed the build to succeed without it actually.. succeeding?
int main(){
//vars
while (TRUE){
//play computer or human?
while (!(p == 1 || p == 2)) {
printf("Single player or two player? (1/2): ");
scanf("%d", &p);
}
if (p==1) {
//play computer
}
else {
//snip
}
printf("%s won the game! Play again?", winner);
scanf("%s", playagain);
if (strncmp(playagain,"no",2)==0){
break;
}
}
return 0;
}
Print out what uppercase TRUE is defined as. I have seen some ambitious but inexperienced folks do weird things with it. You might not even be getting into your main while loop.
printf("TRUE is %d\n",TRUE);
If this is nonzero, then your problem is elsewhere.

Clear the input buffer

I am trying to implement the press any key to continue function by using kbhit, however, after the user presses a key for example a, it will appear in the input buffer the next time I ask the user to input a value. How do you clear the input buffer?
my code for press any button to continue is below.
void
press_any_key(void)
{
int b=0;
while (b==0)
{
b=kbhit();
}
}
I'm trying to implement the press any key to continue function by using kbhit taking this statement as a need to wait for user keyboard input to continue the program execution the below code does the job,
void press_any_key(void)
{
while(1)
{
if(kbhit())
ch = getch();
printf("You passed %c\n", ch);
}
}
Note: the above snippet doesn't try to clear the input buffer. However kbhit() is non standard instead the right way is to read a character from stdin is using fgetc.

Resources