Checking whether input is number in C - c

I need to check whether the input is number. My code looks something like this:
int input;
while ( scanf(" %s %d", string, &input) != EOF) {
if ( isNotANumber(input) ) {
printf("Not a number"); }
doSomethingElse(input, string);
}
EDIT: I need to be accepting input and calling the function doSomethingElse(input) until the user enters EOF.
isNotANumber is a mock function, I don't have that function, I'm asking how could I write it.
EDIT 2: Variable string needs to be a string, variable input needs to be an integer.
EDIT 3: I tried separating my code into this:
while (scanf(" %s", string) != EOF) {
if (scanf("%d",&input) != 1) {
printf("not a number");
}
doSomething();
}
But it stil doesn't work for input like "4a".

For example, you can change it as follows.
#include <stdio.h>
#define doSomethingElse(input) do{ printf("your input is %d\n", input); }while(0)
int main(void){
int input;
int status;
while ((status = scanf("%d", &input)) != EOF) {
if ( status == 0 ) {
printf("Not a number\n");
while(getchar() != '\n'); //clear input
}
else {
doSomethingElse(input);
}
}
}
However, this can not check input like 123.456. (accept 123)
So, It is recommended to input with fgets and check with strtol.
As already pointed out, like scanf(" %s %d", string, &input) can not check the input after the number.
So, For convenience, check backward input.
char string[32], ch;
int input;
int status;
while ((status = scanf("%31s %d%c", string, &input, &ch )) != EOF) {
if ( status == 3 && ch == '\n') {
doSomethingElse(input);
}
else {
printf("Not a number\n");
while(getchar() != '\n'); //clear input
}
}
Example using fgets and strtol
(mystrtoi has reorganized the answer of chux. thanks)
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#define doSomethingElse(input) do{ printf("your input is %d\n", input); }while(0)
int mystrtoi(const char *str, int *err) {
char *endptr;
*err = errno = 0;
long l = strtol(str, &endptr, 0);
if (errno == ERANGE || *endptr != '\0' || str == endptr) {
*err = 1;
}
// Only needed if sizeof(int) < sizeof(long)
if (l < INT_MIN || l > INT_MAX) {
*err = 1;
}
return (int) l;
}
int main(void){
char line[128];
char string1[32], string2[128];
int num, err;
while (fgets(line, sizeof line, stdin)){
// if(2 != sscanf(line, "%31s %31s", string1, string2)){// or use strtok to split
if(2 != sscanf(line, "%31s %127[^\n]", string1, string2)){
printf("invalid input\n");
continue;
}
num = mystrtoi(string2, &err);
if(err) {
printf("Not a number\n");
}
else {
doSomethingElse(num);
}
}
}

while ( scanf("%d", input) != EOF)
Your scanf code has two problems:
scanf returns the number of successfully read item, not EOF. Here you want to check if scanf has successfully read one integer input
scanf expects the address of the variable
You should re-write that line as:
while ( scanf("%d", &input) == 1 )

Related

Is there a way how to check if input I have scanfed is a number? With IF function in C?

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;
}
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,
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);
}
}

loop is running Infinitely

I have written the below small code with several conditions on number entered by the user
#include<stdio.h>
int main()
{
int userInput;
while(1)
{
printf("Press '1':To Print\n");
scanf("%d",&userInput);
if(userInput==1)
{
printf("ABCD\n");
}
else
{
printf("WARNING:Pressed invalid key");
}
}
}
When I press any number then it works fine, but when I press up arrow/any character key and press enter the loop runs infinite times.
Why is this happening and is there any way to prevent it?
You're not checking whether scanf failed. May something like this help?
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
void printHelp(bool afterInvalid) {
if(afterInvalid)
fprintf(stderr, "\nInvalid input, try again!\n");
printf("Press 1 to print\nPress 3 to break\nInput: ");
}
int main() {
while(1) {
int userInput;
printHelp(false);
if(scanf("%d", &userInput) == 0) {
char ch;
bool reachedNewline = false;
do {
if(reachedNewline) {
printHelp(true);
reachedNewline = false;
}
ch = getchar();
if(ch == '\n')
reachedNewline = true;
} while(!isdigit(ch));
ungetc(ch, stdin);
continue;
}
if(userInput == 1)
printf("ABCD\n");
else if(userInput == 3) {
printf("Breaking!\n");
break;
} else
printHelp(true);
}
return 0;
}
this makes it an infinite loop that keep asking to print..
#include<stdio.h>
int main()
{
int userInput;
while(1!=EOF)
{
printf("Press '1':To Print\n");
scanf("%d",&userInput);
if(userInput==1)
{
printf("ABCD\n");
}
else
{
printf("WARNING:Pressed invalid key");
}
}
}
Check the return value from scanf("%d"... and consume the non-numeric input as needed.
#include<stdio.h>
int main(void) { // Add void
int ch = 0;
while (ch != EOF) {
int userInput;
printf("Press '1':To Print\n");
// Expect 0, 1 or EOF to be returned
int fields_scanned = scanf("%d",&userInput);
if (fields_scanned == 1) {
printf("ABCD %d\n", userInput);
}
else if (fields_scanned == 0) {
printf("WARNING:Pressed invalid key\n");
}
// Consume remaining characters in the line
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
;
}
}
return 0; // Not required, yet good practice.
}
All in all, recommend using fgets()/other code instead of scanf()
#define INT_MAX_SIZE (sizeof (int) * CHAR_BITS /3 + 3)
fputs(Prompt, stdout);
char buf[INT_MAX_SIZE*2 +1]; // I like 2x expected size, no need to be stingy here.
if (fgets(buf, sizeof buf, stdin) == NULL) break; // No more input or error
// Use sscanf() or strtol(), etc
if (sscanf(buf, "%d", &userInput) == 1) {
; // Success
} else {
; // Failure
}

How to check for a blank space with scanf("%s", answer)

So, I'm working on this program and I've encountered a problem with scanf. I'm scanning the input from the user in the form of a string, however if the user just presses enter, scanf doesn't pick up on it and the cursor just moves on waiting for whatever specified input I programmed it to look for. Is there anyway I can skirt around this with like a comparison to 0 or 1, or do I need to go about this in another way? Yes, this is the same program from earlier and I thought to mention this in the other post I made, but I figured this was a different problem in itself so it deserved another post separate from my other problem earlier.
/*
* Scott English
* CS 1412
* tconv
* 1/28/15
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *
input_from_args(int argc, const char *argv[])
{
if (argc == 1){
return stdin;
}
else {
return fopen(argv[1], "r");
}
}
void
rot_13(FILE *src, FILE *dest)
{
int c,j;
while ((c = getc(src)) != EOF)
{
if(c>= 'A' && c <= 'Z')
{
if((j = c + 13) <= 'Z')
c = j;
else
{
j = c - 13;
c = j;
}
}
else if(c >= 'a' && c <= 'z')
{
if((j = c + 13) <= 'z')
c = j;
else
{
j = c - 13;
c = j;
}
}
else
c = c;
fprintf(dest, "%c", c);
}
}
void
convert_all_upper(FILE *src, FILE *dest)
{
int c;
while ((c = fgetc(src)) != EOF)
{
fprintf(dest, "%c", toupper(c));
}
}
void
convert_all_lower(FILE *src, FILE *dest)
{
int c;
while ((c = fgetc(src)) != EOF)
{
fprintf(dest, "%c", tolower(c));
}
}
void
print_all(FILE *src, FILE *dest)
{
int c;
while ((c = fgetc(src)) != EOF)
{
fprintf(dest, "%c", c);
}
}
int
main(int argc, const char *argv[])
{
char answer[4];
FILE *src = input_from_args(argc, argv);
FILE *dest = stdout;
printf("Please enter which conversion -r -u -l\n");
scanf("%s", answer);
if (src == NULL)
{
fprintf(stderr, "%s: unable to open %s\n", argv [0], argv[1]);
exit(EXIT_FAILURE);
}
else if (strcmp(answer,"-r") == 0)
{
rot_13(src, dest);
}
else if (strcmp(answer, "-u") == 0)
{
convert_all_upper(src, dest);
}
else if (strcmp(answer, "-l") == 0)
{
convert_all_lower(src, dest);
}
else
{
printf("%s: is unsupported\n", answer);
}
fclose(src);
return EXIT_SUCCESS;
}
ESTRAPOLATED FROM LINK
scanf stands for "scan formatted" and there's precious little less formatted than user-entered data. It's ideal if you have total control of the input data format but generally unsuitable for user input.
Use fgets() to get your input into a string and sscanf() to evaluate it.
A simple program to show you how to intercept the 'enter' key.
#include<stdio.h>
#include<string.h>
int main()
{
char answer[4];
memset(answer, 0x00, sizeof(answer));
printf("Please enter which conversion -r -u -l\n");
fgets (answer, sizeof(answer), stdin);
if (strlen(answer) > 0)
{
if (answer[0] == '\n')
{
printf("Empty string and enter key pressed\n");
}
else
{
printf("Parameter %s", answer);
}
}
return 0;
}
I recommend using fgets:
fgets(answer, sizeof answer, stdin);
instead of scanf, since scanf skips over whitespace including newlines, and the user won't be able to get out of the input loop.
"if the user just presses enter, scanf doesn't pick up on it" -->
scanf("%s", answer) is just beginning.
The "%s" specifies scanf() to scan 3 things:
1) Scan in and toss all leading white-space including '\n', ' ', '\t' and a few others.
2) Scan in and save an unlimited number of non-white-space char to answer. Append a terminating '\0' when done.
3) Upon scanning a white-space again, put that char back into stdin for later reading.
So when a user enters Enter or '\n', scanf("%s", answer) is still in step 1.
As a rule: mixing scanf() with fgets()/getc() is problematic. Further recommend against using scanf() for just about all applications. Consider:
// char answer[4];
// scanf("%s", answer);
char answer[4+1];
if (fgets(answer, sizeof answer, stdin) == NULL) return 1; // stdin closed
// now remove the potential trailing '\n`.
size_t len = strlen(answer);
if (len > 0 && answer[len-1] == '\n') answer[--len] = 0;

string in place of int in c

//why the code starts printing retry infinitely if i wrongly
enter a string in place of int i in terminal
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char const *argv[])
{
int i,j=0;
while(1)
{
scanf("%d",&i);
if(i==10)
{
printf("you got the max! YOU WON\n");
break;
}
else
{
printf("%s\n","retry" );
}
}
return 0;
}
Try consuming (flushing) on bad input:
else {
while ((j = fgetc(stdin)) != '\n' && j != EOF);
printf("%s\n", "retry");
}
An alternative using fgets (is preferable because it consumes the whole line) and strtol:
#include <stdio.h> /* fgets, printf */
#include <stdlib.h> /* strtol */
#include <string.h> /* strchr */
int main(void) /* No args */
{
char buf[128], *p;
int i;
while (fgets(buf, sizeof(buf), stdin)) {
if ((p = strchr(buf, '\n')) != NULL) {
*p = '\0'; /* remove newline */
}
i = (int)strtol(buf, &p, 10); /* Base 10 */
if (*p != '\0' || i != 10) {
printf("retry\n");
} else {
printf("you got the max! YOU WON\n");
break;
}
}
return 0;
}
Read fails because of you inputted wrong type and i will have garbage value.
Add initialization to i:
int i=0, j=0;
scanf returns number of succesful reads. Add return value check to scanf:
int r = scanf("%d",&i); // Will return 1 if 1 argument was successully read
if(r == 1 && i == 10)
{
//do something
}
Edit:
As others have pointed out, it seems that scanf doesn't consume incoming bytes if input is wrong. Thus you might want to replace it wit fgets and sscanf:
int r;
char temp[32];
fgets(temp, 32, stdin); // Read input to temporary buffer
r = sscanf(temp, "%d", &i); // Try to convert value on buffer
if(r == 1 && i == 10)
{
//do something
}

do-while loop for checking users input using c

I'm using this piece of code to read users input and check if it is a number or not.But sincerly it just works for numbers and letters. I want it to work with every char. For example "!?%". I have already tried to change the "isalnum" by "isascii" but that does not work.
#include <stdio.h>
#include <ctype.h>
int main ()
{
int a;
int b = 1;
char c ;
do
{
printf("Please type in a number: ");
if (scanf("%d", &a) == 0)
{
printf("Your input is not correct\n");
do
{
c = getchar();
}
while (isalnum(c));
ungetc(c, stdin);
}
else
{
printf("Thank you! ");
b--;
}
}
while(b != 0);
getchar();
getchar();
return 0;
}
Unless you have specific requirements, you should use fgets and sscanf
while (1) {
char buf[1000];
printf("Please input a number: ");
fflush(stdout);
if (!fgets(buf, sizeof buf, stdin)) assert(0 && "error in fgets. shouldn't have hapenned ..."):
/* if enter pending, remove all pending input characters */
if (buf[strlen(buf) - 1] != '\n') {
char tmpbuf[1000];
do {
if (!fgets(tmpbuf, sizeof tmpbuf, stdin)) assert(0 && "error in fgets. shouldn't have hapenned ...");
} while (buf[strlen(tmpbuf) - 1] != '\n');
}
if (sscanf(buf, "%d", &a) == 1) break; /* for sufficiently limited definition of "numbers" */
printf("That was not a number. Try again\n");
}
A correct way in strictly C89 with clearing input buffer, checking overflow looks like:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int readLong(long *l)
{
char *e,in[20];
fgets( in,20,stdin );
if(!strchr(in,'\n')) while( getchar()!='\n' );
else *strchr(in,'\n')=0;
errno=0;
*l=strtol(in,&e,10);
return *in&&!*e&&!errno;
}
int main()
{
long l;
if( readLong(&l) )
printf("long-input was OK, long = %ld",l);
else
puts("error on long-input");
return 0;
}

Resources