【问题标题】:How do I make a function that validates user input in C? [closed]如何在 C 中创建一个验证用户输入的函数? [关闭]
【发布时间】:2012-07-15 21:37:22
【问题描述】:

我需要为我的第一学期 c 作业编写一个函数。如果有人可以帮助我,我已经编写了所有作业,我只需要验证用户输入。这是老师给我的...如果这还不够,我可以发布更多信息

double get_double(void) 函数必须用于验证每个费用的输入 和收入。它会不断提示用户输入一个数值,直到满足 条件。该值必须是数字且大于或等于 0。如果输入任何字符 在输入被视为无效的数字之前或之后。

#include <stdio.h>
#include <conio.h>

double get_expenses(double* pSchool, double* pLiving, double* pTransp, double* pOther); /* function prototype */
double get_income(double* pEmploy, double* pOther);                                     /* function prototype */
double display_report(double School, double Living, double Transp, double OtherExp, double Employ, double OtherInc);  /* function prototype */
char get_char(char* pRecalculate);   /* function prototype */
void clear_buffer(void);   /* function prototype */
double get_double(void);   /* function prototype */

main() {

double school, living, transp, otherExp;
double employ, otherInc;
char recalculate;
int counter = 1;



while (counter > 0){  
    printf("Student Budget Planner\n");
    printf("~~~~~~~~~~~~~~~~~~~\n");
    printf("Input Set: %d\n\n", counter);             
    get_expenses(&school, &living, &transp, &otherExp);
    get_income(&employ, &otherInc);
    display_report(school, living, transp, otherExp, employ, otherInc);
    clear_buffer();
    get_char(&recalculate);
     if (recalculate == 'Y' || recalculate == 'y'){
     counter = counter + 1;
        } else {
               counter = 0;
               }

}                                      
return 0;
}


double get_expenses(double* pSchool, double* pLiving, double* pTransp, double* pOther) {
*pSchool = *pLiving = *pTransp = *pOther = 0;

double tuition, textbooks, supplies, rent, utilities, phone, groceries;
double entertainment, transportation, car, insurance, gas, other;

printf("School Expenses:\n");
printf("~~~~~~~~~~~~~~\n");
printf("Tuition (per semester): ");
scanf("%lf", &tuition);
printf("\nTextbooks(per semester): ");
scanf("%lf", &textbooks);
printf("\nSupplies: ");
scanf("%lf", &supplies);

*pSchool = (tuition / 4) + (textbooks / 4) + supplies;

printf("\n\nLiving Expenses:\n");
printf("~~~~~~~~~~~~~\n");
printf("Residence/Rent/Mortgage: ");
scanf("%lf", &rent);
printf("\nUtilities: ");  
scanf("%lf", &utilities);           
printf("\nPhone/Internet: "); 
scanf("%lf", &phone);                
printf("\nGroceries/Eating out: ");
scanf("%lf", &groceries);                 
printf("\nEntertainment: "); 
scanf("%lf", &entertainment);

*pLiving = rent + utilities + phone + groceries + entertainment;

printf("\n\nTransportation: \n");              
printf("~~~~~~~~~~~~~\n");
printf("Public Transportation: "); 
scanf("%lf", &transportation);
printf("\nCar: ");
scanf("%lf", &car);
printf("\nAuto Insurance: ");
scanf("%lf", &insurance);
printf("\nGas/Maintenance: ");
scanf("%lf", &gas);

*pTransp = transportation + car + insurance + gas;

printf("\n\nOther: \n");
printf("~~~~~\n");
printf("Any other expenses: ");
scanf("%lf", &other);

*pOther = other;

return *pSchool, *pLiving, *pTransp, *pOther;
}

double get_income(double* pEmploy, double* pOther){
*pEmploy = *pOther = 0;

double wages, family, scholarship, other;

printf("\n\nEmployment income:\n");
printf("~~~~~~~~~~~~~~~~~\n");
printf("Expected Wages/Tips: ");
scanf("%lf", &wages);

*pEmploy = wages;

printf("\n\nOther income:\n");
printf("~~~~~~~~~~~\n");
printf("Family Support: ");
scanf("%lf", &family);
printf("\nScholarship/Bursaries (per semester): ");
scanf("%lf", &scholarship);
printf("\nOther: ");
scanf("%lf", &other);

*pOther = family + scholarship + other;

return *pEmploy, *pOther;
}

double display_report(double School, double Living, double Transp, double OtherExp, double Employ, double OtherInc) {  

printf("\n\nStudent Name Budget Report\n");  
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("Expenses:\n");
printf("~~~~~~~~\n");
printf("                                              MONTHLY  ANNUALY\n");
printf("School Expenses:                              $%.2lf   $%.2lf\n", School, School * 12);
printf("Living Expenses:                              $%.2lf   $%.2lf\n", Living, Living * 12);
printf("Transportation Expenses:                      $%.2lf   $%.2lf\n", Transp, Transp * 12);
printf("Other Expenses:                               $%.2lf   $%.2lf\n", OtherExp, OtherExp * 12);
printf("total Expenses:                               $%.2lf   $%.2lf\n", School + Living + Transp + OtherExp, School * 12 + Living * 12 + Transp * 12 + OtherExp * 12); 
printf("Income:\n");
printf("~~~~~~~\n");
printf("Employment Income:                            $%.2lf   $%.2lf\n", Employ, Employ * 12);
printf("Other Income:                                 $%.2lf   $%.2lf\n", OtherInc, OtherInc * 12);
printf("Total Income:                                 $%.2lf   $%.2lf\n", Employ + OtherInc, Employ * 12 + OtherInc * 12);
printf("Total Savings Available for your Goals:       $%.2lf   $%.2lf\n", (Employ + OtherInc) - (School + Living + Transp + OtherExp), (Employ * 12 + OtherInc * 12)- (School * 12 + Living * 12 + Transp * 12 + OtherExp * 12));


return 0;
}

char get_char(char* pRecalculate){

     int valid_input;

     valid_input = 0;

     while (valid_input == 0){
     printf("\nWould you like to recalculate your budget? (Y/N): ");
     scanf("%c", &*pRecalculate);
     *pRecalculate = toupper(*pRecalculate);
     if (*pRecalculate == 'Y' || *pRecalculate == 'y' || *pRecalculate == 'N' || *pRecalculate == 'n') valid_input = 1;
         else printf("Error Invalid choice\n");


     printf("\n");
     }

     return *pRecalculate;
     }


void clear_buffer(void) {

while ( getchar() != '\n' );
}

double get_double()
{

 // What to put here?
}

【问题讨论】:

  • @azuyer:你必须发布一些代码。展示你的作品。我建议您尽快这样做,否则人们会投反对票或发帖。
  • 我尝试发布所有内容,但它说存在格式错误或其他问题
  • double get_expenses(double* pSchool, double* pLiving, double* pTransp, double* pOther); /* 函数原型 / double get_income(double pEmploy, double* pOther); /* 函数原型 / double display_report(double School, double Living, double Transp, double OtherExp, double Employ, double OtherInc); //i>函数原型/char get_char(char pRecalculate); /* 函数原型 / void clear_buffer(void); //i>函数原型/double get_double(void); / 函数原型 */
  • +1 表示您正在努力解决您的问题。大多数新用户在看到最初的大量反对票后愤怒地退出了。

标签: c input validation scanf


【解决方案1】:

想想流程的顺序,想想你希望你的程序或函数遵循的流程图/决策树。

在输入有效输入之前,您不希望停止询问用户输入。您可以保证至少询问用户一次,但可能会询问多次。输入有效或无效。

现在我们开始起草一些伪代码。以下是我的做法:

double get_double(void)
{
    double d;
    int ask_again = 1; /* continue if 1 (true), exit if 0 (false) */

    do {
        /* display message to user to let them know to type a number */
        /* read user input */
        if (/* user input didn't input a valid double */)
        {
            /* display appropriate error message */
        }
        else if (/* user entered a double, but it wasn't greater than or equal to zero */)
        {
            /* display appropriate error message */
        }
        else    /* user entered valid input, so ...  */
        {
            /* ... do something to make sure the loop exists */
        }
    } while (/* we need to ask again */);
}

这对我来说是 do-while,所以我在 do-while 循环中编写了它。我提供了一个 int ask_again 变量,但我把它留给你,如果它可能有用的话。

您应该考虑所有 cmets 所在的实际代码应该放在哪里。
查看您的课程笔记,了解您的老师希望您知道哪些技巧可以在这里应用。

读取和清理用户输入是所有计算机语言中的一个臭名昭著的问题,尤其是 C。StackOverflow 可以让您了解如何执行特定操作。

【讨论】:

    【解决方案2】:

    试试这个:

    double get_double()
    {
        double d;
    
        if (scanf("%lf", &d) != 1)
            /* handle error */
            reurn -1;
    
        if (d < 0)
            /* handle error */
            return -1;
    
        return d;
    }
    

    或者,正如 Keith Thompson 指出的那样,您也可以安全:

    double get_double()
    {
        double d;
        char *line = NULL;
        size_t len;
    
        getline(&line, &len, stdin);
        if (line == NULL)
            return -1;
    
        d = strtod(line, NULL);
        free(line);
    
        if (d < 0)
            /* handle error */
            return -1;
    
        return d;
    }
    

    你可以这样使用它(因为没有办法在一个双精度中返回所有输入的双精度——也许你想要一个数组,但问题将目标签名指定为双精度 (*)()):

    double d;
    
    while ((d = get_double()) >= 0)
    {
        /* do what you want */
    }
    

    【讨论】:

    • scanf 如果输入值超出目标类型的范围(在这种情况下为double),则具有未定义的行为;见N15707.21.6.2p10
    • 问题说会不断提示用户输入数值,直到满足条件。该值必须是数字并且大于或等于 0。如果任何字符输入在数字之前或之后,则输入将被视为无效。
    • @KeithThompson 那么这里有什么问题?
    • 调用scanf("%lf", &amp;d)时,如果用户输入,例如1.0e1000000,则行为未定义;不能保证scanf 会指示错误。它可能会使程序崩溃。 (哦,你在下一行拼错了return。)
    • @KeithThompson 谢谢!我会更新的。但这基本上意味着我们不能使用scanf()?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多