How to detect non-integer input in C - c

I have this program:
#include <stdio.h>
int main(){
int val;
printf("Enter any number: ");
scanf("%d",&val);
printf("The number incremented is %d\n",val+1);
printf("Enter any number again: ");
scanf("%d",&val);
printf("The number decremented is: %d\n",val-1);
return 0;
}
It works completely fine if i give it an integer input, but when its a different input, the program goes crazy and runs without accepting the second input. (the second output is -1). is there a fix to this?
I have tried to test the program with number and non-number inputs, For the non number one in the first input, as the description said, the program continued and didnt accept the second input.
Edit: I did not mention the desired output of the program, sorry about that.
If the output is non-integer then it will return with err code 1.

If you want the function to return -1; in the case of the user entering invalid input, then you should check the return value of scanf, for example like this:
#include <stdio.h>
int main( void )
{
int val;
printf( "Enter any number: ");
if ( scanf( "%d", &val ) != 1 )
{
printf( "Invalid input!\n" );
return -1;
}
printf( "The number incremented is %d\n", val+1 );
printf( "Enter any number again: " );
if ( scanf( "%d", &val ) != 1 )
{
printf( "Invalid input!\n" );
return -1;
}
printf( "The number decremented is: %d\n", val-1 );
return 0;
}
This program has the following behavior:
Enter any number: abc
Invalid input!
Enter any number: 5
The number incremented is 6
Enter any number again: abc
Invalid input!
Enter any number: 5
The number incremented is 6
Enter any number again: 10
The number decremented is: 9
However, this solution is not perfect. For example, if the user enters 5abc in the first line, then the first scanf successfully reads 5, but the second scanf will fail:
Enter any number: 5abc
The number incremented is 6
Enter any number again: Invalid input!
If you don't want this counter-intuitive behavior, then it would probably be best not to use the function scanf for line-based user input, but to rather use the functions fgets and strtol instead, for example like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
int get_int_from_user( const char *prompt );
int main( void )
{
int val;
val = get_int_from_user( "Enter any number: ");
printf( "The number incremented is %d\n", val+1 );
val = get_int_from_user( "Enter any number again: ");
printf( "The number decremented is: %d\n", val-1 );
return 0;
}
int get_int_from_user( const char *prompt )
{
//loop forever until user enters a valid number
for (;;)
{
char buffer[1024], *p;
long l;
//prompt user for input
fputs( prompt, stdout );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "Unrecoverable input error!\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "Line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "Unrecoverable error reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
l = strtol( buffer, &p, 10 );
if ( p == buffer )
{
printf( "Error converting string to number!\n" );
continue;
}
//make sure that number is representable as an "int"
if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
{
printf( "Number out of range error!\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfj23jlj" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return l;
continue_outer_loop:
continue;
}
}
This program has the following behavior:
Enter any number: 5abc
Unexpected input encountered!
Enter any number: abc
Error converting string to number!
Enter any number: 5
The number incremented is 6
Enter any number again: 10
The number decremented is: 9
Note that my second program is more sophisticated than the first program, because it keeps on prompting the user for input until the user enters a valid int, whereas the first program simply prints an error message and returns -1.
I took the function get_int_from_user from this answer of mine to another question. See that answer for more information on the extensive input validation that the function performs.

The first scanf is looking for an integer if it doesn't get an integer it does nothing,
The secoind scanf is looking for an integer if it doesn't get an integer it does nothing.
If the first scanf does nothing, nothing changes, so the second identical scanf presented with the same environment will also do nothing.
one way to fix this is to tell the second scanf to discard the garbage characters.
scanf("%*[^0-9]%d",&val);
Subsequent edits to the question made that solution unsuitable.
#include <stdio.h>
int main(){
int val;
char junk[2];
printf("Enter any number: ");
if( scanf("%d%1[\n]",&val,&(junk[0])) < 2)
{
puts("numbers only please");
return 1;
}
printf("The number incremented is %d\n",val+1);
printf("Enter any number again: ");
if( scanf("%d%1[\n]",&val,&(junk[0])) < 2)
{
puts("numbers only please");
return 1;
}
printf("The number decremented is: %d\n",val-1);
return 0;
}

Related

How to deal with wrong input in C?

I am just a beginner to C language. I am trying to write a programme that take marks of four subjects. But in case if user provides a wrong input such as alphabets then it should print "Please Enter Number" and should again ask the marks of same subject.
Here is my code..
// Programme to add marks of four subject and to calculate percentage.
#include <stdio.h>
#include<ctype.h>
int main()
{
float sub_marks, total_marks, temp, check = 0;
printf("\nPragramme to add marks of four subject and to calculate percentage.\n\n");
for (int i = 1; i <= 4; i++) //Running loop four times to enter marks of four subjects.
{
printf("Enter Marks of Subject %d: ", i);
scanf("%f", &sub_marks);
if (sub_marks > 100) //condition for what to do if marks are greater then 100
{
printf("\n**MARKS CONNOT BE GREATER THEN 100**\n\n");
i--;
}
else
{
temp = temp + sub_marks; //addind marks to get total marks
}
}
printf("\n\nTotal Marks: 400");
printf("\n\nObtained marks: %.2f", temp);
printf("\n\nPercentage: %.2f%%\n\n", temp / 4);
return 0;
}
I did try a lot but ended up with output..
Pragrame to add marks of fout subject and to calculate percentage.
Enter Marks of Subject 1: 65
Enter Marks of Subject 2: y
**PLEASE ENTER NUMBER.**
Enter Marks of Subject 3:
**PLEASE ENTER NUMBER.**
Enter Marks of Subject 4:
**PLEASE ENTER NUMBER.**
After entering alphabet it dosen't let the user to input for the rest of the loops. Instead it should ask "Enter Marks of Subject 1:"
I achived above output by placing below code after else.
while (sub_marks >= 0)
{
remainder = sub_marks % 10;
if (!isdigit(remainder))
{
printf("Please enter Number");
break;
}
}
Unfortunately, the C standard library does not offer any easy way to read a floating-point number from the user, and to automatically keep asking the user until the input is valid. However, you can write such a function yourself, using the functions fgets and strtof.
In the code snippet below, I wrote a variadic function
float get_float_from_user( const char *prompt, ... )
which you can call like printf to print a string. It will repeatedly prompt the user for input using this string, until the input is valid. Once the input is valid, the function will return the user input converted to a float. You can call the function for example like this:
sub_marks = get_float_from_user( "Enter Marks of Subject %d: ", i );
If you replace the call to scanf with the line above, then your program should work as desired, after additionally fixing the following bug:
You must initialize temp to 0. The line
float sub_marks, total_marks, temp, check = 0;
will not initialize temp to 0. It will only initialize check to 0. If you want to initialize all 4 variables to 0, then you should instead write the following:
float sub_marks = 0, total_marks = 0, temp = 0, check = 0;
However, it would probably be better to change the name of temp to sum, as that describes the purpose of the variable better. Also you are not using the variables total_marks and check at all, so you can remove them. Therefore, you may want to change that line to the following:
float sub_marks, sum = 0;
Note that I am deliberately not initializing sub_marks, as that is not necessary (initializing sum is necessary, though).
However, since you are not using sub_marks outside the loop, it would probably be better to declare it inside the loop, in order to limit its scope.
Also, changing the loop counter i inside the loop is considered bad programming practice. A cleaner solution would be to create an additional loop inside the loop, so that the inner loop will only stop when the input is in the desired range.
Here is the code which does everything mentioned above:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
float get_float_from_user( const char *prompt, ... )
{
for (;;) //loop forever until user enters a valid number
{
char buffer[1024], *p;
float f;
va_list vl;
//prompt user for input
va_start( vl, prompt );
vprintf( prompt, vl );
va_end( vl );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
f = strtof( buffer, &p );
if ( p == buffer )
{
printf( "error converting string to number\n" );
continue;
}
//make sure that no range error occurred
if ( errno == ERANGE )
{
printf( "number out of range error\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfh4q" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return f;
continue_outer_loop:
continue;
}
}
int main()
{
float sum = 0;
printf( "\nProgram to add marks of four subjects and to calculate average.\n\n" );
for ( int i = 1; i <= 4; i++ )
{
float sub_marks;
//loop forever until input is in the desired range
for (;;)
{
sub_marks = get_float_from_user( "Enter marks of subject %d: ", i );
if ( sub_marks < 0.0 )
{
printf( "Marks cannot be negative!\n" );
continue;
}
if ( sub_marks > 100.0 )
{
printf( "Marks cannot be greater than 100!\n" );
continue;
}
//input is in acceptable range, so break out of infinite loop
break;
}
sum += sub_marks;
}
printf( "\n" );
printf( "Total marks: 400\n" );
printf( "Obtained marks: %.2f\n", sum);
printf( "Average: %.2f%%\n", sum / 4.0 );
printf( "\n" );
return 0;
}
The program above has the following behavior:
Program to add marks of four subjects and to calculate average.
Enter marks of subject 1: This is a test.
error converting string to number
Enter marks of subject 1: 70
Enter marks of subject 2: 80abc
unexpected input encountered!
Enter marks of subject 2: 80
Enter marks of subject 3: 110
Marks cannot be greater than 100!
Enter marks of subject 3: 90.7
Enter marks of subject 4: abc85
error converting string to number
Enter marks of subject 4: 85
Total marks: 400
Obtained marks: 325.70
Average: 81.43%
The function get_float_from_user is a slight modification of my function get_int_from_user from the second code snippet of this answer of mine to another question.
I've tried to put everything together as much as possible, but it's hard to read input correctly, managing everything that users can throw at you. This version is not perfect!
EDIT: As Andreas Wenzel pointed out: This solution has the following issues:
If the user enters a line that is so long that it doesn't fit into the input buffer, then your program won't handle the input properly. Ideally, you should check for the newline character in the input buffer.
The function sscanf has undefined behavior if the input is out of range of a float. This cannot be prevented when using the function sscanf. Therefore, it is generally not a good idea to use that function for input validation. The function strtof is better, as the behavior is well-defined for an out of range error.
The main thing is that you were computing the "average", not the "percentage".
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void)
{
printf("Program to add marks of four subjects and to calculate the average.\n\n");
float total_marks = 0;
for (int i = 1; i <= 4; i++) { // Running loop four times to enter marks of four subjects.
bool valid = false;
while (!valid) {
printf("Enter mark of subject %d: ", i);
char line[256];
if (fgets(line, 256, stdin) == NULL) {
printf("\n**INPUT ERROR OR EOF**\n\n");
exit(EXIT_FAILURE);
}
float mark;
int n;
if (sscanf(line, "%f %n", &mark, &n) != 1) {
printf("\n**ENTER A FLOATING POINT VALUE**\n\n");
}
else if (line[n] != 0) {
printf("\n**DON'T ADD ANYTHING AFTER THE NUMBER**\n\n");
}
else if (mark < 0 || mark > 100) {
printf("\n**MARKS MUST BE BETWEEN 0 AND 100**\n\n");
}
else {
valid = true;
total_marks += mark; // add marks to get total
}
}
}
printf("Total Marks: %.2f\n", total_marks);
printf("Average: %.2f\n\n", total_marks / 4);
return EXIT_SUCCESS;
}

scanf stops taking inputs from the commandline once you feed into it (the command line) an input that it didn't expect

Here's my code. When it asked for my first input on the command line, I entered '5cde'. Then it printed '5', and it didn't ask for any more inputs before termination.
How is this okay? Is there a way to see how scanf is working internally as I run this program? I really want to know what exactly is going on behind the scenes. I'm not sure how the input buffer works, and if I should even be messing with it. Or should I just use a different io function instead? Because scanf seems pretty unsafe to me.
int i;
scanf("%d", &i);
printf("%d", i);
scanf("%d", &i);
scanf("%d", &i);
scanf("%d", &i);
scanf("%d", &i);
The behavior of the function scanf when the conversion specifier d is used is the following
d Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtol function
with the value 10 for the base argument. The corresponding argument
shall be a pointer to signed integer
So for this input buffer
5cde
the first call of scanf reads the character 5 because it represents a valid integer number and the position in the input buffer moves to the right to the character 'c'.
When the next and subsequent calls of scanf failed because the symbol 'c' is not a valid digit. The position in the input stream stays the same.
You should check whether call of scanf was successful> For example
if ( scanf("%d", &i) == 1 )
{
printf("%d\n", i);
}
else
{
// remove the invalid input
scanf( "%*[^\n]%*c" );
}
Here is a demonstration program.
#include <stdio.h>
int main( void )
{
enum { N = 3 };
printf( "Enter %d numbers.", N );
for ( int i = 0; i < N; i++ )
{
printf( "\t%d: ", i + 1 );
int value;
while ( !( scanf( "%d", &value ) == 1 ) )
{
scanf( "%*[^\n]%*c" );
puts( "Invalid input. Try again" );
printf( "\t%d: ", i + 1 );
}
printf( "You inputted %d\n", value );
}
}
Its output might look like
Enter 3 numbers.
1: 1A
You inputted 1
2:
Invalid input. Try again
2: B
Invalid input. Try again
2: 2C
You inputted 2
3:
Invalid input. Try again
3: 3
You inputted 3
That is the user entered the following sequence of strings
1A
B
2C
3
You should check the result of each scanf call. It returns the number of items successfully read (or EOF in case of failure) so in your case it should return 1 or otherwise something went wrong.
Please also note that each time you hit enter during input, there's a trailing line feed character added to stdin which needs to be discarded, if you were for example to read a string after reading a number. This should be addressed early on in your C book, if it's any good.
Overall scanf is to be regarded as a quick & dirty function for simplistic programs and not something to be used in real production code, so you don't really need to worry about leaning all the details of it. Using fgets and reading everything as strings is much better (and faster) practice.
Every time you ask for input, the user will also press Enter.
Therefore, get input as a string, then turn that string into a number. As there are several steps to reading a number and verifying it as correct, you can even write a convenient function to help.
void fatal_error( const char * message )
{
fprintf( stderr, "%s\n", message );
exit( 1 );
}
int get_int( const char * prompt, int min, int max, const char * error_message )
{
char s[ 100 ];
int n, count;
printf( "%s ", prompt );
fflush( stdout );
if ( !fgets( s, sizeof(s), stdin ) // user's input
or (sscanf_s( s, "%d %n", &n, &count ) != 1) // convert to int
or (count != strlen( s )) // no "123abc" stuff allowed
or (n < min)
or (n > max) )
fatal_error( error_message );
return n;
}
int main()
{
int n = ask_int( "n?", 1, 100, "n is not optional, and must be in [1,100]" );
int age = ask_int( "How old are you?", 0, INT_MAX, "You cannot be negative years old." );
etc

c programming: Error handling. How do I stop characters from being entered into program

How I can exclude characters from being entered as a value in my programs?
Is there a way through the scanf function to recognize the input as a character and then write a printf to show an invalid value message? It would be more recognizing the character then printing the message I'm concerned with.
Edit:
So as asked, the below is my code for a program that first reads five numbers(each between 1 and 30).For each number read, the program should print a line containing that number of adjacent asterisks.
For this, if I enter a number value it causes the program to stop working. So if i could add a way to create "Try again" message or something similar when they are entered, this will stop it from having errors.
#include <stdio.h>
int main(void)
{
int number1 = 0; int counter;
int sentinelcount = 1;
printf("Please enter 5 values, between 1 and 30");
while (sentinelcount <= 5) {
printf("\n\nEnter number: \n"); /*prompt*/
scanf_s("%d", &number1); /*read an interger*/
sentinelcount++;
if (number1 < 1 || number1 > 30)
{
sentinelcount--;
printf("\nWrong Value\n");
}
if (number1 < 1 || number1 > 30)
{
printf("Enter within correct value range: 1 - 30! ");
}
else if (number1 >= 1 || number1 <= 30)
{
printf("Number of asterisks:\n");
for (counter = 1; counter <= number1;
counter++)
{
printf("*");
}
}
}
return 0;
How do I stop characters from being entered into program
Short of some magic hand that prevents the user from typing in non-numeric or a limited key board, the better approach is not to stop characters from being entered, but accept them as input and then detect invalid input.
I recommend to consume invalid input and alert the user of the issue.
A good first attempt is to read a line of input into a string with fgets().
Test for input, conversion success, extra junk and range.
char buf[80];
if (fgets(buf, sizeof buf, stdin)) { // TBD deal with lines longer than 79
If a line was read, process it with strtol(), sscanf(), etc. Use "%n" to detect where scanning ended. Perform error checking.
int num;
int n;
// If an integer was parsed with no trailing junk and in range ...
if (sscanf(buf, "%4d %n", &num, &n) == 1 && buf[n] == 0 &&
(num >= 1 && num <= 30)) {
Oh_Happy_Day(); // TBD code
} else {
Invalid_input(): // TBD code
}
One way to determine whether the user entered a character or a number is to call scanf with the %d conversion format specifier, and check the return value of scanf. If it returns 1, then the conversion format specifier was successfully matched. Otherwise, you print an error message and prompt the user again to enter input. For example:
#include <stdio.h>
int main( void )
{
int i;
//infinite loop, equivalent to while(1)
//repeat the loop until the input is valid
for (;;)
{
//prompt user for input
printf( "Please enter a number: " );
//attempt to read and convert user input
if ( scanf( "%d", &i ) == 1 )
{
//input was valid
break;
}
//print error message
printf( "Input was invalid, please try again!\n" );
//discard remainder of line
for ( int c; c = getchar(), c != '\n' && c != EOF; )
;
}
printf( "Input was successfully converted to the number %d.", i );
}
This is the output of the program:
Please enter a number: sjdfk
Input was invalid, please try again!
Please enter a number: erlh89
Input was invalid, please try again!
Please enter a number: 34
Input was successfully converted to the number 34.
However, this code has one problem: It will accept input such as "6sdfj23jlj" as valid input for the number 6:
Please enter a number: 6sdfj23jlj
Input was successfully converted to the number 6.
You would probably want to reject the input instead, in this case.
The function scanf will do this, because it is not line-based; it only processes as much input as it can to match the %d conversion format specifier.
One thing you could do to detect such invalid input would be to look at the remainder of the line, and verify that it is empty, apart from the newline character:
#include <stdio.h>
#include <stdbool.h>
int main( void )
{
bool successfully_matched = false;
bool found_newline = false;
int i;
//infinite loop, equivalent to while(1)
//repeat the loop until the input is valid
for (;;)
{
//prompt user for input
printf( "Please enter a number: " );
//attempt to read and convert user input
if ( scanf( "%d", &i ) == 1 )
successfully_matched = true;
//verify that remainder of line is empty
if ( getchar() == '\n' )
found_newline = true;
//break loop if everything was ok
if ( successfully_matched && found_newline )
break;
//print error message
printf( "Input was invalid, please try again!\n" );
//discard remainder of line, if necessary
if ( !found_newline )
{
for ( int c; c = getchar(), c != '\n' && c != EOF; )
;
}
}
printf( "Input was successfully converted to the number %d.", i );
}
Now, the program correctly rejects 6sdfj23jlj as invalid input:
Please enter a number: 6sdfj23jlj
Input was invalid, please try again!
Please enter a number:
However, this code will reject input such as 21 (note the space character after the number). I'm not sure if you want to reject input simply because of a trailing space. If you want to allow spaces and other whitespace characters, then this is possible too, but would require a bit more coding.
In your question, you stated that even if the input is a valid number, you want to additionally check whether the number is in a certain range. This can be accomplished too. However, since the code is starting to get complicated, it seems better to create a new function get_int_from_user to actually get a number from the user. After calling that function, we can then perform the range check, and if the number is not in the desired range, we print an error message and then call the function again.
#include <stdio.h>
#include <stdbool.h>
int get_int_from_user( const char *prompt )
{
bool successfully_matched = false;
bool found_newline = false;
int i;
//infinite loop, equivalent to while(1)
//repeat the loop until the input is valid
for (;;)
{
//prompt user for input
printf( "%s", prompt );
//attempt to read and convert user input
if ( scanf( "%d", &i ) == 1 )
successfully_matched = true;
//verify that remainder of line is empty
if ( getchar() == '\n' )
found_newline = true;
//break loop if everything was ok
if ( successfully_matched && found_newline )
break;
//print error message
printf( "Input was invalid, please try again!\n" );
//discard remainder of line, if necessary
if ( !found_newline )
{
for ( int c; c = getchar(), c != '\n' && c != EOF; )
;
}
}
return i;
}
int main( void )
{
int i;
//repeat until input is in the desired range
for (;;)
{
//read number from user
i = get_int_from_user( "Please enter a number: " );
//perform range check on number
if ( 1 <= i && i <= 30 )
{
//input is in the desired range
break;
}
//print error message
printf( "Number is not in the desired range, please try again!\n" );
}
printf( "The number %d is in the desired range.", i );
}
This program has the following output:
Please enter a number: 342
Number is not in the desired range, please try again!
Please enter a number: 27
The number 27 is in the desired range.
However, I generally do not recommend using scanf for line-based user input. As previously stated, the function scanf does not read one line of input at a time. This means that is can leave leftovers of the line on the input stream, which can be confusing to the programmer, and can lead to bugs, such as this one. See this question for more information on the disadvantages of using scanf.
For line-based user input, it is generally better to use the function fgets. Here is a very robust implementation of the function get_int_from_user which I copied from this previous answer of mine to another question. This function uses fgets and strtol instead of scanf, and performs extensive input validation and error checking:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
int get_int_from_user( const char *prompt )
{
for (;;) //loop forever until user enters a valid number
{
char buffer[1024], *p;
long l;
fputs( prompt, stdout );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
l = strtol( buffer, &p, 10 );
if ( p == buffer )
{
printf( "error converting string to number\n" );
continue;
}
//make sure that number is representable as an "int"
if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
{
printf( "number out of range error\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfj23jlj" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return l;
continue_outer_loop:
continue;
}
}
If you want to exclude characters from being in your code you can use something like this:
unsigned long long answer1,answer2,answer3,c;
scanf("%*[^0123456789]%llu%*[^0123456789]%llu%*[^0123456789]%llu",&answer1,&answer2,&answer3);
printf("%lld %lld %lld",answer1,answer2,answer3);
return 0;
and if you want to print characters you shouldn't scan characters like this: scanf("%d"&a) instead you scan them with this: scanf("%c",&a) and the same point stands in print. but with this you can only scan one character at a time and if you want to scan more than that use more %c in the scanf and printf.

How to scan in multiple characters at once in C?

Say if I want to ask the user to enter one input or two inputs or three.
For example:
int num_1, num_2, num_3;
printf("Enter input" );
Now I'm struggling to find how to scan either one, two or three.
If I do this:
scanf("%d %d %d", &num_1, &num_2, &num_3);
it won't work if the user inputs only one or two inputs.
So how do I do it?
You should use a cycle and an array for the inputs, for example:
/* array where the inputs will be stored. It has the maximum
number of elements (3), assuming you want to use static arrays */
int inputs[3];
int n_inputs, i;
/* ask the user how many values he wants to put */
printf("Number of inputs: \n");
if(scanf("%d", &n_inputs) != 1) {
fprintf(stderr, "scanf fail!\n");
exit(EXIT_FAILURE);
}
/* ask for the inputs values */
printf("inputs [%d]: \n", n_inputs);
for(i = 0; i < n_inputs; i++) {
if(scanf("%d", &inputs[i]) != 1) {
fprintf(stderr, "scanf fail!\n");
exit(EXIT_FAILURE);
}
}
*edited to add scanf basic error handling.
Use a simple for loop and an array:
#include <stdio.h>
int main() {
int arr[3];
for (int i = 0; i < 3; i++) {
if (scanf("%d", &arr[i]) != 1) {
return 1;
}
}
return 0;
}
You can use loop for multiple input. First take the number of input, then loop through that.
For example:
int n, i;
printf("Please enter the input threshold: ");
scanf("%d", &n);
int arr[n];
for (i = 0; i < n; i++) {
printf("Enter number #%d: ", i+1);
scanf("%d", &arr[i]);
}
The following program will read exactly one line of input using fgets and read up to MAX_INPUTS (defined as 3) numbers from that line using strtol.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MAX_INPUTS 3
#define MAX_LINESIZE 80
int main( void )
{
long inputs[MAX_INPUTS];
int num_inputs;
char line[MAX_LINESIZE], *p;
//prompt user for input
printf( "Please enter up to %d numbers: ", MAX_INPUTS );
//attempt to read one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
fprintf( stderr, "error reading line\n" );
exit( EXIT_FAILURE );
}
//verify that entire line was read in
if ( strchr( line, '\n' ) == NULL )
{
fprintf( stderr, "line too long\n" );
exit( EXIT_FAILURE );
}
//read one number per loop iteration
for (
num_inputs = 0, p = line;
num_inputs < MAX_INPUTS;
num_inputs++
)
{
char *q;
errno = 0;
//attempt to convert next number
inputs[num_inputs] = strtol( p, &q, 10 );
//break out of loop if unable to find another number
if ( p == q )
break;
//make p point to end of inputted number
p = q;
//make sure that entered number is representable as "long int"
if ( errno == ERANGE )
{
fprintf( stderr, "number is out of range\n" );
exit( EXIT_FAILURE );
}
}
//output the inputted data
printf( "You entered %d inputs. The values are:\n", num_inputs );
for ( int i = 0; i < num_inputs; i++ )
{
printf( "%ld\n", inputs[i] );
}
}
This is what happens when I run this program:
Please enter up to 3 numbers: 80 30
You entered 2 inputs. The values are:
80
30

Using scanf only for integers in c

I need to get user input for a number between 0 and 100. The problem is when i input letter in scanf the program crashes or recognizes it as a 0.I want to avoid any user mistake that would potentially crash my program.I used getch previously but i don't know how to get multiple digit numbers with it.
Any help on how to solve this problem would be nice.
Thank you.
do
{
printf("Enter ID: ");
scanf("%d", &NewWorkder->id);
TargetList= FillWorker();
TargetList= SeekList(Head, NewWorker->id);
}
while (NewWorker->id<0 || NewWorker->id>100 || (TargetList)!= (NULL) ||NewWorker->id ==0);
fprintf(filemechanic,"%s %s %d\n", NewWorker->name, NewWorker->surname, NewWorker->id);
free(TargetList);
fclose(filemechanic);
}
Don't use scanf at all. Maybe you could use its return value to see if no digits were entered at all, but if you don't want an input like 12ab to be valid, scanf won't help.
Here's an example that uses fgets and strtol to check for a valid number:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char nptr[1024];
char *errptr;
long n = 0;
do
{
printf("Enter a base-10 number: ");
fgets(nptr, sizeof nptr, stdin);
n = strtol(nptr, &errptr, 10);
} while ((*errptr != '\n' && *errptr != '\0') || n < 0 || n > 100);
}
Example of running:
Enter a base-10 number: ab
Enter a base-10 number: 12ab
Enter a base-10 number: -1
Enter a base-10 number: 101
Enter a base-10 number: 123
Enter a base-10 number: 50
[end]
If you want to see whether scanf was able to successfully match an integer, you must check the return value.
Change the line
scanf("%d", &NewWorkder->id);
to:
if ( scanf("%d", &NewWorkder->id) != 1 )
{
fprintf( stderr, "Error reading number!\n" );
exit( EXIT_FAILURE );
}
If you want to check whether the value is in the desired range, you can add the following code:
if ( newWorker->id < 0 || newWorker->id > 100 ) )
{
fprintf( stderr, "Input is out of range!\n" );
exit( EXIT_FAILURE );
}
If you don't want your program to exit on bad input, but would prefer it to print an error message and prompt the user again, you could use the following code instead:
bool bad_input;
do
{
bad_input = false;
//prompt user for input
printf("Enter ID: ");
//call scanf and verify that function was successful
if ( scanf("%d", &NewWorkder->id) != 1 )
{
printf( "Error reading number, try again!\n" );
bad_input = true;
}
//verify that input is in range
if ( newWorker->id < 0 || newWorker->id > 100 ) )
{
printf( "Number must be between 0 and 100, try again!\n" );
bad_input = true;
}
//discard remainder of line
for ( int c; (c=getchar()) != EOF && c != '\n'; )
;
} while ( bad_input );
However, for line-based input, I wouldn't recommend using scanf, because that function does not extract the entire line from the input stream; it only extracts as much as it needs. This can be confusing and can lead to programming bugs. Instead, I would recommend using fgets and strtol instead. See the other answer for such a solution. Also, I suggest that you read this guide: A beginners' guide away from scanf()

Resources