Каков наилучший способ гарантировать, что пользователь вводит только натуральные числа? - PullRequest
0 голосов
/ 25 апреля 2020

Только начал изучать C, и было бы здорово, если бы вы могли помочь мне со следующим:

Я только что написал программу, которая вычисляет факториал натурального числа, введенного пользователем. Если число отрицательное или символ, оно должно уведомить пользователя с сообщением You have not entered a natural number.. Это сообщение приходит от функции check_if_valid_value.

. До сих пор оно отображало это сообщение при вводе символов, но, похоже, не работает с отрицательными значениями. Я думал, что приведение переменной как long long unsigned поможет, но похоже, что это не так. Дело в том, что функция scanf() возвращает 0, поэтому не уверен, почему программа не запускает функцию check_if_valid_value, поэтому возвращает сообщение: You have not entered a natural number.

Я с нетерпением жду чтения любые предложения по улучшению этого кода!

#include <stdio.h>
#include <stdlib.h>

void check_if_valid_value(int value_entered)
{
        if (value_entered != 1) 
        {
                printf("You have not entered a natural number.\n");
                exit(1);
        }
}          

void do_the_factorial(int p)
{  
        int i;
        unsigned long long int factorial=1;

        for (i = 1; i <= p; ++i)
        {
                factorial=factorial*i;
                printf("%llu\n", factorial);
        }
}


int main(void)
{
        int value_entered, p;

        printf("Enter a natural number:");

        value_entered=scanf("%llu",&p);

        check_if_valid_value(value_entered);

        do_the_factorial(p);

        return 0;
}

1 Ответ

2 голосов
/ 25 апреля 2020

Проблемы с вашим кодом:

  • scanf возвращает количество успешных конверсий. Поэтому вам, возможно, следует переименовать эту переменную successful_conversions.
  • . Формат scanf для указателя на целое без знака: %u, а не %llu.

Вы можете также начните факториал l oop с 2, так как умножение на 1 в большинстве случаев бесполезно. Итак, мы имеем:

#include <stdio.h>
#include <stdlib.h>

void check_if_valid_value(int successful_conversions)
{
        if (successful_conversions != 1)
        {
                printf("You have not entered a natural number.\n");
                exit(1);
        }
}

void do_the_factorial(unsigned int p)
{
        unsigned int i;
        unsigned long long int factorial=1;

        for (i = 2; i <= p; ++i)
        {
                factorial=factorial*i;
        }
        printf("%llu\n", factorial);
}

int main(void)
{
        int successful_conversions;
        unsigned int p;

        printf("Enter a natural number:\n");
        successful_conversions=scanf("%u",&p);
        check_if_valid_value(successful_conversions);
        do_the_factorial(p);
        return 0;
}

Предупреждение: сканирование %u позволяет номеру иметь знак, который может быть отрицательным. Если вы введете -1, то p будет наибольшим положительным целым числом без знака, UINT_MAX. Тогда do_the_factorial () будет вводить очень длинный l oop. Вы должны добавить некоторую проверку, если p достаточно мало, чтобы факториал p не превышал диапазон unsigned long long.

Если вы хотите более строго проверить ввод, вы должны научиться читать в коротком string, а затем проверьте, состоит ли строка целиком из десятичных цифр. В качестве отправной точки, посмотрите на fgets().

...