确保用户只输入自然数的最佳方法是什么?

What is the best way to ensure a user only enters natural numbers?

刚开始学习C,如果你能在以下方面帮助我就太好了:

我刚刚写了一个程序,计算用户输入的自然数的阶乘。如果数字是负数或字符,它应该用消息 You have not entered a natural number. 通知用户。此消息来自函数 check_if_valid_value.

到目前为止,它在输入字符时会显示该消息,但似乎不适用于负值。我认为将变量转换为 long long unsigned 可以解决问题,但事实并非如此。问题是 scanf() 函数 returns 一个 0 所以不确定为什么程序不 运行 函数 check_if_valid_value 所以它 returns留言: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;
}

您的代码有问题:

  • scanf returns 成功转换的次数。所以你应该重命名那个变量 successful_conversions.
  • 指向无符号整数的指针的 scanf 格式是 %u,而不是 %llu

您也可以从 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()就会进入一个很长的循环。您应该添加一些检查 p 是否足够小,以便 p 的阶乘不超过 unsigned long long.

的范围

如果你想更严格地测试输入,你应该学习如何读入一个短字符串,然后测试该字符串是否完全由十进制数字组成。作为起点,请查看 fgets().