//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
}
Related
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);
}
}
This is the code why when I show in output the string I have all words but with in the final row a strange symbol , an ASCII random symbol...
My objective is to save in a string all words to operate with it.
For example I have this document:
Mario
Paul
Tyler
How can i save all words in a string??
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int l,i=0,j=0,parole=0;
char A[10][10];
char leggiparola;
char testo[500];
FILE*fp;
fp=fopen("parole.txt","r");
if(fp!=NULL)
{
while(!feof(fp))
{
fscanf(fp,"%c",&leggiparola);
printf("%c", leggiparola);
testo[j]=leggiparola;
j++;
}
}
fclose(fp);
printf("%s",testo);
return 0;
}
Besides while(!feof(fp)) being "always wrong" you miss to 0-terminate the result string.
To do so place a
testo[j] = '\0'
just after the while-loop.
Instead of using fscanf, try with getc:
int leggiparola; /* This need to be an int to also be able to hold another
unique value for EOF besides 256 different char values. */
...
while ( (leggiparola = getc(fp)) != EOF)
{
printf("%c",leggiparola);
testo[j++] = leggiparola;
if (j==sizeof(testo)-1)
break;
}
testo[j] = 0;
Here's fslurp. I't a bit messy due to the need to grow the buffer manually.
/*
load a text file into memory
*/
char *fslurp(FILE *fp)
{
char *answer;
char *temp;
int buffsize = 1024;
int i = 0;
int ch;
answer = malloc(1024);
if(!answer)
return 0;
while( (ch = fgetc(fp)) != EOF )
{
if(i == buffsize-2)
{
if(buffsize > INT_MAX - 100 - buffsize/10)
{
free(answer);
return 0;
}
buffsize = buffsize + 100 * buffsize/10;
temp = realloc(answer, buffsize);
if(temp == 0)
{
free(answer);
return 0;
}
answer = temp;
}
answer[i++] = (char) ch;
}
answer[i++] = 0;
temp = realloc(answer, i);
if(temp)
return temp;
else
return answer;
}
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 )
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;
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;
}