I need to input 1 to 3 numbers with values between 3 to 69 only. So when I input something different from a number the program should fprintf on stderr "The input isn't number". But I cannot find a way how to code that. And I should use if function.
#include <stdio.h>
int main()
{
int i=0;
while (scanf("%d", &i) == 1)
{
if (i<3 || i>69)
{
fprintf(stderr,"Error: Input is too big or too small!");
return 101;
}
if (ISNT A NUMBER)
{
fprintf(stderr,"Error: Input isnt a number!");
return 100;
}
}
return 0;
}
CodePudding user response:
There are many ways to do this correctly:
Using scanf:
#include <stdio.h>
#include <stdlib.h>
int get_num() {
int i;
printf("Enter a number between 3 and 69: ");
fflush(stdout);
if (scanf("%d", &i) != 1) {
fprintf(stderr, "incorrect number of arguments, we need exactly one number (between 3 and 69)\n");
return -1;
}
if( i < 3 || i > 69 ) {
fprintf(stderr, "oops the number must be between [3, 69]\n");
return -2;
}
return i;
}
void eat_trash() {
int c;
while((c = getchar())!= '\n' && c !=EOF);
}
int main() {
int value;
while ((value = get_num()) <= 0 ) {
eat_trash();
}
printf("Got: %d\n", value);
}
A little extra but has interesting but (maybe slightly silly) things:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int stdin_copy;
int get_num() {
int i, rv = 0;
static int err_count = 0;
char *input = NULL;
size_t len = 0;
printf("Enter a number between 3 and 69: ");
fflush(stdout);
// gets a line (allocates memory we have to free)
rv = getline(&input, &len, stdin);
if ( rv > 3 ) {
err_count ; // see if we have a lot of garbage incoming
free(input);
if (err_count < 3 ) {
fprintf(stderr, "a number between 3 and 9 only needs two characters, try again. (%d tries left)\n", 3 - err_count);
return -3;
}
// just stop dealing with this silly user.
fprintf(stderr, "really? okay bye!\n");
exit(127);
}
rv = sscanf(input, "%d", &i);
free(input);
if (rv != 1) {
fprintf(stderr, "incorrect number of arguments, we need exactly one number (between 3 and 69)\n");
return -1;
}
if( i < 3 || i > 69 ) {
fprintf(stderr, "oops the number must be between [3, 69]\n");
return -2;
}
return i;
}
void eat_trash() {
fclose(stdin);
stdin = fdopen(stdin_copy, "r");
stdin_copy = dup(fileno(stdin));
}
int main() {
int value;
stdin_copy = dup(0);
while ((value = get_num()) <= 0 ) {
eat_trash();
}
printf("Got: %d\n", value);
}
The thing to note is the way trash is being consumed. The trouble with this is what happens if user pushes an input without \n
and then we are stuck in the way getline functions (also it can use up memory and that needing to free the input is annoying). So,
CodePudding user response:
is there a way how to check if input I have scanfed is a number? With IF function in C
The best is to read the user input line with fgets()
, (or getline()
if you have it) and then parse for an integer with strtol()
.
The troubles with scanf("%d", ...
include
- Leaving non-numeric input in
stdin
. - Not reading the entire line.
- Reading multiple lines when first ones are all white-space.
- Not detecting trailing nun-numeric input.
- Undefined behavior on
int
overflow.
Instead read a line and form a string. Then parse the string:
char *endptr;
long num = strtol(input_line_as_a_string, &endptr, 10);
if (input_line_as_a_string == endptr) {
printf("No conversion happened. Input is non-numeric\n");
} else if (num < 3 || num > 69) {
printf("Input %ld is out of range\n", num);
} else {
while (isspace(*endptr)) endptr; // skip trailing white-space
if (*endptr != '\0') {
printf("Input has trailing input\n");
} else {
printf("Success %ld\n", num);
}
}