Reputation: 377
The program was not working for input 5r
i.e in input when first character is number and remaining next character is any alphabet or negative number. For example when I am giving input as 5r in the output I am getting factorial of 5.
So I tried putting check for strtol
unsuccessful conversion :-
if (p == buf || *p != '\0'){ printf("\nInvalid input: not a number\n");}
but I am getting output as Invalid input: not a number
for all the input.
I found many similar questions in Stack Overflow. However, they don't resolve my issue. I am not understanding what is wrong with this simple check? How can I successfully detect errors from strtol
?
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
int display();
void fact_fun(int num_fact);
int main()
{
int num;
while ((num = display()) >= 0)
{
fact_fun(num);
}
return 0;
}
int display()
{
char buf[256];
char *p;
long value;
for (;;)
{
printf("\nEnter number to find factorial or press ENTER KEY to exit: ");
if (fgets(buf, sizeof buf, stdin) == NULL || *buf == '\n')
return -1;
errno = 0;
value = strtol(buf, &p, 0);
if (p == buf || *p != '\0')
{
printf("\nInvalid input: not a number\n");
}
else
{
if (value < 0)
{
printf("\nInvalid input: negative values not allowed\n");
}
else if (errno != 0 || value > INT_MAX)
{
printf("\nInvalid input: value too large for type int\n");
}
else
{
return (int)value;
}
}
}
}
void fact_fun(int num_fact)
{
int fact = 1;
for (int i = 1; i <= num_fact; i++)
{
if (fact > INT_MAX / i)
{
printf("\nInvalid input: arithmetic overflow\n");
return;
}
fact = fact * i;
}
printf("\nFactorial of %d is %d\n", num_fact, fact);
}
Upvotes: 0
Views: 57
Reputation: 157
The string you get from fgets
contains '\n'
as last char because you hit enter, so replace it with '\0'
. That is a common error we C coders sometimes make.
Edit: So I have tested it myself, and you're right, the reason is that strtoI does not mess with line terminator, so now it works fine with the following check:
*p != '\n'
The full working code is this:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
int display();
void fact_fun(int num_fact);
int main()
{
int num;
while ((num = display()) >= 0)
{
fact_fun(num);
}
return 0;
}
int display()
{
char buf[256];
char *p;
long value;
for (;;)
{
printf("\nEnter number to find factorial or press ENTER KEY to exit: ");
if (fgets(buf, sizeof buf, stdin) == NULL || *buf == '\n')
return -1;
errno = 0;
value = strtol(buf, &p, 0);
if (p == buf || *p != '\n')
{
printf("\nInvalid input: not a number\n");
}
else
{
if (value < 0)
{
printf("\nInvalid input: negative values not allowed\n");
}
else if (errno != 0 || value > INT_MAX)
{
printf("\nInvalid input: value too large for type int\n");
}
else
{
return (int)value;
}
}
}
}
void fact_fun(int num_fact)
{
int fact = 1;
for (int i = 1; i <= num_fact; i++)
{
if (fact > INT_MAX / i)
{
printf("\nInvalid input: arithmetic overflow\n");
return;
}
fact = fact * i;
}
printf("\nFactorial of %d is %d\n", num_fact, fact);
}
Upvotes: 2