【问题标题】:C Program Limit the integer input rangeC程序限制整数输入范围
【发布时间】:2018-12-16 09:10:28
【问题描述】:

我是一个新的 C 编程学习者,我正在尝试制作一个程序,该程序可以根据输入的成绩和科目的学分计算学生的 GPA。

  1. 我遇到的问题是我想将输入的主题数量限制在 2 到 6 之间。

  2. 另一个问题是我想限制用户只能输入从 1 到 100 的整数,而不是任何其他关键字,特殊字符 (EOF)

我已将 "###" 放在需要这些修改的注释行中

#include <stdio.h>
int main(void) {
    // input      user input -- hopefully a number
    // temp       used to collect garbage characters
    // status     did the user enter a number?
    // counter    for keeping track of loop repetition
    // no         no. of subjects to be entered by user.
    // credits    credits per subject 
    // grades     grades acheived in each subject (1 to 100).
    // grade_value  for holding the value of each subject grade (for ex; 80 to hundred is 4.0)
    // grade_points  Grade points for each subject (credits * grade_value)
    // sum         sum of total grade points
    int counter = 1, subjects, no, credits, grades, status, temp;
    float grade_value, grade_point, sum;
    printf("Enter number of subjects you took for current semester: ");
    status = scanf("%d", & no);

    // ### I want to limit this integer input to be >=2 && <=6.

    while (status != 1) {
        while ((temp = getchar()) != EOF && temp != '\n');
        if ((temp < 2) && (temp > 6));
        break;
        printf("Invalid input... please enter the number of subject again: ");
        status = scanf("%d", & no);

    }
    // ### I want to be this input to block other character inputs than integer from 1 to hundred.
    while (counter <= no) {
        printf("\nEnter Subject %d grades separated with credits \n", counter);
        scanf("%d %d", & grades, & credits);
        if ((grades > 0) && (grades <= 29)) {
            grade_value = 0;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 30) && (grades <= 34)) {
            grade_value = 0.67;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 35) && (grades <= 39)) {
            grade_value = 1;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 40) && (grades <= 44)) {
            grade_value = 1.33;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 45) && (grades <= 49)) {
            grade_value = 1.67;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf(" \nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 50) && (grades <= 54)) {
            grade_value = 2;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 55) && (grades <= 59)) {
            grade_value = 2.33;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 60) && (grades <= 64)) {
            grade_value = 2.67;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 65) && (grades <= 69)) {
            grade_value = 3;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 70) && (grades <= 74)) {
            grade_value = 3.33;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 75) && (grades <= 79)) {
            grade_value = 3.67;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        } else if ((grades >= 80) && (grades <= 100)) {
            grade_value = 4;
            printf("Grade value for subject %d is: %.2f", counter, grade_value);
            grade_point = credits * grade_value;
            printf("\nGrade point for subject %d is: %.2f", counter, grade_point);
            sum = sum + grade_point;
            ++counter;
        }
        // To print a message if user doesnt enter an integer varying from 1 to 100.
        else {
            printf("\n Error Grade input, Please Key in Again. (1 to 100 only.)");
        }
    }
    printf("\n");
    printf("\n");
    printf("\nThe GPA is: %.2f", sum);
    if (sum <= 49) {
        printf("\nYou can register for 2 subjects for next semester.");
    } else if ((sum >= 50) && (sum >= 79)) {
        printf("\nYou can register for 5 subjects for next semester.");
    } else if ((sum >= 80) && (sum <= 100)) {
        printf("\nYou can register for 6 subjects for next semester.");
    }
    printf("\n");
    printf("\n");
    printf("\n_______________________________________________________");
    printf("\nEnd of program");
    return 0;
}

【问题讨论】:

  • 您想读取任意输入,根据规则检查它,忽略任何不符合规则的输入并继续要求输入直到满足规则?您的代码似乎已经很接近了。是什么让你卡住了?
  • 我不知道 any 字符编码在哪里,例如2 == '2'。绝对不在ASCII
  • 此外,请考虑重新阅读您的 if 声明。那个分号在那里做什么?
  • 首先正确地格式化你的代码。尊重我们的时间 现在@Some programmer dude 提到您需要将 char 转换为数字。 temp = temp - '0';需要检查scanf的返回值。最后一句话 - 使用函数来完成任务。不要把所有的东西都写在 main 函数中。我没有检查其他任何内容,因为代码的编写和格式都太糟糕了。
  • 另一个 scanf() 用于读取用户输入而不检查返回值。如果用户输入的不是数字,你的变量不会被初始化,你就会陷入未定义的行为。请使用 fgets() 读取整行输入而不溢出输入缓冲区,然后在内存中解析该缓冲区(使用例如 strtol())。

标签: c input integer range


【解决方案1】:

您的代码存在一些语义错误。绝对不能在if 语句之后放置分号。您还可以通过分隔代码块来编写更清晰的代码。更好的是,您可以重构一些块并将其封装到函数中。除此之外,请参阅以下解决方案:

对于第一个问题,几行代码就可以解决。用户在输入之前知道输入的限制是一个很好的做法:

/* ### I want to limit this integer input to be >=2 && <=6. */

#include <stdio.h>

int main()
{
    int no;

    do {
        printf("Enter number of subjects you took for current semester (2~6): ");
        scanf("%d", &no);
    } while (no < 2 || no > 6);

    return 0;
}

另一个问题可以通过使用标准 C 库来解决。只需#include &lt;string.h&gt;#include &lt;ctype.h&gt;

#include <stdio.h>
#include <string.h> /* strlen() */
#include <ctype.h> /* isdigit() */

int main()
{
    int n, invalidInput, status;
    char strInput[5];
    int i; /* for loop */

    do {
        invalidInput = 0;
        printf("Enter a **number** between 1 and 100: ");
        fflush(stdin);
        status = scanf("%4s", strInput); /* read at maximum 4 chars from stdin */
        if (status > 3) {
            continue; /* try again */
        }

        for (i = 0; i < strlen(strInput); ++i) { /* ensure that all characters are numbers */
            if (!isdigit(strInput[i])) {
                invalidInput = 1;
                break;
            }
        }

        if (!invalidInput) {
            n = atoi(strInput); /* now your input is a integer */
            if (n < 1 || n > 100) {
                printf("Error: the input must be between 1 and 100.\n");
                invalidInput = 1;
            }
        }
    } while (invalidInput); /* repeat until all chars are digits and they are in the required interval */

    return 0;
}

【讨论】:

    【解决方案2】:

    do-while 循环非常适合需要至少调用一次并且可以摆脱重复代码的循环。读取非结构化输入,可能来自键盘,(可以调用,./a.out &lt; text.txt)实际上是一件很棘手的事情。

    幸运的是,C 常见问题解答有很多建议,例如,http://c-faq.com/stdio/scanfprobs.html。但是,如果没有功能,这将是非常艰巨的。通过有限的测试,我很确定这是读取第一个变量的可靠方法。

    #include <stdio.h>  /* fgets sscanf */
    #include <stdlib.h> /* EXIT_ printf fprintf */
    #include <string.h> /* strlen */
    
    int main(void) {
        int no;
        /* Input number, no \in [2, 6], and make sure that the read cursor is on
         the next line. */
        do {
            char buffer[80];
            size_t len;
            printf("Enter number of subjects you took for current semester, [2, 6]: ");
            /* On the advice of http://c-faq.com/stdio/scanfprobs.html, this reads
             into a buffer first. */
            if(!fgets(buffer, sizeof buffer, stdin)) {
                if(feof(stdin)) {
                    fprintf(stderr, "Premature EOF.\n");
                } else {
                    /* On IEEE Std 1003.1-2001-conforming systems, this will print
                     a meaningful error. */
                    perror("stdin");
                }
                /* Can't really do anything interactive once stdin has a read
                 error. */
                return EXIT_FAILURE;
            }
            /* This is always going to be true, but segfaults if not. Paranoid. */
            if(!(len = strlen(buffer))) continue;
            /* Normally fgets stores a '\n' at the end; check. */
            if(buffer[len - 1] != '\n') {
                /* Check if the length of the buffer is big enough to hold input. */
                if(len >= sizeof buffer - 1) {
                    int c;
                    fprintf(stderr, "Line too long.\n");
                    /* Flush whole line. http://c-faq.com/stdio/stdinflush2.html */
                    while((c = getchar()) != '\n') {
                        if(c != EOF) continue;
                        if(feof(stdin)) fprintf(stderr, "Premature EOF.\n");
                        else            perror("stdin");
                        return EXIT_FAILURE;
                    }
                    continue;
                } else {
                    /* Non-POSIX lines, eg, file without '\n' terminating. */
                    fprintf(stderr, "Note: line without line break detected.\n");
                }
            }
            /* Parse buffer for a number that's between [2, 6]. Ignore the rest. */
            if(sscanf(buffer, "%d", &no) != 1 || no < 2 || no > 6) {
                fprintf(stderr, "Invalid input.\n");
                continue;
            }
            /* Now no \in [2, 6]. */
            printf("no: %d\n", no);
            break;
        } while(1);
        return EXIT_SUCCESS;
    }
    

    如果你的老师只输入格式正确的数字,你可能会逃脱其中的一部分。

    【讨论】:

    • if(!(len = strlen(buffer))) continue; 重复检查 if(!fgets(buffer, sizeof buffer, stdin)) -- 通过第一个测试的唯一方法是 buffer 中是否有字符。 if(buffer[len - 1] != '\n') 不保证 "Line too long.\n"。 (非 POSIX EOF 或用户生成的 EOF,例如 [Ctrl+d] 会这样做)而不是检查 if (len &amp;&amp; buffer[len-1] == '\n') buffer[--len] = 0; else if (len == sizeof buffer - 1) { /* then too long */ }。不要吝啬buffer 的大小。 5121024 都可以。
    • 我没有遇到任何消息来源明确表示fgets 将填充至少一个字符以在所有机器中返回 true。本质上,使用if(len &amp;&amp; ...) 将检查移至下一行接受非POSIX 行,而不接受我的代码将拒绝的\n。因此,EOF 在行尾之前会导致,"Line too long.\n";消息不准确。缓冲区通常很小;一个可以使用,LINE_MAX&lt;limits.h&gt; 中定义。
    • man 3 fgets RETURN "fgets() 在成功时返回 s,在错误或未读取任何字符时出现文件结束时返回 NULL。"
    • 我添加了一个检查来区分非 POSIX 和超长行,len &gt;= sizeof buffer - 1。感谢您的评论。
    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多