Vasudha Dixit
Vasudha Dixit

Reputation: 377

*pointer_variable != '\0' is not working for the check of unsuccessful conversion in strtol() function

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

Answers (1)

Fuel
Fuel

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

Related Questions