编写一个需要整数输入并为其他数据类型返回错误的程序

问题描述 投票:0回答:1

我试图编写一个代码,该代码在获取除整数数据类型之外的输入时返回错误。

void error() {
    printf("Invalid Input. Please Try Again.");
    exit(0); //terminate program after invalid input
}

int main() {
    
    int myHW, myQ, myME, myFE, myGrade; //score variables
    
    printf("Grade Calculation Program\n***************************\n\n"); //header

    printf("Please enter your scores.\n");
    
    printf("Homework Score (out of 20): "); //homework score
    ( scanf("%d", &myHW) == 1) ? : error(); 
    (myHW>=0 && myHW<=20) ? : error(); 
    
    
    printf("Quiz Score (out of 30): "); //quiz score
    ( scanf("%d", &myQ) == 1) ? : error();
    (myQ>=0 && myQ<=30) ? : error(); 
    
    printf("Midterm Exam Score (out of 20): "); //midterm exam score
    ( scanf("%d", &myME) == 1) ? : error();
    (myME>=0 && myME<=20) ? : error(); 
    
    printf("Final Exam Score (out of 30): "); //final exam score
    ( scanf("%d", &myFE) == 1) ? : error();
    (myFE>=0 && myFE<=30) ? : error(); 

我尝试使用

( scanf("%d", &myHW) == 1) ? : error();

但是,如果用户输入的第一个字符是以字符/字母开头(a、f25、bd236.5 是我尝试过的一些输入),或者如果字符/小数之前的整数是已经出界(例如 25a、28bd、29.5)。如果我尝试输入浮点/双精度数据类型或仍在参数范围内的整数组合,后跟字符(例如 12.5、5.3、5a),则程序在传递之前首先跳到下一行错误。

请输入您的分数。 家庭作业分数(满分 20 分):5a 测验分数(满分 30 分):输入无效。请再试一次。

这是上述错误的一个实例。

我知道这和我在条件中使用scanf的返回值有关。据我所见,只要输入以数字开头,scanf 就会返回 1。我对编程相当陌生,我只是想尝试解决我们教授给出的一些问题,但我似乎无法为此找到解决方案

c scanf
1个回答
0
投票

在尝试您的代码时,我看到一些可以增强用户体验的领域,可以使用标准字符和数字功能,以及一些可以合并的冗余。因此,以下是代码的重构版本,它应该使用户体验更加流畅。

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

void error()
{
    printf("Invalid Input. Please Try Again.\n");
    return;
}

int allDigits(char *word)
{
    for (int i = 0; i < strlen(word); i++)
    {
        if ((word[i] == '\0') || (word[i] == 10))   /* Reached the terminator or newline character  */
            return 1;
        if (isdigit(word[i]) == 0)                  /* Standard ctype.h function                    */
            return 0;
    }
    return 1;
}

int getInput(char *input_type, int max)
{
    char inp[10];
    int result;
    while (1)
    {
        printf("%s", input_type);
        if (fgets(inp, 4, stdin) == NULL)
        {
            error();
            continue;
        }
        if (allDigits(inp) == 0)
        {
            error();
            continue;
        }
        result = atoi(inp);
        if (result < 0 || result > max)
        {
            error();
            continue;
        }
        break;
    }
    return result;
}

int main()
{
    int myHW, myQ, myME, myFE, myGrade;         //score variables

    printf("Grade Calculation Program\n***************************\n\n"); //header

    printf("Please enter your scores.\n");

    myHW = getInput("Homework Score (out of 20)....: ", 20);    /* Homework score       */
    myQ  = getInput("Quiz Score (out of 30)........: ", 30);    /* Quiz score           */
    myME = getInput("Midterm Exam Score (out of 20): ", 20);    /* Midterm exam         */
    myFE = getInput("Final Exam Score (out of 30)..: ", 30);    /* Final exam           */

    myGrade = myHW + myQ + myME + myFE;

    printf("Recap:\nHomework....: %d\nQuiz........: %d\nMidterm Exam: %d\nFinal Exam..: %d\n- - - - - - - - -\nTotal Score.: %d\n", myHW, myQ, myME, myFE, myGrade);

    return 0;
}

在此重构代码中需要指出的一些关键位。

  • 添加了“string.h”和“ctype.h”包含文件,以允许使用标准字符和数字检查以及字符串数据到整数数据的标准转换。
  • 注意到好的评论中告诉用户发生了某种类型的输入错误然后退出程序似乎让用户体验有点模糊,因此将退出改为返回以允许用户重试输入。
  • 还注意到,在好的评论中,“fgets()”函数可能是用户输入的更好选择,这在重构的代码中进行了更改。
  • 注意到大量冗余函数调用和输入验证导致将这些冗余代码从主函数中取出,并将其包装在一个通用函数中,该函数可以重复用于每个类别的输入(例如家庭作业、测验、期中考试和期末考试),从而减少程序的大小。
  • 经过有根据的猜测,代码已完成,用于计算总分并打印学生的统计数据。

通过这些重构,以下是学生的示例输出。

craig@Vera:~/C_Programs/Console/Scores/bin/Release$ ./Scores 
Grade Calculation Program
***************************

Please enter your scores.
Homework Score (out of 20)....: 17
Quiz Score (out of 30)........: 25
Midterm Exam Score (out of 20): 13
Final Exam Score (out of 30)..: 28
Recap:
Homework....: 17
Quiz........: 25
Midterm Exam: 13
Final Exam..: 28
- - - - - - - - -
Total Score.: 83

回顾这段重构的代码并将其作为思考的基础。当重复类似或相同的功能时,始终留意可以重构代码的地方。这通常是一个信号,表明重复的步骤可以封装在一个函数中,然后可以使用不同的输入参数多次调用该函数。一如既往,请始终参考有关在语言中使用标准函数的可用编码教程,以避免不必要地重新创建现有功能。

© www.soinside.com 2019 - 2024. All rights reserved.