integer validation gives infinite loop - c

The user needs to type an integer, then type enter. If it gets validated then it should return the integer, if not validated the user should get an error message.
When I try to validate input through getInt() function, I get an infinite loop when I type 1 or more chars. When I type abc, I get an infinite loop of error messages, while entering 1a gets the correct validation (1 single error message). I followed the directions of this flowchart:
Code
#include <stdio.h>
void clrKyb(void){
char input;
do {
scanf("%c",&input);
} while(input !='\n');
}
int getInt(void){
char NL= 'x' ;
int value ;
while(NL!='\n'){
scanf("%d%c",&value,&NL);
if(NL!='\n') {
void clrKyb(void);
printf("Invalid integer, please try again:");
}
}
return value ;
}
int main(void) {
int iVal;
printf("Enter an integer: ");
iVal = getInt();
printf("You entered: %d\n", iVal);
return 0;
}

As noted in comments:
cxw said:
In getInt, void clrKyb(void); should just be clrKyb();, since you are wanting to use the clrKyb you have already defined.
Jonathan Leffler said:
Note that in clrKyB() (and getInt()), you need to check the return value from scanf(). If it returns EOF, then no amount of retrying etc is going to stop an infinite loop. (As cxw notes, in getInt() at the moment, you (re)declare clrKyB() and don't call it — that's also a problem.)

Related

unexpected result when i entered character instead of integer value in scanf

here is my code where i am facing a problem regarding datatypes in c
#include<stdio.h>
int main()
{
int a,b;
scanf("%d",&b);
printf("%d",b);
}
When In Entered Any Character Instead Of Integer values It always Prints 32. Am Not Getting Why Its printing 32.
The value that gets printed is completely arbitrary. It is a result of undefined behavior, because b remains unassigned.
You need to check that the user has entered a value before proceeding. scanf returns the number of items that it has processed, so your code should not use the value unless scanf has returned 1, indicating that one item has been read successfully:
int b;
for (;;) { // Repeat forever
int numRead = scanf("%d",&b);
if (numRead == 1) {
// We've got our number; end the loop:
break;
}
printf("You did not enter a number\n");
// Consume the data that cannot be interpreted as a number.
// Asterisk means "discard the value":
scanf("%*s");
}
printf("b=%d\n", b);
Demo.
If you try the following modification, you might get some insight:
#include<stdio.h>
int main()
{
int a, b;
a = scanf("%d",&b);
printf("%d %d",a,b);
}
When you type anything other than an integer, scanf returns 0, meaning that none of the items in the argument list was successfully filled. That means b has whatever value it had before the call to scanf. Since b is never initialized, this value is undefined.
P.S. Your main function should return type int, not void.

program running infinite times if entered character sometimes and sometimes not

this is a menu driven program having two functions. everything works fine if i enter numbers but when i enter character it runs infinite times sometimes :(
like when i enter integers it works fine and if i enter char it shows some junk value and then try again option is showed and i again enter char it runs infinite times
#include<stdio.h>
#include<conio.h>
#include<math.h>
void cal()
{
int x,y,z;
printf("enter two numbers\n");
scanf("%d%d",&x,&y);
z=x+y;
printf("%d\n",z);
}
void mul()
{
int x,y,z;
printf("enter two numbers\n");
scanf("%d%d",&x,&y);
z=x*y;
printf("%d\n",z);
}
void main()
{
int x,c;
clrscr();
menu :
printf("1.sum\n");
printf("2.mul\n");
printf("enter choice\n");
scanf("%d",&x);
switch(x)
{
case 1:cal();break;
case 2:mul();break;
default :printf("try again\n");
}
printf("press 5 to run another function\n");
scanf("%d",&c);
if(c==5)
{
goto menu;
}
getch();
}
You could try updating your gcc compiler. I ran the code on gcc 4.8 and the code terminated well for characters as well.
Otherwise if you really want to handle characters as well you take an input using a char pointer (string that is ) and then using atoi(str) store it in an int variable and then process it. And you can check : if the user enters characters ( using isalpha() ) then terminate the code.
Sample Code : (ran well enough)
char *s = malloc(64);
scanf("%s",s);
if(isalpha(s[0]))
return ;
else
int x = atoi(s);
int sum = x + 1; //or whatever manipulations you need to do
"when i enter character it runs infinite times sometimes ..."
All the code that tries to read an int uses the following of some sort. When non-numeric data is entered, scanf("%d", ... does not consume that IO (leaving it for the next IO operation), does not set c to any value, and then returns a 0 (which is not tested). At that point c has whatever value it had before the scanf() call. Since c was not initialized, its value could be anything - hence undefined behavior as suggested by #BLUEPIXY
int c;
...
scanf("%d",&c);
Since the non-numic data is left for the next IO and the next IO could be another scanf("%d", code is stuck in a rut - infinite loop.
To best fix, initialize variables, get the user input via fgets() and detemrine the value via sscanf() or strtol().
int c = 0;
char buf[80];
if (fget(buf, sizeof buf, stdin) == NULL) Handle_EOForIOerror();
if (sscanf(buf, "%d",&c) != 1) Handle_NonNumericInpupt();

Trouble figuring out logic for while/if loop in C

I have a some code, and the function I am having trouble with is this:
unsigned int getInputData() {
printf("Please input a positive integer number terminated with a carriage return.\n");
do{
scanf("%c", &input);
if(isdigit(input)) {
temp = charToInt(input);
rValue = mergeInt(rValue, temp);
}
if(rValue >= imax) {
rValue = 0;
printf("ERROR: That is too large of an integer. Please try again. \n");
}
else if(isalpha(input)){
rValue = 0;
printf("This is not a integer. Please try again. \n");
}
else{
printf("OK. This is a good number. \n");
}
} while(1);
}
I'm scanning in each char individually, merging it into an int. Which is exactly what I want to do BUT I only want it to print "OK. This is a good number." once when the user types it in. Example: If someone was to type in: 12345 I want it to return: "OK. This is a good number." once for those 5 char rather than once each. Hoping this makes sense, been at it for awhile so anything will help.
There's huge logic problems behind your code:
You loop infinitely without checking for end of input:
You say you want to tell whether this is a good number when the user inputs several digits, but you do only read one character at a time, and you do not define how a number ends.
Though you do specify to end with a carriage return, you did not design your algorithm that way, you never check for the \n character.
You define a return value for the getInputData() function but you do never return from that function.
You test whether input is a digit to update the value, but for errors you do show an error only if it's an alphabetic character.
Basically, to keep with the way you wrote your algorithm, here's another take:
unsigned int getInputData() {
char input;
long value=0;
do {
scanf("%c", &input);
if (isdigit(input))
value = value*10+input+'0';
else if (input == '\n')
return 1;
else
return 0;
} while(1);
}
int main() {
printf("Please input a positive integer number terminated with a carriage return.\n");
if (getInputData() == 1)
printf("OK. This is a good number.\n");
else
printf("This is not a integer. Please try again. \n");
return 0;
}
but I do exit from the infinite loop to be able to check the result.
N.B.: for the purpose of the example, I did not check for overflows.
N.B.1: I kept using scanf() to stay close to your code, but if you only want to read one character at a time, it is better to use getchar() which is way simpler and faster.
N.B.2: you can also simplify your code by using more features of scanf():
unsigned int getInputData() {
unsigned input;
long value=0;
int n;
do {
n = scanf("%u", &input);
if (n == 0)
return 0;
else
return 1;
} while(1);
}
You may even try to use scanf("%a[0-9]") which is a GNU extension. See man scanf for more details.

Infinite loop code in C

In the below program I try to input a number between 1 to 100 but if I enter a 'character' or "string" ( like s or sova ) during the execution time of scanf() statement it creates a infinite loop. so I try to do .... when I input a string or a character it shown me a message like "wrong value entered. enter again" and it will enter again...
Thanx;
#include<stdio.h>
int main()
{
int a;
scanf("%d",&a);
while(!(a>=1&&a<=100))
{
printf("wrong value entered. enter again\n");
scanf("%d",&a);
}
printf("you enter %d. Thanxz",a);
return 0;
}
You need to check the return value of scanf
If the user has not entered a integer, you need to eat the input. The scanf function will continually say not a integer, try again. So if scanf returns 0 you need to deal with it
When you use scanf you are working with buffered input, this means that when you enter a value say "123" and press ENTER then "123" plus the ending character (ENTER) will all be added to the buffer. scanf then removes 123 since %d specifies that an integer should be read but if a user enters something invalid like a string instead then the buffer will not be emptied.
A better way to read input from the keyboard is to use fgets() where you specify a max length to read. Once you have the input you can use sscanf() to retrieve the numeric value from it. The ENTER till then not irritate your input.
char buffer[128];
fgets( buffer, 128, stdin );
sscanf( buffer, "%d", &a );
Also always check return values from functions as a rule of thumb so that you can do appropriate action if the function fails.
If the return value from scanf is not equal to the number of item you like the user to input, read all characters of the input buffer until there is a '\n'. But instead of copying a whole loop over and over again to the places in your code where the user should input something, you could wrap the loop in a function like this:
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
void input(const char *format,...)
{
va_list ap;
int r;
/* number of items [to read] */
int noi=0;
for(r=0;r<strlen(format)-1;r++)
{
if(format[r]=='%')
{
if(format[r+1]!='%')
noi++;
else
r++;
}
}
do
{
va_start(ap,format);
r=vscanf(format,ap);
va_end(ap);
if(r!=noi)
{
switch(r)
{
case EOF:
case 0:
printf("All wrong, try again!\n");
break;
default:
printf("Unexpected value after item no %d!\n",r);
}
while(getc(stdin)!='\n');
}
else
break;
} while(1);
}
Hope that helps,
Jan
Try this.
#include <stdio.h>
#define FLUSH while (getchar() != '\n') // macro to eat invalid input
int main (void) {
int a = 0;
printf ("Enter an integer: ");
scanf("%d", &a);
while (a < 1 || a > 100) {
FLUSH;
printf("Invalid input. Please try again: ");
scanf("%d",&a);
}
printf("You entered %d.\nThanks!\n", a);
return 0;
}
Your code shows several coding habits that need to be changed:
Include (void) in the parameter list of main().
Leave spaces on either side of binary operators: while(!(a>=1&&a<=100)) is needlessly ugly and hard to read.
Simplify your logical expressions. Why use (! (a>=1 && a<=100)) when it means the same thing as (a < 1 || a > 100), and the latter is so much easier to read?
Prompt for user input when needed. Don't have the cursor just sit at a blank line with no indication to the user about what to do.
Use proper grammar and capitalization in your prompts. There's no reason to be lazy in your programming.

entering a char using scanf and saving it in an int can cause undefined behaviour?

I am working on a code, and I tried to enter a char instead of integer, and the result was '2' regardless of the character I entered, is it undefined behaviour or some thing else ?
The code:
#include <stdio.h>
int f1(int n);
int f2(void);
int main(void)
{
int t;
printf("Enter a number: ");
scanf("%d", &t);
/* print proper message */
t ? f1(t) + f2() : printf("zero entered.\n");
return 0;
}
int f1(int n)
{
printf("%d ", n);
return 0;
}
int f2(void)
{
printf("entered.\n");
return 0;
}
when I entered a, the result was "2 entered", and when I entered g the result was "2 entered" and when I entered i,h,k,..... the result was the same. What is that?
If scanf() encounters something it cannot parse based on the specified format string, it simply stops and returns early. So it never writes anything to t (you're just seeing whatever indeterminate value t had before the call).
To handle this, you should always examine the return value of scanf.
It is because scanf failed to parse you input. It expects you to enter a decimal digits since you used %d.
You have to check the return value of scanf to avoid this kind of behavior :
On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.
So :
int items_matched;
// ...
items_matched = scanf("%d", &t); // Get the return value
if ( items_matched != 1 ) // Check it
{
printf("Matching failure with scanf.\n");
return 0;
}
else
{
if ( t == 0 )
printf("zero entered\n");
else
printf("%d entered\n", t);
}
You don't need your f1(t) + f2() who is quite confusing...
The problem is, as you say, that scanf using %d format is expecting you to enter one or more ascii digits. It stops scanning the input at a non-digit character, so it never reads what you type and t has whatever value it had before the scant was called.
You need to check the return code of scanf. Have a look at the manpage:
Return Value
These functions 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.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.
In other words, scanf does not write anything into t, it's uninitialized the whole time.
So, instead of this:
scanf("%d", &t);
try this:
int items_matched = scanf("%d", &t);
if (items_matched != 1) {
printf("bad number entered\n");
exit(1);
}
From the Linux man page
The format string consists of a sequence of directives which describe
how to process the sequence of input characters. If processing of a
directive fails, no further input is read, and scanf() returns. A
"failure" can be either of the following: input failure, meaning that
input characters were unavailable, or matching failure, meaning that
the input was inappropriate.
In the C11 standard description of scanf (7.21.6.4 The scanf function) section 3:
The scanf function returns the value of the macro EOF if an input
failure occurs before the first conversion (if any) has completed.
Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the
event of an early matching failure.
Emphasis is mine . So as #oli charlesworth said you should check the return value of scanf when in doubt :)

Resources