Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I need to write a code where you ask the user for number between 3-69. If the input is incorrect I have to print in stderr either "wrong input" (if it's a letter) or "out of range" if it doesn't belong in the interval.
I can deal with the "out of range" stderr, but not the other one. When I input a letter it gets automatically transformed into some big number, which is I suppose an adress in memory or something. In that case the stderr becomes "out of range" and not "wrong input". Is there a way to fix it?
Maybe it's wrong that I introduced the variables as int?(these are the lines in code that get the input):
int x, y;
scanf("%i %i",&x,&y);
When I input a letter it gets automatically transformed into some big number, which is I suppose an adress in memory or something.
It's whatever garbage was in x and y.
scanf("%i %i",&x,&y); says to look for two integers. If scanf doesn't see two integers it will fail and it will not write anything to x nor y. Because you're not checking if scanf succeeded, when you read x and y they will be uninitialized; they'll contain whatever garbage was in memory at the time.
The naive approach is to first check if scanf succeeded. Then check if the numbers are in the right range. I'll simplify the problem to a single number for illustrative purposes.
#include <stdio.h>
int main() {
int num;
while(1) {
if( scanf("%i ",&num) != 1 ) {
fprintf(stderr, "Please enter a number.\n");
continue;
}
if( num < 3 || 69 < num ) {
fprintf(stderr, "The number must be between 3 and 69.\n");
continue;
}
break;
}
printf("Your number is %i.\n", num);
}
But when the user enters "a" this will enter an infinite loop.
$ ./test
a
Please enter a number.
Please enter a number.
Please enter a number.
When scanf fails it leaves the user's input on stdin. The above program will read the same a over and over again. This is a general problem with scanf, it is designed for well-structured input and user input is not well-structured. See the C FAQ for more problems with scanf.
Instead, read and parse separately. Read the whole line with fgets, parse it with sscanf, and if it isn't what you want read another line.
#include <stdio.h>
int main() {
int num;
char line[1024];
while(fgets(line, sizeof(line), stdin)) {
if( sscanf(line, "%i ",&num) != 1 ) {
fprintf(stderr, "Please enter a number.\n");
continue;
}
if( num < 3 || 69 < num ) {
fprintf(stderr, "The number must be between 3 and 69.\n");
continue;
}
break;
}
printf("Your number is %i.\n", num);
}
Related
I am attempting to create a program where you input 2 numbers and then print out the first number to the power of the second number.
I tried using a while loop to say that if the numbers you input are two, then you keep repeating the program, otherwise if you input more than 2, you end the loop and print out that you input too many numbers.
However, the code still works if I input more than two, and I assume this is because the scanf function ignores anything other than the first two numbers I input.
How do I fix this program so that it works as I had intended?
#include <stdio.h>
#include <math.h>
int main(void)
{
float x, exp;
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
while(scanf("%f%f", &x, &exp) == 2)
{
printf("%f\n", pow(x, exp));
printf("Enter the next pair of numbers:\n");
}
printf("You entered too many numbers!\n");
return 0;
}
User input is tricky. Get input as a string, and loop on that. Just keep in mind that the user may enter each input one at a time. Either require it to be correct (user types two numbers followed by Enter) or take effort to handle multiple correct inputs (user types one number followed by Enter and then another number followed by Enter). Here we will require both inputs on the same line:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
float x, exp;
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
char s[1000];
while (fgets(s, sizeof(s), stdin))
{
if (sscanf(s, "%f %f", &x, &exp) != 2)
{
puts("Invalid input, my dude.");
break; // Stop running if user supplies fewer than two valid inputs
}
else
{
printf("%f\n", pow(x, exp));
}
printf("Enter the next pair of numbers:\n");
}
return 0;
}
This requires the user to terminate the stream to quit, BTW, by pressing ^Z,Enter on Windows or ^D on Linux. You could easily add additional methods to terminate in the loop (for example, terminate if s is empty or sscanf returns 0), but this is not necessary.
EDIT: There are other issues too. For example, what if the user enters more than two inputs on a line. Should I detect that? Again, for programs like this, it is ok to assume that inputs will be valid unless your assignment specifically requires you to detect error conditions.
EDIT 2: If you wish to catch a more than two items entered error, you must make sure that sscanf() consumed the entire line. Fortunately there is an easy way to do that. Change line 15 to:
int n;
if ((sscanf(s, "%f %f %n", &x, &exp, &n) != 2) || (s[n] != '\0'))
What that does is skip all whitespace after the second float to either end of string or the next available item in the string and returns the index of that position in n.
After that we only need to verify that the end of string condition is what was found.
If the user types more than two numbers this will not be an error. They will be stored in the input buffer and read in the next call of scanf.
Pay attention to that the user can type two numbers on the same line or in different lines.
In fact you can not prevent the user to enter on one line numerous numbers. But you can check that at most two lines there are entered two numbers.
So you need to split the input.
The first number will be read using scanf and the second number will be read using fgtes.
Here is a demonstration program.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
while ( 1 )
{
float x, exp;
if ( scanf( "%f ", &x ) != 1 ) break;
char s[20];
if ( !fgets( s, sizeof( s ), stdin ) ) break;
int n;
if ( sscanf( s, "%f %n", &exp, &n ) != 1 || s[n] != '\0' ) break;
printf("%f\n", pow(x, exp));
printf("Enter the next pair of numbers: ");
}
puts( "You entered too many or too few numbers!" );
return 0;
}
Its output might look like
Please enter a number followed by the power you want to raise it to: 1 2
1.000000
Enter the next pair of numbers: 2
3
8.000000
Enter the next pair of numbers: 4
5 6
You entered too many or too few numbers!
Simply put, your code will always continue. This is just because of how scanf works:
Scanf scans input from stdin. When scanf reaches the end of stdin and still hasn't scanned everything it expected to scan, it waits until the user sends a newline (presses enter). In other words, so long as you enter valid floats, your scanf will never return a value lower than the expected float count.
On the other end, once scanf is finished with scanning stdin, it immediately evaluates the variables and returns. This means that there is still some input left in stdin that has not yet been read. In fact, when scanf next runs, it will resume scanning exactly where it left off. Take this sample code:
int main()
{
int x,y;
int ct = scanf("%d%d",&x,&y);
printf("%d (%d,%d)\n",ct,x,y);
scanf("%d",&x);
printf("%d\n",x);
}
If you compile and run this, try inputting three ints at once. The second scanf will immediately terminate because it is reading the third integer that was inputted.
If you are trying to get a specific number of inputs, I would suggest scanning the user's input as a string and then using sscanf (scanf for strings). You could also check for the number of spaces in the string, then, to determine if there are too many inputs. If you want to get a little tricky, you could continue to use scanf but then check whether bytes are remaining in stdin before you continue. Here is a good answer that will help if you want to keep using scanf as is, but checking whether stdin is empty.
There is another issue with your code though; what happens when a user inputs something other than a float? But that is a different question entirely (and one where my personal suggestion would be to analyze the entire scanned string).
The problem with using scanf is that it treats all whitespace characters (e.g. spaces and newline characters) as equal. For example, scanf won't care whether the numbers you entered are on the same line or not.
If scanf is asked to read two numbers, but the user instead enters three numbers on the same line, then your first call to scanf will only read the first two numbers and leave the third number on the input stream, so that the next scanf call in the next loop iteration will read it as the next first number. This is not what you want.
Therefore, for line-based user input, it is probably better not to use scanf. Instead, it makes more sense to always read exactly one line per loop iteration. You can do this with the function fgets.
After using fgets to read a line of input, two of the other answers use sscanf to convert both numbers at once. However, you can also convert one number at a time using strtof:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdbool.h>
int main(void)
{
//we want to provide the user with a different prompt the first time,
//so we must remember whether it is the first time
bool first = true;
//infinite loop
while ( true )
{
float x, exp;
char line[100];
char *p, *q;
//prompt user for input
if ( first )
{
printf(
"Please enter a number followed by the power "
"you want to raise it to: "
);
//remember to use a different prompt next time
first = false;
}
else
{
printf("Enter the next pair of numbers: ");
}
//attempt to read one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
//break out of infinite loop
break;
}
//attempt to find newline character
p = strchr( line, '\n' );
//make sure entire line was read in
if ( p == NULL && !feof(stdin) )
{
//only accept missing newline character on end-of-file
if ( !feof(stdin) )
{
int c;
printf( "Line too long for input buffer!\n" );
//discard remainder of line
do
{
c = getchar();
} while ( c != EOF && c != '\n' );
continue;
}
}
else
{
//remove newline character by overwriting it with null character
*p = '\0';
}
//start parsing at start of line
p = line;
//attempt to convert first number
x = strtof( p, &q );
//determine whether conversion of first number succeeded
if ( p == q )
{
printf( "Conversion of first number failed!\n" );
continue;
}
//continue parsing at end of first number
p = q;
//attempt to convert second number
exp = strtof( p, &q );
//determine whether conversion of second number succeeded
if ( p == q )
{
printf( "Conversion of second number failed!\n" );
continue;
}
//verify that remainder of line is either empty or only
//consists of whitespace characters
for ( p = q; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected character found after second number!\n" );
//we cannot use the "continue" keyword here, because
//we want to continue to the next iteration of the
//outer loop, not the inner loop
goto continue_outer_loop;
}
}
//print result
printf( "Input accepted, the result is: %f\n", pow(x, exp) );
continue_outer_loop:
continue;
}
return 0;
}
This program has the following behavior:
Please enter a number followed by the power you want to raise it to: abc
Conversion of first number failed!
Enter the next pair of numbers: 10
Conversion of second number failed!
Enter the next pair of numbers: 10 abc
Conversion of second number failed!
Enter the next pair of numbers: 10 20
Input accepted, the result is: 100000000000000000000.000000
Enter the next pair of numbers: 10 20 30
Unexpected character found after second number!
As you can see, the program correctly rejects the input if it contains a third number.
I'm trying to do a program with a simple game for a user to guess the number. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 30
#define TRYING 5
void guessnumber(int, int, int *);
int main(void) {
int mytry = 1;
guessnumber(MAX, TRYING, &mytry);
if (mytry <= TRYING)
printf("Congratulations! You got it right in %d tries\n", mytry);
else
printf("Unfortunately you could not guess the number in the number of tries predefined\n");
printf("End\n");
return EXIT_SUCCESS;
}
void guessnumber(int _n, int _m, int *_mytry) {
srandom(time(NULL));
int generated = 0, mynum = 0, test = 0;
generated = rand() % (_n + 1);
printf("Welcome to \"Guess the number\" \n");
printf("A number between 0 and %d was generated\n", _n);
printf("Guess the number:\n");
while (*_mytry <= TRYING) {
test = scanf(" %d", &mynum);
if (test != 1 || mynum < 0 || mynum > MAX)
printf("ERROR: please enter a valid number \n");
else
if (mynum > generated)
printf("Wrong! The number your trying to guess is smaller\n");
else
if (mynum < generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry = *_mytry + 1;
}
}
Okay, now the program is working pretty ok except for one thing: the scanf test.
It works if I try to enter a number out of my range (negative or above my upper limit) but it fails if I for example try to enter a letter. What it does is that it prints the message of error _m times and then it prints "Unfortunately you could not guess the number in the number of tries predefined" and "End".
What am I doing wrong and how can I fix this?
In case, a character is entered, you're trying to detect it correctly
if(test!=1 ......
but you took no action to correct it.
To elaborate, once a character is inputted, it causes a matching failure. So the input is not consumed and the loop falls back to the genesis position, only the loop counter is increased. Now, the previous input being unconsumed, is fed again to the scanf() causing failure once again.
This way, the loop continues, until the loop condition is false. Also, for every hit to scanf(), as unconsumed data is already present in the input buffer, no new prompt is given.
Solution: You need to clean the input buffer of existing contents when you face a failure. You can do something like
while ((c = getchar()) != '\n' && c != EOF);
to clean the buffer off existing contents.
When you enter a letter, scanf() leaves the letter in the input stream since it does not match the %d conversion specifier. The simplest thing to do is use getchar() to remove the unwanted character:
if (test != 1) {
getchar();
}
A better solution would be to use fgets() to get a line of input, and sscanf() to parse the input:
char buffer[100];
while (*_mytry<=TRYING)
{
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
fprintf(stderr, "Error in fgets()");
exit(EXIT_FAILURE);
}
test=sscanf(buffer, "%d", &mynum);
if(test!=1 || mynum<0 || mynum>MAX)
printf ("ERROR: please enter a valid number \n");
else if(mynum>generated)
printf("Wrong! The number your trying to guess is smaller\n");
else if(mynum<generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry=*_mytry+1;
}
In the above code, note that the leading space has been removed from the format string. A leading space in a format string causes scanf() to skip leading whitespaces, including newlines. This is useful when the first conversion specifier is %c, for example, because any previous input may have left a newline behind. But, the %d conversion specifier (and most other conversion specifiers) already skips leading whitespace, so it is not needed here.
Additionally, your code has srandom() instead of srand(); and the call to srand() should be made only once, and probably should be at the beginning of main(). And, identifiers with leading underscores are reserved in C, so you should change the names _m, _n, and _mytry.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I want to read n integers from user during execution and the numbers are separated by spaces. It would be the best to be received as an array. For input 1 22 3 445 3, the result is, array[0]=1, array[1]=22 and so on. I have to do it in C. Can't use
scanf("%d %d %d", &var1, &var2, &var3);
because, I don't know how many such numbers would be inserted. The value of n would be read from user just before reading this data.
enum { MAX_NUMBERS = 1000000 }; // Choose appropriate upper bound
int n;
if (scanf("%d", &n) == 1 && n > 0 && n < MAX_NUMBERS)
{
int array[n];
for (int i = 0; i < n; i++)
{
if (scanf("%d", &array[i]) != 1)
…process error — terminate loop?…
}
…use array…
}
You can read multiple numbers with scanf() using a loop as shown. You've no idea whether they were all presented on a single line, or each was on its own line, or whether there were many blank lines between successive numbers (or any permutation of all these possibilities).
The scanf() family of functions basically do not care about newlines — it is hard to force them to do so. When you care about line-based input, use fgets() or POSIX function getline() to read a line and sscanf() — or other string parsing functions — to process the line.
I'm assuming support for C99 with VLA (variable length arrays). The principles are the same without that support — the mechanics are a little different (and there are multiple options for how to do it).
Use fgets() and then strtok() with atoi().
Take the numbers as a string.
Here is one way to do it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char numbers[100];
int myn[100];
printf("Give me numbers..\n");
fgets(numbers,100,stdin);
const char s[2] = " ";
char *token;
token = strtok(numbers, s);
int i=0;
myn[i]=atoi(token);
while( token != NULL )
{
i++;
printf( " %s\n", token );
token = strtok(NULL, s);
myn[i]=atoi(token);
}
printf("You gave me: ");
for (int j=0; j<i; j++){
printf ("%d, ", myn[j]);
}
return(0);
}
The above C program does exactly what you want. At the for loop, it prints to the screen the numbers you gave from keyboard. The "problem" would be much easier by using enter instead of spaces between the numbers.
Click on the links, to see very useful details about the functions used.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
Part of my assignment is to get user input; then, if the input is incorrect, prompt them to try again. When I use if statements and while loops in this way, they completely skip over the scanf command, and the program either runs infinitely or terminates immediately, skipping over the second chance for user input. Any idea how to fix this?
#include <stdio.h>
int main(void)
{
int number;
printf("please insert positive number\n");
scanf(" %d", &number);
// if the user inputs a value that is not a positive integer, it becomes false
// i want the if statement to re-prompt them to input the correct value
if (number <= 0)
{
printf("try again\n");
scanf(" %d", &number);
}
return 0;
}
scanf Returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned.
The scanf function reads data from the standard input stream stdin and writes the data into the location given by argument. Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format.
I recommend handle errors . it will happen in Real World code. (write Concise and robust Code).
so i recommend something like this:
#include <stdio.h>
int read_positive_int(int *n){
int retry = 3;
do{
printf("Please enter a positive number:\n");
if (scanf("%d", n) == 1){
if (*n > 0) return 1; //ok
}
} while (--retry);
return 0; //error
}
int main(void)
{
int n;
if (read_positive_int(&n))
printf("n = %d\n", n);
else
printf("error\n");
}
i hope this helps.
the code does what it's written to do, so in your case it's following:
message to user: enter a positive number
scanf: reads user's input
determine, if the number is positive
if yes - the if body will not be executed
and program ends
if not - print a message, read a number and program ends
the thing you are looking for is a loop
you want to do something like this:
while the entered number is not positive, ask the user to enter the number again
that's what loops are used for
int number;
printf("please insert positive number\n");
scanf("%d", &number);
while (number <= 0) {
printf("try again\n");
scanf("%d", &number);
}
return 0;
This question already has answers here:
Check if input is integer type in C
(16 answers)
Closed 8 years ago.
I am working on code for one of my classes and I have hit a wall. I need the user to input a number that will be used as the number of times a for loop will be repeated. The first loop where I ask for this number is a while loop. I need to make sure the value entered is a number and not a letter or special character.
I do not know how to make sure that it is not a letter or special character.
The next problem is making sure that the for loop only runs for the specified number of times that is the number provided in the first loop.
This is what I have written so far.
#include <stdio.h>
int main()
{
int num_of_scores, n;
char enter;
float score=-1, total=0, average;
do
{
printf("\n\nEnter the number of quiz scores between 1 and 13: ");
scanf ("%d, %c", &num_of_scores, &enter);
}
while(num_of_scores<1 || num_of_scores>13/* && enter == '\n'*/);
printf("\nStill Going!");
for(n=0; n<num_of_scores; n++)
{
printf("\nEnter score %i: ", n+1);
scanf ("%f", &score);
while(score>=0 || score<=100)
{
total = total + score;
score = -1;
break;
}
}
average = total / num_of_scores;
printf("\nThe average score is %.0f.\n\n", average);
return 0;
}
So I have edited the code a little bit. There is a part in the first while loop that is in a comment which i removed because it made the program end after that loop. The printf("still going") is just a test to make sure the program gets that far. Any further pointers? I am still not sure how to check make sure a number is not entered. I though adding the && enter == '\n' would do it, but if it hangs the program it is no good. Many of the examples you have suggested are good, but i find them a little confusing. Thanks!
I'd check Check if input is integer type in C for the answer to this...
Check the return value of scanf. Per the man page:
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. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see
ferror(3)) is set, and errno is set indicate the error.
do{
char ch = 0;
num_of_scores = 0;
printf("\nEnter the number of quiz scores between 1 and 13: ");
if(scanf("%d%c", &num_of_scores, &ch)!=2 || ch != '\n'){
int ch;
while((ch=getchar())!='\n' && ch !=EOF);
}
} while(num_of_scores<1 || num_of_scores>13);