Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scanf to find integers

Tags:

c

I feel like I am missing something dreadfully obvious here, but I just can't seem to find the problem with my code. I am trying to use scanf to find if an input is an integer, and if it is, find the octal. If it is not an integer, then it simply prompts the user to enter again. For some reason, however, I can only seem to get the code to work if the reverse is the case, where an integer is not accepted and anything else is. Seems like it would be a simply problem to fix, but I just get infinite loops otherwise. Any help you guys could give would be appreciated.

#include <stdio.h>
enum state {success,fail,quit};
int status = fail;

int main(void)
{
int n;
char t;
do
{
printf("Enter a number between 0 and 32767: ");

if(scanf("%d%c", &n, &t) != 2 )
status = success;
}
while (status == fail);
if (status == success)
{

int oct1, oct2, oct3, oct4, oct5;

oct1 = ((((n / 8) / 8) / 8) / 8) % 8;
oct2 = (((n / 8) / 8) / 8) % 8;
oct3 = ((n / 8) / 8) % 8;
oct4 = (n / 8) % 8;
oct5 = n % 8;

printf("In octal, your number is: %d%d%d%d%d\n", oct1, oct2, oct3, oct4, oct5);
return 0;
}
}
like image 821
user2760309 Avatar asked Nov 01 '22 14:11

user2760309


2 Answers

Refactored your code

#include <stdio.h>

    int main(void)
    {
    int n;
    char t;
    do
    {
    printf("Enter a number between 0 and 32767: ");
    scanf("%d", &n);
    }
    while( (n < 0) || (n > 32767)) ; //check the range of the input.if not there in this range then re read input.
    printf("In octal, your number is: %o \n", n); //print octal of input with %o format specifier.
    return 0;
    }
like image 89
Gangadhar Avatar answered Nov 15 '22 08:11

Gangadhar


You have a problem in that if you enter a non-numeric value, then the it will not be removed from the input buffer and will stay there forever while you try to scan for numbers.

Instead read the line separately, and then try to get the number from that line. Something like this:

for (;;)
{
    printf("Enter a number: ");

    /* Get a line of input from the user */
    char line[128];
    if (fgets(line, sizeof(line), stdin) == NULL)
    {
        /* Error reading */
        perror("fgets");
        break;
    }

    /* The `fgets` function leaves the newline in the string */
    /* Remove it by overwriting it with the string terminator */
    line[strlen(line) - 1] = '\0';

    /* Convert to a number */
    char *endptr = NULL;
    n = strtol(line, &endptr, 10);

    /* Check if a valid number was entered */
    if (endptr == line)
        printf("Not a valid number, please enter again\n");
    else if (endptr < (line + strlen(line)))
        printf("Line begins with a number, but then there is garbage\n");
    else
        break;  /* We got a valid number */
}

If you don't care about possible garbage, you could use sscanf instead, and simplify this as

for (;;)
{
    printf("Enter a number: ");

    /* Get a line of input from the user */
    char line[128];
    if (fgets(line, sizeof(line), stdin) == NULL)
    {
        /* Error reading */
        perror("fgets");
        break;
    }

    /* Try to get number as an unsigned short */
    if (sscanf(line, " %hu", &n) == 1)
        break;

    printf("Illegal number\n");
}
like image 41
Some programmer dude Avatar answered Nov 15 '22 09:11

Some programmer dude