Why this code is not re-prompting correctly? - c

I am totally new to C.
I want to re-prompt when the input value is not a number and when it's a number it should be less than 1. when I give any sort of string it works correctly. But when I give any number it goes to the next line without printing "Number: ".Then in the next line, it prints "Number: "again if the input value is less than 1.
int x;
printf("Number: ");
while (scanf("%d", &x) != 1 || x < 1 )
{
printf("Number: ");
scanf("%*s");
}
and the result it gives me is this
result

It would be wise to use fgets to read the line, then use sscanf to parse the input. That way, you can get the line, then check if sscanf succeeds!
Simple example:
int target_number; // The number you will have at the end of this.
while (1) { // Loop for rechecking number
char line[16]; // See notes on how to read the whole line.
fgets(line, sizeof(line), stdin);
// We use 1 here because sscanf returns the number of format specifiers that are matched. Since you only need one number, we use 1.
if (sscanf(line, "%d", &target_number) != 1) {
fprintf(stderr, "Invalid Input! Please enter in a valid number.");
continue;
}
}
// Do whatever you will with target_number
Notes
You can see how to read the whole line here.
This code is not safe!
It does not protect against buffer overflow attacks and the like. Please see this on the right way to do this. If this is just for learning, you don't need to worry.

/*This is how it will work the way you want.
If I understand your goal correctly, of course?
If your goal was different,
please specify and I will try to solve it.*/
#include<stdio.h>
int main(void)
{
int x;
printf("Number: ");
while (scanf("%d.%*d", &x)!=1 || x<0)
{
if(x<0)
{
printf("Number: ");
continue;
}
else
printf("Number: ");
scanf("%*s");
}
printf("Hello world!");
return 0;
}

Related

While loop misbehaving,

i am pretty new to c, i m trying to make the user input a number, but if they input a letter or word it shows a warning and asks for input again, my code works fine if the user puts in a number but it goes into an infinite loop if the user inputs something invalid, here is my code
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
}
printf("%.2f\n", salary);
return 0;
}
i thought that i was something to do with the buffer left over from the first scanf , but adding a space " %f" didnt work, i tried using fflush(stdin) after then scanf also didnt work. i m not sure what else i can try.
thanks in advance for any help.
You need to clear the buffer or it will keep evaluating it and cause the endless loop. Add one line after your invalid input: scanf("%*[^\n]")
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
scanf("%*[^\n]");
}
printf("%.2f\n", salary);
return 0;
}
This will work. You can see a better explanation here: Scanf and loops
The problem is that scanf won't advance the file stream. You ask it to read a floating point value and it isn't able to, so it doesn't consume the input.
For example, let's say your input is "foo", which isn't a number. Your scanf call isn't able to successfully read anything and returns 0. Then, in the next iteration, "foo" is still waiting to be read from stdin.
Try changing your if condition to something like
if (status == 0) {
char foo[256];
fgets(foo, sizeof(foo), stdin);
printf("Invalid input! Expected a nmuber, got: %s", foo);
}
Notice how the entire input is read from stdin by the gets call.

C Program - How to deny any non-numerical input

I've just started learning the language of C, and would love your help in cleaning up / simplifying my code if you know a better way to reach the following.
I want a program to ask for a number, and if that is found then proceed to print and end, however if anything else is put in (e.g. a letter key), then I want the program to loop asking for a number until one is given.
I started off by using a simple scanf input command, but this seemed to go into an infinite loop when I tried to check if a valid number (as we define them) was put in.
So instead I have ended up with this, from playing around / looking online, but I would love to know if there is any more efficient way!
//
// Name & Age Program
// Created by Ben Warren on 1/3/18.
//
#include <stdio.h>
int main (void)
{
//Setting up variables
int num;
char line[10]; /* this is for input */
//Collecting input
printf("Please enter any number? \t");
scanf("%d", &num);
//If Invalid input
while (num==0)
{
printf("\nTry again:\t");
fgets(line, 10, stdin); //turning input into line array
sscanf(line, "%d",&num); //scaning for number inside line and storing it as 'num'
if (num==0) printf("\nThat's not an number!");
}
//If Valid input
{
printf("\n%d is nice number, thank you! \n\n", num);
*}*
return 0;
}
Instead of checking if the value is different to 0, check the return value of
sscanf. It returns the number of conversions it made. In your case it should be 1. Unless the return value is 1, keep asking for a number.
#include <stdio.h>
int main(void)
{
int ret, num;
char line[1024];
do {
printf("Enter a number: ");
fflush(stdout);
if(fgets(line, sizeof line, stdin) == NULL)
{
fprintf(stderr, "Cannot read from stdin anymore\n");
return 1;
}
ret = sscanf(line, "%d", &num);
if(ret != 1)
fprintf(stderr, "That was not a number! Try again.\n");
} while(ret != 1);
printf("The number you entered is: %d\n", num);
return 0;
}
That is not a bad approach for someone new to C. One small improvement would be to actually check the return value of scanf(), since it returns the number of arguments successfully retrieved. Then you could get away from relying on num being 0 to indicate the input was valid. Unless you do want to specifically flag 0 as invalid input.
int ret = scanf("%d", &num);
ret == 1 would mean an integer was succesffully read into num, ret == 0 would mean it was not.
Consider using strtol to parse a string for a long int. This also allows you to detect trailing characters. In this example if the trailing character is not a newline, the input can be rejected. strtol can also detect overflow values. Read the documentation to see how that works.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
//Setting up variables
long int num = 0;
char line[40] = ""; /* this is for input */
char *parsed = NULL;
printf("Please enter any number? \t");
fflush ( stdout);
while ( fgets(line, 40, stdin))
{
parsed = line;//set parsed to point to start of line
num = strtol ( line, &parsed, 10);
if ( parsed == line) {//if parsed equals start of line there was no integer
printf("Please enter a number? \t");
printf("\nTry again:\t");
fflush ( stdout);
continue;
}
if ( '\n' != *parsed) {//if the last character is not a newline reject the input
printf("Please enter only a number? \t");
printf("\nTry again:\t");
fflush ( stdout);
}
else {
break;
}
}
if ( !parsed || '\n' != *parsed) {
fprintf ( stderr, "problem fgets\n");
return 0;
}
printf("\n%ld is nice number, thank you! \n\n", num);
return 0;
}
0 (zero) is a number...
But I see what you want to do...
You can check for a valid number, using isdigit or a combination of similar functions
I think its also important to follow the advice of other answers to use the return value from scanf using code such as:
int ret = scanf("%d", &num);
and examining ret for success or failure of scanf.

Verifying Input in C

I'm trying to write a simple binary calculator to get reaquainted with C. for some reason the first input verification works fine, and even though the second verification for the numbers is written in almost the same way, if the user enters faulty input, the while loop just loops infinitely without ever waiting for new user input. Here is the code, and thanks for the help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char operator[20];
char valid_operator[4] = "+-*/";
printf("Enter operator: ");
scanf("%s", operator);
printf("You entered: %s\n", operator);
while(strchr(valid_operator, (int)operator[0]) == NULL) {
printf("%s is not a valid operator. Enter +, -, /, or *: ", operator);
scanf("%s", operator);
}
The code works up until here. This next part is thrown into an infinite loop if the user enters faulty input the first time. The re-prompting never happens.
int input1;
int input2;
printf("Enter the two inputs (separated by whitespace): ");
int num_ints = 1;
num_ints = scanf("%d %d", &input1, &input2);
printf("Input 1: %d. Input 2: %d.\n", input1, input2);
while(num_ints < 2){
printf("Invalid input. Enter two integers separated by whitespace: ");
num_ints = 0;
num_ints = scanf("%d %d", &input1, &input2);
printf("Input 1: %d. Input 2: %d.\n", input1, input2);
}
return 0;
The reason it loops infinitely without ever waiting for new user input is that when scanf fails to read a char in the requested format (%d in your case) it won't advance the file pointer and at the next iteration of the loop it will try to read the same incorrect char again.
This is consistent with POSIX: http://pubs.opengroup.org/onlinepubs/009695399/functions/fscanf.html
if the comparison shows that they are not equivalent, the directive shall fail, and the differing and subsequent bytes shall remain unread.
Also, return value from the man scanf:
...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.
So, you better combine fgets and sscanf.
do {
char buf[BUFSZ];
printf("Enter the two inputs (separated by whitespace): ");
if(fgets(buf, BUFSZ, stdin) == NULL)
{
/* Error exit. */
break;
}
num_ints = sscanf(buf, "%d %d", &input1, &input2);
} while(num_ints != 2);
You need to clear stdin. If you input a non-integer in your example "1 t", "t" is not consumed (left in the stream). Add this to your loop:
while(num_ints < 2){
while (fgetc(stdin) != '\n'); // clear input
. . .
See C program loops infinitely after scanf gets unexpected data for a good description of the issue.

How to check if the user input an integer using scanf

I created a program to make a diamond out of *'s. I am looking for a way to check if the type of input is an integer in the C language. If the input is not an integer I would like it to print a message.
This is what I have thus far:
if(scanf("%i", &n) != 1)
printf("must enter integer");
However it does not display the message if it's not an integer. Any help/guidance with this issue would be greatly appreciated!
you can scan your input in a string then check its characters one by one, this example displays result :
0 if it's not digit
1 if it is digit
you can play with it to make your desired output
char n[10];
int i=0;
scanf("%s", n);
while(n[i] != '\0')
{
printf("%d", isdigit(n[i]));
i++;
}
Example:
#include <stdio.h>
#include <string.h>
main()
{
char n[10];
int i=0, flag=1;
scanf("%s", n);
while(n[i] != '\0'){
flag = isdigit(n[i]);
if (!flag) break;
i++;
}
if(flag)
{
i=atoi(n);
printf("%d", i);
}
else
{
printf("it's not integer");
}
}
Use fgets() followed by strtol() or sscanf(..."%d"...).
Robust code needs to handle IO and parsing issues. IMO, these are best done separately.
char buf[50];
fgets(buf, sizeof buf, stdin);
int n;
int end = 0; // use to note end of scanning and catch trailing junk
if (sscanf(buf, "%d %n", &n, &end) != 1 || buf[end] != '\0') {
printf("must enter integer");
}
else {
good_input(n);
}
Note:
strtol() is a better approach, but a few more steps are needed. Example
Additional error checks include testing the result of fgets() and insuring the range of n is reasonable for the code.
Note:
Avoid mixing fgets() and scanf() in the same code.
{ I said scanf() here and not sscanf(). }
Recommend not to use scanf() at all.
strtol
The returned endPtr will point past the last character used in the conversion.
Though this does require using something like fgets to retrieve the input string.
Personal preference is that scanf is for machine generated input not human generated.
Try adding
fflush(stdout);
after the printf. Alternatively, have the printf output a string ending in \n.
Assuming this has been done, the code you've posted actually would display the message if and only if an integer was not entered. You don't need to replace this line with fgets or anything.
If it really seems to be not working as you expect, the problem must be elsewhere. For example, perhaps there are characters left in the buffer from input prior to this line. Please post a complete program that shows the problem, along with the input you gave.
Try:
#include <stdio.h>
#define MAX_LEN 64
int main(void)
{ bool act = true;
char input_string[MAX_LEN]; /* character array to store the string */
int i;
printf("Enter a string:\n");
fgets(input_string,sizeof(input_string),stdin); /* read the string */
/* print the string by printing each element of the array */
for(i=0; input_string[i] != 10; i++) // \0 = 10 = new line feed
{ //the number in each digits can be only 0-9.[ASCII 48-57]
if (input_string[i] >= 48 and input_string[i] <= 57)
continue;
else //must include newline feed
{ act = false; //0
break;
}
}
if (act == false)
printf("\nTHIS IS NOT INTEGER!");
else
printf("\nTHIS IS INTEGER");
return 0;
}
[===>] First we received input using fgets.Then it's will start pulling each digits out from input(starting from digits 0) to check whether it's number 0-9 or not[ASCII 48-57],if it successful looping and non is characters -- boolean variable 'act' still remain true.Thus returning it's integer.

C programming - Repeat scanf until only numbers are input

What I wan't to do is check if my input is a number and then continue, else print out wrong format and ask for a new input. What I get is an endless loop printing "Wrong format"
This is my function for the input number:
void input_number(int *number)
{
printf("Number: ");
if ( scanf("%d", number) == 1 )
return 0;
else
{
printf("-> Wrong format, try again! <-\n");
input_number(number); // start over
}
}
When I run the program I want it to look something like this:
Number: hello
-> Wrong format, try again! <-
Number: 4
and go on....
Try this : ( beware there are a lot of much better ways to do this )
void input_number(int *number)
{
int flag=1;
printf("Number: ");
while(flag==1){
if ( scanf("%d", &number) == 1 ){ // also you were missing & specifier
flag = 0;
//return 0;
}else{
printf("-> Wrong format, try again! <-\n");
getchar(); // to catch the enter from the input -- make sure you include stdlib.h
}
}
return 0;
}
Output:
Number: f
-> Wrong format, try again! <-
Number: f
-> Wrong format, try again! <-
Number: d
-> Wrong format, try again! <-
Number: d
-> Wrong format, try again! <-
Number: s
-> Wrong format, try again! <-
Number: s
-> Wrong format, try again! <-
Number: s
-> Wrong format, try again! <-
Number: s
-> Wrong format, try again! <-
Number: 6
I think the problem is that if the scanf() fails because of either EOF or because there's a non-numeric character in the input stream, that problem still exists when you next call it, so it fails again, and this continues until the program runs out of resources or you run out patience.
At the very least, you need to distinguish between:
OK
EOF (nothing more to read)
Error (more to read, but the next character at least is not part of a number)
If you are expecting a single number per line, then it is probably best to use fgets() and sscanf(). If you are happy with multiple numbers per line, then you have to work a bit harder. You should probably also return a value from the function to indicate whether it was successful or not.
int input_number(int *number)
{
char line[4096];
while (printf("Number: ") > 0 && fgets(line, sizeof(line), stdin) != 0)
{
if (sscanf(line, "%d", number) == 1)
return 0;
printf("-> Wrong format, try again! <-\n");
}
return EOF;
}
int input_number(int *number)
{
while (printf("Number: ") > 0 && scanf("%d", number) != 1)
{
int c;
if (feof(stdin) || ferror(stdin))
return EOF;
printf("-> Wrong format, try again! <-\n");
while ((c = getchar()) != EOF && c != '\n')
;
if (c == EOF)
return EOF;
}
return 0;
}
Note the correct use of feof(); an I/O operation has failed and the code needs to distinguish between EOF and I/O errors and format errors.
In the second function, if the printf() fails, you are erroneously told that a number was read. If that's a problem, add extra tests, but that code is already harder to write than the code using fgets(), so be cautious about deciding to use it.
Note that the original code had return 0; in a function returning void. The code should have been rejected by the compiler.
Try using a loop that checks the user input and tries to parse it to an int. If it doesn't succeed, it can keep asking the user for input until they enter an actual int.
At this point you probably know that there are few flaws in your code and recursion isn't the best idea. This one is an attempt to make your code work, pretty or not.
void input_number(int *number)
{
printf("Number: ");
if ( scanf("%d", number) == 1 )
return 0;
else
{
scanf("%*s"); /* <--this will read and discard whatever caused scanf to fail */
printf("-> Wrong format, try again! <-\n");
input_number(number); // start over
}
}

Resources