I'm trying to write a program that lets the user insert integer values into an array until they enter a specific key to stop, say ENTER, or X.
int array_numb[100];
char quit = 'x';
printf("Enter as many values into the array as you want, pressing x will end the loop\n");
while(1==1){
int i = 0;
scanf("%i",&array_numb[i]);
i++;
array_numb[i] = quit;
}
I know it's wrong but this is my thought process. Any ideas? thanks for the help
Enter as many values into the array as you want while having int array_numb[100];, at some point you will be in trouble. What if the user enters more than 100 numbers before entring the sentinel value? You'll be overruning the allocated memory, isn't it?
You should check the return value of scanf() to ensure proper input. A mismatch in the supplied format specifier and the type of input will cause scanf() to fail. Check the man page for details.
You need to have a break statement inside while(1) loop to break out. Otherwise, you need to have a conditional statement in the controlling expression for while() loop to terminate the loop.
Note: IMHO, the best way to stop scanning user input is to comapre the return value of scanf() against EOF, which can be produced by pressing CTRL+D on linux and CTRL+Z in windows.
You can check this answer for your reference.
The same thing can be achieved as shown below:
scanf() can fail and check the return value. When a character is scanned scanf() fails
int i=0;
printf("Enter as many values into the array as you want, pressing x will end the loop\n");
while(i<100 && scanf("%d",&array_numb[i])==1)
{
i++;
}
scanf, with %i, will fail to scan a number when invalid data, such as a character is inserted and will return 0(in your case) if it fails.
Just check the return value of scanf. If it is zero, use
if(getchar()=='x') //or if(getchar()==quit)
break;
Note: Clear/flush the standard input stream(stdin) using
int c;
while((c=getchar())!='\n' && c!=EOF);
after the loop as well as after the break; .
You could learn something and use signals:
http://man7.org/linux/man-pages/man7/signal.7.html
Register SIGINT, override it, let it check which key was pressed, then let it change a variable. In your loop check if this variable is 0 or 1.
Signals have top priority, signal code will be executed no matter the loop.
Example: http://www.thegeekstuff.com/2012/03/catch-signals-sample-c-code/
It's overkill for this case but a fun thing to know. Signals are the way how an OS is managing events, like process kills, keyboard input etc. Be warned, how to use this is OS specific and has not much to do with C itself.
Related
I just wanted to ask what the importance of using getch() is, especially in this array/for-loop example that our professor showed us:
int i;
char pw[7], ch;
printf ("\npw: ");
for (i=0; i<7; i++) {
ch = getch();
pw[i] = ch;
printf ("%c", ch);
}
I tried removing the ch = getch() line and what happened when I ran the program was that the loop went on forever.
Why does that happen?
I only understand that getch() is used at the end of a program to not show a character on the screen (from online definitions).
getch() reads a character from the keyboard without echoing it.
so your program is reading a character from the keybord (user input). and storing it in ch variable, then saving it in the string array pw[], at the end echoing it using printf("%c");
by removing ch = getch();. your program stops reading from keyboard. and fills the pw[] with the same value of (uninitialized ) ch exactly 7 times, and then exit loop.
according to what you posted, you program hangs elsewhere, where you are testing the validity of the password.
If you comment out getch line it runs and ends, it does not loop forever, you must have removed more to change it into a loop forever. To answer your initial question [getch] gets a char and then the program displays it, that's all.
Getch() - Reads a single character from STDIN, if none exists, waits for it!
In your example, Getch() plays a central role, reading the user input (given 7 characters).
if you remove this statement, not only you leave int ch uninitialized (with no valid value),
but the loop wont wait for anything (as getch() won't wait).
Sometimes, especially when learning c++, running a simple program from Visual Studio (or whatever IDE you use)...
running the program is very short, and you cant see the output!
so one adds getch(); at the end, just to tell the program to wait for any character, or put differently, leave the window open and wait for my key-press.
I have some experience with the c programming but sometimes the author of some books just pose such strange syntactical question which we will never use in actual programming and similar to that I stuck on one such question though the answer is given but I am not able to understand the answer.Here is the code below
int main
{
int i;
for(;scanf("%d",&i);printf("%d",i)){
;
}
}
The question is how many times this for loop will run and the answer given is indefinite
Can anyone explain how the loop will get executed
scanf returns number of elements successfully read and in this case it will be 1 if it reads a integer and keeps printing it.
Let's say you pass a character here then scanf() fails and exits from a for loop
Scanf will return the no of successful input get. If you give the input correctly then the condition will be true so it keep on running as indefinite.
To make the condition false you can give the input other than the integer value. That time scanf will return zero. So the loop will end.
Here, indefinite means that it is cannot be defined(unknown), it does not mean infinite (just to clear things out). Because, here the no of times the loop is run is dependent on the input given. If a correct input is given, which is an integer, the loop keeps running. If a wrong input is given, that is a non integer, the control jumps out of the loop. So you cant have a single answer for all scenarios, hence it is indefinite.
No. This is not an infinite for loop.
As per the syntax of for loop, from section 6.8.5.3 of the n1256 TC3 C99
for ( clause-1 ; expression-2 ; expression-3 ) statement
behaves as follows: The expression expression-2 is the controlling expression that is
evaluated before each execution of the loop body....
In your case, expression-2 is scanf("%d",&i), and the return value of scanf() will be considered for evaluation of expression-2.
As per the man page of scanf()
Return Value
... return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.
So, in your case,
till time scanf() is success, it will number of input items
successfully matched, which is 1 and a TRUE value, for loop
will continue execution.
if the scanf() fails [example: input char value], the return
value of scanf() will be 0 [matching failure] and the loop will
terminate.
After accept answer
Yes this very well may be an infinite loop.
scanf() returns the number of successfully scanned fields (0 or 1 ) here or EOF on IO error or end-of-file.
The only way to exit the loop is to enter a non-numeric input like "xyz".
Should user close stdin, scanf() will return EOF. EOF is a negative value (not 0). So the loop will continue calling scanf(), continue receiving EOF until the program is killed.
#include <stdio.h>
int main(void) {
int i;
for (; scanf("%d", &i); printf("%d", i)) {
;
}
return 0;
}
I've got a program here which contains a do-while loop within a specified void method. I'm trying to exit the loop within the function, so that the do-while loop actually works as it is supposed to. Except after I run the program and one of the cases occurs, the program continues to run despite my while statement stating that it should only work while(userInput != 1).
I cannot use global variables to solve this problem, as my assignment limits me on using such techniques, thus any help would be much appreciated!
Here is a snippet of my code:
void functionTest()
{
int gameOver = 0;
int userInput;
do
{
printf("please enter a number 1-3");
scanf("%d",&userInput);
switch(userInput)
{
case 1:
printf("You entered %d",userInput);
gameOver = 1;
break;
case 2:
printf("You entered %d",userInput);
gameOver = 1;
break;
case 3:
printf("You entered %d",userInput);
gameOver = 1;
break;
}
}
while(gameOver!= 1);
}
}
The problem probably lies when you use scanf(). Something that you're inputting before hitting enter is not 1, 2 or 3. Could you tell us exactly what you type when it asks you to enter a choice?
Sometimes, the standard output needs to be flushed before using a fresh scanf(). Try fflush(stdout) before the scanf line.
See older question 1 and older question 2.
EDIT:
I can reproduce the problem easily enough if I enter anything apart from "1","2" or "3"...
I would suggest, you do the following before executing the switch statement:
Add fflush(stdout) before scanf()
Accept the input as a string (%s) instead of a number. (char [] needed)
Trim the string of trailing and leading white spaces.
Convert to number using a library function
Then switch-case based on that number
The problem is that if other characters (that aren't part of an integer) are present in the input stream before an integer can be read, scanf() fails and unusable data is never cleared out... which leads to an infinite loop (where scanf() repeatedly fails to read the same characters as an integer, over and over).
So you need to read off the invalid characters when scanf() fails, or as part of the format.
A simple fix would be to change your scanf from:
scanf("%d",&userInput);
to:
scanf("%*[^0-9]%d",&userInput);
to read (and discard) any characters in the input stream that aren't digits 0-9 before reading your integer... but that still doesn't check whether scanf fails for any other reason (like a closed input stream).
You could replace it with something like this:
int scanfRes,c;
do {
scanfRes = scanf("%d",&userInput); /* try to read userInput */
/* ..then discard remainder of line */
do {
if ((c = fgetc(stdin)) == EOF)
return; /* ..return on error or EOF */
} while (c != '\n');
} while (scanfRes != 1); /* ..retry until userInput is assigned */
..which will retry scanf() until the field is assigned, discarding the remainder of the line after each attempt, and exiting the function if fgetc() encounters an error or EOF when doing so.
I'm trying to make a loop in C where the program calculates the avarage of 2 numbers and then waits for user input. If the user input is 'G' then the loop will break. However this is not working currently because it's (in a strange way) a infite loop.
My code is:
while(1){
pogingen++;
gem = (minimum+maximum)/2;
printf("%i",gem);
scanf("%c",&invoer);
if(invoer=='L'){
maximum = gem;
}
if(invoer=='H'){
minimum = gem;
}
if(invoer=='G'){
printf("%i",pogingen);
break;
}
}
I tested it with these values: minimum = 1, maximum = 10. The result will be an infite loop of 5's. It doesn't even wait for the user input (which it's supposed to do.)
Thanks in advance for looking at this!
It doesn't even wait for the user input (which it's supposed to do.).
The program is not waiting to get the input means there is some character left in input buffer. possibly \n from previous input. So clear the input buffer before reading input.
you can put,
getchar();
scanf("%c",&invoer);
before scanf() inside loop;
The reason it doesn't wait for user input in some instances, is because when scanf reads a character, you press the Enter key at the end of the of input, and that key is also stored in the input buffer. So the next iteration it will read that enter key.
This is easily solved by telling scanf to discard trailing whitespace (which the newline character is):
scanf("%c ",&invoer);
/* ^ */
/* | */
/* Notice extra space here */
You might also want to print some error message if the user doesn't give valid input. Also, consider using toupper, because the chances are the user will not give you an upper-case letter.
It might also be better to to use e.g. if ... else if ... else ... instead. Or possibly use a switch statement.
simple and sweet solution invoer=getchar(); that will wait for a character as well as store in to the variable.
no need to write scanf
invoer=getchar();
is a solution if you flush stdin before using it for the next iteration like so:
fflush(stdin);
invoer=getchar();
Here is a snippet from my code
scanf("%d", &s);
while(s!=1 && s!=2) {
if(scanf("%d", &s) != 1) {
show_warning(); //just print some info msg
}
}
The idea is to execute show_warning function only if user enter something different of 1,2 and entered value to be only integer.
With the code above it jumps in infinity loop. How to fix that ?
The problem is that the failed input operation doesn't extract any characters from the stream (and you'll keep reading the invalid input over and over), so you have to empty the input manually. For example:
char buf[1000];
// ...
if(scanf("%d", &s) != 1)
{
puts("Error, try again: ");
fgets(buf, 1000, stdin);
}
As I suggested in the other question, if you use fgets from the start to always read one line and process it later, you overcome this problem.
(The same philosophy is true in C++: read the whole line first so the input stream can move on, and process the line later to see if its valid.)
Why are you using a while loop? Do you want show_warning(); to be called once, or repeatedly? If you answered once then you only need an if-statement.
What makes you think it is looping until infinity?
You only get the warning message when you have not entered a number because it did not read a token.
Changing the && to || though is a certain way to ensure it will run to infinity as your loop will never break then.
You might want an alternative message to prompt the user to enter data when they did enter a number but not 1 or 2?
I'm assuming you're having issues when a non-integer is input. This is because scanf leaves non-matching characters in the buffer, so subsequent calls are seeing the same input and looping.
What you need to do is if the scanf call returns any number other 1 is: read that character in using scanf("%c",&somechar) so you can print it and tell the user that it isn't accepted. The non-accepted input will then have been removed so the next call to scanf will give you the next input rather than the one you saw on the previous iteration.
Also what happens when no scanf succeeded? The variable s remains unchanged (and perhaps with an undefined value, if you did not initialize it). You should set it, or change the condition of the while !
And you really should learn to compile with warnings enabled and debugging information (i.e. gcc -Wall -g on Linux) and to use a debugger (e.g. gdb on Linux)