The purpose of this code is so if the user enters an incorrectly formatted input, the program while ask the user to try again. For some reason though in my code, the scanf is constantly skipped after the first iteration, causing in infinite loop
#include <stdio.h>
int main() {
double A1;
int n1, loopchck, i=0;
while (i==0) {
printf("Enter a real number and inerger (A n): ");
fflush(stdin);
loopchck=scanf_s(" %lf %d", &A1, &n1);
if (loopchck == 2) {
i = 1;
}
else {
i = 0;
}
}
return 0;
}
For a start, lets think about what you want fflush(stdin); to do. fflush only operates on streams that have been written to; it causes any unwritten (cached) data to be fully written, and it makes no sense in the context of stdin.
This is a common mistake. When you tell scanf to read an integer (or a floating point, whatever) it'll stop reading when it no longer sees anything numeric. This means you'll probably have a leftover '\n' on the stream, at least. The user might have also entered other (erroneous) input that you want to discard.
The idea of discarding user input is horrible! You should think about accepting input in a different form (e.g. using argv in int main(int argc, char **argv)) to make their uncomfortable life a little more comfortable.
If you can't do that (or you don't want to), you can use one of the following pieces of code to discard up to (and including) the next '\n':
void fdiscardline(FILE *f) {
int c;
do {
c = fgetc(f);
} while (c != EOF && c != '\n');
}
void fdiscardline(FILE *f) {
fscanf(f, "%*[^\n]");
fgetc(f);
}
You should use this after your input, not before. Also, you need to think about what i should be. Should it be zero when more input can be read (e.g. while (i==0)), or zero when input wasn't read correctly? You need to be consistent because that's your loops terminal condition. For example:
#include <stdio.h>
int main() {
double A1;
int n1, loopchck, i=0;
while (i==0) {
printf("Enter a real number and inerger (A n): ");
loopchck=scanf_s(" %lf %d", &A1, &n1);
fdiscardline(stdin);
if (loopchck == 2) {
i = 0;
}
else {
i = 1;
}
}
return 0;
}
Related
I am fairly new when it comes down to C programmming. That's why i am working my way up by doing some of the easier exercises. The exercise i'm working on is the "guess the number" game, where the user must guess the number that lies between two numbers (upper and lower bounds). The program is doing what it must, with one exception: when the user enters a character instead of an integer, the program gets stuck in an infinite loop. The only way to break out of this loop is by using a break statement and restarting the program. What i want instead, is to have the program request for the users input again, untill an integer is entered.
Can someone tell me why the programm gets stuck in this infinite loop and why it is not requesting for input again trough scnanf like it did in the first iteration? your help will be appreciated. thank you.
//globals
int secret_nr;
int guess;
int upper_bound = 100;
int lower_bound = 1;
int total_guesses = 1;
void check_input(void) {
if (guess < lower_bound || guess > upper_bound) {
printf("Invalid input! Your guess must be between %d and %d\n", lower_bound, upper_bound);
}
else if (guess < secret_nr) {
printf("Higher\n");
total_guesses++;
}
else if (guess > secret_nr) {
printf("Lower\n");
total_guesses++;
}
else if (guess == secret_nr) {
printf("correct! You guessed the number after guessing %d times!\n", total_guesses);
}
}
int main(int argc, char* argv[]) {
srand(time(NULL));
secret_nr = (rand() % upper_bound) + 1;
printf("Guess the number between %d and %d:\n", lower_bound, upper_bound);
do {
if (scanf("%d", &guess)) {
check_input();
}
else {
printf("Invalid input! Only integer values are allowed!\n");
//break;
}
} while (guess != secret_nr);
return 0;
}
If scanf fails to parse its input according to the specified format, then the input will be left in the input buffer for the next call to scanf which will read the very same input and again fail. And so on and on and on...
The simple solution is to first of all read the whole line of input, using e.g. fgets. Then you can use sscanf in that (now extracted) input to attempt to parse it.
Further complicating your current code is the fact that if scanf fails in some other way, it will return EOF which is the integer -1, which is "true". That will of course lead to problems with your logic and looping as well.
I see this reply in another post: https://stackoverflow.com/a/1716066/5687321
scanf consumes only the input that matches the format string, returning the number of characters consumed. Any character that doesn't match the format string causes it to stop scanning and leaves the invalid character still in the buffer. As others said, you still need to flush the invalid character out of the buffer before you proceed. This is a pretty dirty fix, but it will remove the offending characters from the output.
char c = '0';
if (scanf("%d", &number) == 0) {
printf("Err. . .\n");
do {
c = getchar();
}
while (!isdigit(c));
ungetc(c, stdin);
//consume non-numeric chars from buffer
}
I want the user to be asked "how many circles" they wanna write until the user decides to end it with (Ctrl+d) which is EOF?
extra question: if I write a letter for example "k" it will spam out circles. How do I change that?
#include <stdio.h>
int main ()
{
int i;
int x;
printf("\nHow many circles do you want to write?\n");
scanf("%d", &x);
while(x != EOF)
{
for (i = 1; i <= x; i = i + 1)
{
putchar('o');
}
printf("\nHow many circles do you want to write?"
"(to end program click ctrl+d at the same time!))\n");
scanf("%d", &x);
}
printf("\n\n Bye! \n\n");
return 0;
}
The biggest problem with your program is that scanf will not read an EOF into a variable. However, fixing just this problem is not going to make your program entirely correct, because there are other issues in your code:
Your code repeats itself - when possible, you should unify the code that deals with the first iteration vs. subsequent iterations.
Your code will not handle invalid input - when an end-user enters non-numeric data, your program goes into an infinite loop.
Your code follows the old style of C - declaring all variables at the top has not been required for more than fifteen years. You should declare your loop variable inside the loop.
Here is how you fix all these shortcomings:
int x;
for (;;) {
printf("\nHow many circles do you want to write? (to end the program click Ctrl+D at the same time!)\n");
int res = scanf("%d", &x);
if (res == EOF) break;
if (res == 1) {
... // Draw x circles here
} else {
printf("Invalid input is ignored.\n");
scanf("%*[^\n]");
}
}
printf("\n\n Bye! \n\n");
return 0;
As per the man page, scanf() will return EOF, not scan EOF to x as a value.
Return Value
These functions 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.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs......
Also,
if I write a letter for example "k" it will spam out circles, how do I change that?
In case of input of one char value, it causes matching failure, in your case, scanf() returns 0, instead of 1.
So, altogether, you've to collect the return value of scanf() and check check that value for the required condition. You can change your code as
int retval = 0;
while ((retval = scanf("%d", &x))!= EOF && (retval == 1))
if you're allowed to #include , there are two convenient functions bool kbhit() and char getch().
So you can write
char c=0;
if(kbhit()) c = getch();
if(c== whatever code ctrl+d returns) x=EOF;
Hint: Take a look at what scanf(%d,&x) returns when you enter a letter instead of a number.
You can read char by char input :
#include <stdio.h>
int main ()
{
int i;
int x = 0;
int nb = 0;
while(x != EOF)
{
printf("\nHow many circles do you want to write?\n");
nb = 0;
for (x = getchar(); x != '\n'; x = getchar()) {
if (x == EOF)
goto end;
if (x >= '0' && x <= '9') {
nb = nb * 10 + x - '0';
}
}
for (i = 0; i < nb; i++)
{
putchar('o');
}
}
end:
printf("\n\n Bye! \n\n");
return 0;
}
Please i'm having an issue with my program. Whenever i try to input a float it's getting into an infinity loop. I know that the input is stored as an integer. How can prevent the user from entering a float (how to filter the input).
Why is the program getting into an infinite loop when the input is a float.
This is an example:
#include <stdio.h>
main()
{
int i = 0;
while(i<10){
system("cls>null");
printf("%d^2 = %d\n", i, i*i);
printf("Index: ");
scanf("%d", &i);
}
}
When you call scanf to read a number, but the input contains something incompatible with the input format specifier, scanf does not consume such incorrect input, leaving it in the buffer. Your program does not clear the buffer on input mismatch, entering an infinite loop: scanf tries to read an int again, sees that it's not there, and exits without modifying i. Your loop sees that i is less than 10, and calls the scanf again.
To fix this, check that scanf returned one input. Use the input when it is correct, or call scanf again with the %*[^\n]\n specifier, which means "read to the end of the string, and discard the input":
if (scanf("%d", &i) != 1) {
scanf("%*[^\n]\n");
}
Note the asterisk - it means that the consumed input needs to be discarded, rather than being written into a variable.
Better use fgets() to read a complete line from stdin, and strtol()
to parse it into an number, for example:
char buffer[256];
char *endp;
int i;
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
// buffer now contains one line (including the terminating newline)
i = (int)strtol(buffer, &endp, 10);
// endp points to the first character after the parsed number:
if (endp > buffer && (*endp == 0 || isspace(*endp))) {
printf("%d^2 = %d\n", i, i*i);
} else {
printf("invalid input\n");
}
}
#include <math.h>
#include <stdio.h>
int main (void)
{
int i = 0;
float j = 0;
while(i<10)
{
system("cls");
printf("%d^2 = %d\n", i, i*i);
printf("Index: ");
if (scanf("%f", &j) <= 0 && j-fabs(j) != 0)
{
printf ("The input is not an interger");
}
}
}
Can someone explain or correct me on the code i have?
I'm trying to input several characters and get the ascii value
ex: input: ab; output:9798
This is my code but there's a 10 at the end of it
#include <stdio.h>
int main() {
char c;
printf("Enter any character\n");
for (c=0; c<=122; c++)
{
scanf("%c", &c);
printf("%d",c);
}
return 0;
}
If you look at ASCII table, a decimal value of 10 is a newline character. In other words, you process \n character as part of the input. This can happen when user copy-pastes multiple lines, or when Enter key is pressed, for example. If you do not want that to happen, you need to take extra care to ignore \n. For example:
#include <stdio.h>
int main() {
char c;
printf("Enter any character\n");
for (c=0; c<=122; c++)
{
scanf("%c", &c);
if (c == '\n')
break; /* Or perhaps continue? Depends on what you actually want. */
printf("%d",c);
}
return 0;
}
Also, note that different systems may have different conventions as for what newline actually is. On UNIX, it is \n character only, on Windows, it might be a combination or \r and \n. So if you want to make your program portable, this needs to be taken into account. You can either do it yourself, or use some other library (GNU getline comes to mind). You can read more about newline here.
You may want to exclude some chars from the output and not only '\n', in that case you can try something like this:
#include <stdio.h>
int isEndingChar(char c) {
char terminators[3] = {'\r','\t','\n'}
int n;
for( n=0; n<3; n++ ) {
if( terminators[i]==c )
return 1;
}
return 0;
}
int main() {
char c;
printf("Enter any character\n");
for (c=0; c<=122; c++)
{
scanf("%c", &c);
if( isEndingChar( c ) )
break;
printf("%d",c);
}
return 0;
}
I want to use infinite type specifiers (%d) in scanf() function.
For example-
printf("Enter numbers: \t");
scanf("--%d SPECIFIERS--");
So its not definite how many nos. the user will enter. I don't want my program to ask the user the 'numbers of characters'.. but I want to allow any the numbers of characters. But its not possible to enter infinite %d in scanf().
So can anyone please tell what is the C program of finding average of numbers given by the user (if you dont know how much nos. the user will give and you don't want the program to ask 'how many numbers.')?
This is tricky. 2 approaches
1 - fgets() Read 1 line, then parse
char buffer[1000];
int count = 0;
double sum = 0;
int num;
fgets(buffer, sizeof buffer, stdin);
const char *p = buffer;
int n;
while (sscanf(p, "%d%n", &num, &n) == 1) {
p += n;
; // do something with `num`
sum += num;
count++;
}
printf("Average %f\n", sum/count);
2 - Lets say you infinite input ends with the end-of-line. Now the problem is that %d will consume all leading whitespace, including \n. Thus we need to consume and test all whitespace beforehand
int count = 0;
double sum = 0;
int num;
for (;;) {
int ws = 0;
while (isspace(ws = fgetc(stdin)) && (ws != '\n'));
if (ws == '\n') break;
ungetc(ws, stdin);
if (scanf("%d", &num) != 1) break;
; // do something with num
sum += num;
count++;
}
printf("Average %f\n", sum/count);
If you really interested in infinite number of inputs the just try this
while(1)
{
printf("Enter numbers: \t");
scanf("%d", number);
}
It will take input until you forcibly close your program!
But does it make any sense of doing this ?
You should have some way of knowing where the input ends. There are many ways for it and each has a possibly different solution. The two most common ones would be:
Input finishes at end-of-line
The solution is to read one line and then parse the line to get your numbers until the line ends.
This has the benefit that the program could ask for other input afterwards for other parts of the program. The disadvantage is that the user has to input all the numbers in the same line.
Input finishes at end-of-file
Simply loop, reading one number until end of file:
while (scanf("%d", &num) == 1)
/* do something with num */
Note: the user can enter end-of-file in a Linux console with Ctrl+D
If the user input is always numbers separeted by spaces and then at the end is an enter (newline). Then you can use the following code
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int input;
char c;
while (scanf(" %d%c", &input, &c) == 2 ) {
printf("number is %d\n", input);
if ( c == '\n') break;
}
}
If the use want to communicate the number of input as argument
int main(int argc, char *argv[])
{
int number_of_input = atoi(argv[1]);
int input, i;
for (i=0; i<number_of_input; i++) {
scanf(" %d", &input);
}
}
and when you call you program. you call it in this way:
$ myprogram 5
and 5 here is the number of the integer that you can input
myprogram will be saved in argv[0]
5 will be saved in argv[1]
myprogram and 5 are saved as sting in the argv[] array. atoi(argv[1]) will convert the "5" as string to 5 as integer
you can make the user enter an infinite integer input in this way too:
int main(int argc, char *argv[])
{
int input, i;
while (1) {
scanf(" %d", &input);
}
}
And you can give the user a way to stop this infinite loop:
int main(int argc, char *argv[])
{
int input;
while (scanf(" %d", &input) != EOF) {
//....
}
}
here you can stop the infinite loop with
EOF = CTRL + D (for Linux)
EOF = CTRL + Z (for Windows)
At first reading, the solution to a problem like this is to loop until the user inputs a "done" character. This could be a letter Q for example. By reading in the input as a string you can process both numbers and letters. The code below processes one input at a time (followed by ) - with the possibility to either Quit (terminate program), or Clear (restart calculation, keep program running):
printf("Enter numbers to average. Type Q to quit, or C to clear calculation.\n");
char buf[256];
double sum=0, temp;
int ii = 0;
while(1)
{
printf("Input: \t");
fgets(buf, 255, stdin);
if (tolower(buf[0])=='q') break;
// allow user to "clear" input and start again:
if (tolower(buf[0])=='c') {
sum = 0;
ii = 0;
printf("Calculation cleared; ready for new input\n");
continue;
}
ii++;
sscanf(buf, "%lf", &temp);
sum += temp;
printf("At this point the average is %lf\n", sum / (double)ii);
}
printf("Done. The final average of the %d numbers is %lf\n", ii, sum / ii);
EDIT Following some back-and-forth in the comments to this and other answers, here is a solution that addresses your problem. Code has been tested - it compiles, runs, gives expected results:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
double sum=0;
int ii=0;
char buf[256], *temp;
char *token;
printf("Enter the numbers to average on a single line, separated by space, then press <ENTER>\n");
fgets(buf, 255, stdin);
temp = buf;
while((token=strtok(temp, " ")) != NULL) {
temp = NULL; // after the first call to strtok, want to call it with first argument = NULL
sum += atof(token);
ii++;
printf("Next token read is number %d: '%s'\n", ii, token); // so you see what is going on
// remove in final code!!
}
printf("AVERAGE: ***** %lf *****\n", sum / (double)ii);
return 0;
}
One more edit If you want to use getline instead (which you asked about in the comments - and it's even safer than fgets since it will increase the buffer size as needed), you would change to change the code a little bit. I am just giving some of the pertinent lines - you can figure out the rest, I'm sure:
double sum=0;
char *buf, *temp; // declaring buf as a pointer, not an array
int nBytes = 256; // need size in a variable so we can pass pointer to getline()
buf = malloc(nBytes); // "suggested" size of buffer
printf("Enter numbers to average on a single line, separated with spaces\n")
if (getline(&buf, &nBytes, stdin) > 0) {
temp = buf;
// rest of code as before
}
else {
// error reading from input: warn user
}
I am sure you can figure it out from here...