C:scanf()和while()(来自C Primer Plus的编程练习7.10)

C:scanf()和while()(来自C Primer Plus的编程练习7.10),c,while-loop,scanf,C,While Loop,Scanf,我还在读斯蒂芬·普拉塔的C初级读物。下面的代码是我试图解决第七章的第十个编程练习。 我的问题是:当输入一个字符而不是一个整数时,为什么程序会无限循环?如何防止这种行为 #include <stdio.h> // taxrates #define TAXRATE_1 .15 #define TAXRATE_2 .28 // category limits #define SINGLE_LIMIT 17850 #define HEAD_OF_HOUSEHOLD_LI

我还在读斯蒂芬·普拉塔的C初级读物。下面的代码是我试图解决第七章的第十个编程练习。 我的问题是:当输入一个字符而不是一个整数时,为什么程序会无限循环?如何防止这种行为

#include <stdio.h>
// taxrates
#define TAXRATE_1 .15
#define TAXRATE_2 .28
// category limits
#define SINGLE_LIMIT            17850
#define HEAD_OF_HOUSEHOLD_LIMIT 23900
#define MARRIED_JOINT_LIMIT     29750
#define MARRIED_SEPARAT_LIMIT   14875
// bases
#define SINGLE_BASE             SINGLE_LIMIT            * TAXRATE_1
#define HEAD_OF_HOUSEHOLD_BASE  HEAD_OF_HOUSEHOLD_LIMIT * TAXRATE_1
#define MARRIED_JOINT_BASE      MARRIED_JOINT_LIMIT     * TAXRATE_1
#define MARRIED_SEPARAT_BASE    MARRIED_SEPARAT_LIMIT   * TAXRATE_1

int main(void)
{
    int selection;
    float income, tax;

    while (1)
    {
        printf("*******************************************************\n"
               "Please enter the number of your category:\n"
               "1) Single\n2) Head of Household\n3) Married, Joint\n4) Married, Separat\n5) quit\n"
               "*******************************************************\n");
        scanf("%d", &selection);
        if (selection >= 1 && selection <= 4)
        {
            printf("Enter income: ");
            scanf("%f", &income);
            switch (selection)
            {
                case 1:
                    if (income < SINGLE_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = SINGLE_BASE           + (income - SINGLE_LIMIT) * TAXRATE_2;
                    printf("Single income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 2:
                    if (income < HEAD_OF_HOUSEHOLD_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = HEAD_OF_HOUSEHOLD_BASE+ (income - HEAD_OF_HOUSEHOLD_LIMIT) * TAXRATE_2;
                    printf("Head of Household income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 3:
                    if (income < MARRIED_JOINT_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = MARRIED_JOINT_BASE    + (income - MARRIED_JOINT_LIMIT) * TAXRATE_2;
                    printf("Married joint income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 4:
                    if (income < MARRIED_SEPARAT_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = MARRIED_SEPARAT_BASE  + (income - MARRIED_SEPARAT_LIMIT) * TAXRATE_2;
                    printf("Married separat income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
            }
        }
        else if (selection == 5)
        {
            printf("Done.");
            break;
        }
        else
            printf("Please enter a number between 1 and 5.\n");
    }
        return 0;
}

仅当else部分中的选择值为5时,程序中的While循环才会退出。
但是,每当您输入一个字符时,选择的值不能是5,因此它永远不会从循环中出来,并使程序循环无限运行

仅当else部分中的选择值为5时,程序中的While循环才会退出。 但是,每当您输入一个字符时,选择的值不能是5,因此它永远不会从循环中出来,并使程序循环无限运行

我的问题是:当一个角色被激活时,为什么程序会无限循环 输入而不是整数,如何防止这种行为

#include <stdio.h>
// taxrates
#define TAXRATE_1 .15
#define TAXRATE_2 .28
// category limits
#define SINGLE_LIMIT            17850
#define HEAD_OF_HOUSEHOLD_LIMIT 23900
#define MARRIED_JOINT_LIMIT     29750
#define MARRIED_SEPARAT_LIMIT   14875
// bases
#define SINGLE_BASE             SINGLE_LIMIT            * TAXRATE_1
#define HEAD_OF_HOUSEHOLD_BASE  HEAD_OF_HOUSEHOLD_LIMIT * TAXRATE_1
#define MARRIED_JOINT_BASE      MARRIED_JOINT_LIMIT     * TAXRATE_1
#define MARRIED_SEPARAT_BASE    MARRIED_SEPARAT_LIMIT   * TAXRATE_1

int main(void)
{
    int selection;
    float income, tax;

    while (1)
    {
        printf("*******************************************************\n"
               "Please enter the number of your category:\n"
               "1) Single\n2) Head of Household\n3) Married, Joint\n4) Married, Separat\n5) quit\n"
               "*******************************************************\n");
        scanf("%d", &selection);
        if (selection >= 1 && selection <= 4)
        {
            printf("Enter income: ");
            scanf("%f", &income);
            switch (selection)
            {
                case 1:
                    if (income < SINGLE_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = SINGLE_BASE           + (income - SINGLE_LIMIT) * TAXRATE_2;
                    printf("Single income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 2:
                    if (income < HEAD_OF_HOUSEHOLD_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = HEAD_OF_HOUSEHOLD_BASE+ (income - HEAD_OF_HOUSEHOLD_LIMIT) * TAXRATE_2;
                    printf("Head of Household income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 3:
                    if (income < MARRIED_JOINT_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = MARRIED_JOINT_BASE    + (income - MARRIED_JOINT_LIMIT) * TAXRATE_2;
                    printf("Married joint income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 4:
                    if (income < MARRIED_SEPARAT_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = MARRIED_SEPARAT_BASE  + (income - MARRIED_SEPARAT_LIMIT) * TAXRATE_2;
                    printf("Married separat income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
            }
        }
        else if (selection == 5)
        {
            printf("Done.");
            break;
        }
        else
            printf("Please enter a number between 1 and 5.\n");
    }
        return 0;
}
当您输入的内容不是scanf所期望的,而是您传递给scanf的格式字符串所定义的内容时,它将忽略该内容并返回。但该无效输入不会从输入流中清除。因此,当读忽略循环再次在程序中继续时,循环将永远继续

因此,为了解决这个问题:

尽可能避免扫描。使用fgets并使用sscanf处理输入,这提供了更好的错误控制。 检查返回值scanf以确定扫描是否成功。 通常的清除方法是在遇到无效输入时读取输入流中的所有字符:

else { 
       int c;
       printf("Please enter a number between 1 and 5.\n");
       while((c = getchar()) != '\n' && c != EOF) ; /* reads and discards */
     }
我的问题是:当一个角色被激活时,为什么程序会无限循环 输入而不是整数,如何防止这种行为

#include <stdio.h>
// taxrates
#define TAXRATE_1 .15
#define TAXRATE_2 .28
// category limits
#define SINGLE_LIMIT            17850
#define HEAD_OF_HOUSEHOLD_LIMIT 23900
#define MARRIED_JOINT_LIMIT     29750
#define MARRIED_SEPARAT_LIMIT   14875
// bases
#define SINGLE_BASE             SINGLE_LIMIT            * TAXRATE_1
#define HEAD_OF_HOUSEHOLD_BASE  HEAD_OF_HOUSEHOLD_LIMIT * TAXRATE_1
#define MARRIED_JOINT_BASE      MARRIED_JOINT_LIMIT     * TAXRATE_1
#define MARRIED_SEPARAT_BASE    MARRIED_SEPARAT_LIMIT   * TAXRATE_1

int main(void)
{
    int selection;
    float income, tax;

    while (1)
    {
        printf("*******************************************************\n"
               "Please enter the number of your category:\n"
               "1) Single\n2) Head of Household\n3) Married, Joint\n4) Married, Separat\n5) quit\n"
               "*******************************************************\n");
        scanf("%d", &selection);
        if (selection >= 1 && selection <= 4)
        {
            printf("Enter income: ");
            scanf("%f", &income);
            switch (selection)
            {
                case 1:
                    if (income < SINGLE_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = SINGLE_BASE           + (income - SINGLE_LIMIT) * TAXRATE_2;
                    printf("Single income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 2:
                    if (income < HEAD_OF_HOUSEHOLD_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = HEAD_OF_HOUSEHOLD_BASE+ (income - HEAD_OF_HOUSEHOLD_LIMIT) * TAXRATE_2;
                    printf("Head of Household income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 3:
                    if (income < MARRIED_JOINT_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = MARRIED_JOINT_BASE    + (income - MARRIED_JOINT_LIMIT) * TAXRATE_2;
                    printf("Married joint income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
                case 4:
                    if (income < MARRIED_SEPARAT_LIMIT)
                        tax = income * TAXRATE_1;
                    else
                        tax = MARRIED_SEPARAT_BASE  + (income - MARRIED_SEPARAT_LIMIT) * TAXRATE_2;
                    printf("Married separat income of: %.2f$ Tax: %.2f$\n", income, tax);
                    break;
            }
        }
        else if (selection == 5)
        {
            printf("Done.");
            break;
        }
        else
            printf("Please enter a number between 1 and 5.\n");
    }
        return 0;
}
当您输入的内容不是scanf所期望的,而是您传递给scanf的格式字符串所定义的内容时,它将忽略该内容并返回。但该无效输入不会从输入流中清除。因此,当读忽略循环再次在程序中继续时,循环将永远继续

因此,为了解决这个问题:

尽可能避免扫描。使用fgets并使用sscanf处理输入,这提供了更好的错误控制。 检查返回值scanf以确定扫描是否成功。 通常的清除方法是在遇到无效输入时读取输入流中的所有字符:

else { 
       int c;
       printf("Please enter a number between 1 and 5.\n");
       while((c = getchar()) != '\n' && c != EOF) ; /* reads and discards */
     }

您可能必须在计算机上运行代码来检查代码。任何整数值都是有效的,即不会导致无限循环。是的,它可以接受任何整数值,但要退出while循环,变量选择的值应为5。如果您必须仔细阅读该问题,则会在输入字符时询问为什么它没有从循环中出来。希望现在很清楚,我只希望选择值为5时循环停止。为什么输入字符后不能输入任何新数字?在第一次打印后,scanf会发生什么变化?为什么输入字符后程序不停止等待用户输入?您可能必须在计算机上运行代码来检查代码。任何整数值都是有效的,即不会导致无限循环。是的,它可以接受任何整数值,但要退出while循环,变量选择的值应为5。如果您必须仔细阅读该问题,则会在输入字符时询问为什么它没有从循环中出来。希望现在很清楚,我只希望选择值为5时循环停止。为什么输入字符后不能输入任何新数字?在第一次打印后,scanf会发生什么变化?为什么输入字符后程序不停止等待用户输入?不幸的是,其他功能还没有引入。我是否理解正确:来自scanf的未识别输入保留在inputstream中,一旦被getchar识别,将被丢弃,直到“\n”。是的,您理解正确。稍后您可以了解这些函数:只是要记住scanf的缺陷&为什么它不是首选。不幸的是,其他函数还没有被引入。我是否理解正确:来自scanf的未识别输入保留在inputstream中,一旦被getchar识别,将被丢弃,直到“\n”。是的,您理解正确。稍后您可以了解这些功能:只是要记住scanf的缺陷&为什么它不是首选。