So this is the code:
int num, counter = 1;
while (counter == 1)
{
printf_s("Enter a 5-digit integer :");
scanf_s("%d",&num);
if (num < 10000 || num > 99999)
{
puts("Please make sure the number you entered has 5 digits!\n");
}
else if((num0000 - num000)/10000 == num && (num0-num) == (num000-num00)/100 )
{
printf_s("%d is a 5-digit palindrome!\n",num);
puts("Do you wish to continue? 1 = continue 0 = stop");
scanf_s("%d",&counter);
}
else
{
printf_s("%d is not a palindrome!\n",num);
}
}
I didn't expect it to do anything useful with floats since I didn't add anything for it to do so, but why does it enter an infinite loop saying "Enter a 5 digit integer : (number) isn't a palindrome!"?
edit: Turns out I forgot to add what type of variable num and counter was. And somehow called while a function.
CodePudding user response:
While function in c goes into infinite loop when float value is assigned to int?
Code fails to check the return value of scanf_s("%d",&num);
When non-numeric text for an int
, like "123.456" is entered, num
takes on the value 123
and 1 is returned. The '.'
is not consumed. scanf_s("%d",&num);
repeatedly fails on subsequent calls as it attempts to read ".456". and num
is not changed - infinite loop.
Instead, check the return value of input functions.
// scanf_s("%d",&num);
if (scanf_s("%d",&num) != 1) {
puts("Fail");
break;
}
Or use fgets()
to read an entire line (usually). @Some programmer dude
CodePudding user response:
I just ran a test on scanf
.
For 123.456
I thought it would return -1. But it returns 1 and num
will be 123
. It also does the same for 123x
.
Then, I realized that is probably wants for scanf
with file input.
But, given the context of checking for valid user input (from stdin
), I'd say that's bad and I'd use strtol
with the requisite checks instead.
Here's some code that shows the difference:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void
doscanf(const char *str)
{
int ret;
int num;
errno = 0;
ret = sscanf(str,"%d",&num);
printf("doscanf: str='%s' ret=%d num=%d -- %s\n",
str,ret,num,strerror(errno));
}
void
dostrtol(const char *str)
{
errno = 0;
char *cp;
int num = strtol(str,&cp,10);
int valid = (*cp == 0);
printf("dostrtol: num=%d str='%s' cp='%s' valid=%d -- %s\n",
num,str,cp,valid,strerror(errno));
}
int
main(void)
{
const char *strs[] = {
"123",
"456",
"",
"123.456",
"123x",
"x123",
NULL,
};
int sep = 0;
for (const char **str = strs; *str != NULL; str) {
if (sep)
printf("\n");
sep = 1;
doscanf(*str);
dostrtol(*str);
}
return 0;
}
Here is the program output:
doscanf: str='123' ret=1 num=123 -- Success
dostrtol: num=123 str='123' cp='' valid=1 -- Success
doscanf: str='456' ret=1 num=456 -- Success
dostrtol: num=456 str='456' cp='' valid=1 -- Success
doscanf: str='' ret=-1 num=1 -- Success
dostrtol: num=0 str='' cp='' valid=1 -- Success
doscanf: str='123.456' ret=1 num=123 -- Success
dostrtol: num=123 str='123.456' cp='.456' valid=0 -- Success
doscanf: str='123x' ret=1 num=123 -- Success
dostrtol: num=123 str='123x' cp='x' valid=0 -- Success
doscanf: str='x123' ret=0 num=0 -- Success
dostrtol: num=0 str='x123' cp='x123' valid=0 -- Success
Side note: Your "is palindrome" algorithm is hardwired to take only 5 digit numbers.
That's okay, but a bit restrictive (and unusual). Here's a test program that shows a generalized algorithm:
#include <stdio.h>
// orig -- OP original code (restricted/hardwired to 5 digit numbers)
int
orig(int num)
{
int palflg;
palflg = (num0000 - num000)/10000 == num &&
(num0-num) == (num000-num00)/100;
return palflg;
}
// ispal -- generalized to any number
int
ispal(int num)
{
int digits[100];
int left = 0;
int right = 0;
int palflg = 1;
// split number into digits
for (; num != 0; num /= 10)
digits[right ] = num % 10;
// compare outer digits (working inward)
--right;
for (; left <= right; left, --right) {
palflg = (digits[left] == digits[right]);
if (! palflg)
break;
}
return palflg;
}
int
main(void)
{
int numbers[] = {
12345, 12312, 12321, 56465,
#ifndef RESTRICT
0, 1, 23, 123, 232, 1221, 12321, 123321,
#endif
};
for (int idx = 0; idx < sizeof(numbers) / sizeof(numbers[0]); idx) {
int num = numbers[idx];
int palflg = ispal(num);
int origflg = orig(num);
printf("d -- ispal=%s orig=%s -- %s\n",
num,
palflg ? "is" : "not",
origflg ? "is" : "not",
(palflg == origflg) ? "PASS" : "FAIL");
}
return 0;
}
Here is the program output:
12345 -- ispal=not orig=not -- PASS
12312 -- ispal=not orig=not -- PASS
12321 -- ispal=is orig=is -- PASS
56465 -- ispal=is orig=is -- PASS
0 -- ispal=is orig=is -- PASS
1 -- ispal=is orig=not -- FAIL
23 -- ispal=not orig=not -- PASS
123 -- ispal=not orig=not -- PASS
232 -- ispal=is orig=not -- FAIL
1221 -- ispal=is orig=not -- FAIL
12321 -- ispal=is orig=is -- PASS
123321 -- ispal=is orig=not -- FAIL