带有验证循环的 C 菜单问题(针对许多打印件)

C menu problem with a validating loop (to many prints)

我正在与合作伙伴(我们是大学生)一起研究菜单,但无法解决满足某些条件的错误,循环打印菜单的次数超过了所需的次数。 当我想将一个负数输入一个 char 变量时,我遇到了所有问题,我用“(短)输入<1”修复了这个问题,尽管我认为这样做应该是一种更有效的内存方式。

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


char main() {
    char choice;
    printf("what would you like to do? use number keys to make a choice.\n");
    printf("Database System Menu:\n1. Add person\n2. Search a person\n3. Search Parents\n4. Delete a person\n5. Get generation\n6. Print database\n7. Search by name\n8. Quit\n");
    scanf("%c", &choice);
    while ((short)choice<1 || (short)choice>8) {
        printf("elegal coice use 1 through 8 keys.\n");
        scanf("%c", &choice);
    }
    if ((short)choice >= 1&&(short)choice < 8) {
        return choice;
    }
    else return '[=10=]';
}

我们尝试过的选项 2:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
    char input = '0';
    while (input != '8')
    {
        printf("Database System Menu:\n");
        printf("1. Add person\n");
        printf("2. Search a person\n");
        printf("3. Search Parents\n");
        printf("4. Delete a person\n");
        printf("5. Get generation\n");
        printf("6. Print database \n");
        printf("7. Search by name\n");
        printf("8. Quit\n");
        scanf("%c", &input);
        if ((short)input < 1 || input >'8')
        {
            printf("Invalid input\n");

        }


    }
}

如您所知,%c 说明符正好从标准输入中获取一个字符,但是当您输入一个字符时,您按 Enter 会导致换行要添加到输入缓冲区的字符,因此您将在 stdin 中有两个字符,循环 运行s 两次,第二次是由换行符引起的。


方法 #1:

要丢弃空白字符,例如 \n,只需在说明符前使用 space,,即 scanf("%c", &input); 替换为 scanf(" %c", &input);,注意 %c 说明符之前的 space。剩下的问题是循环将循环与输入缓冲区中的字符一样多的次数例如如果你输入asdf循环仍将循环四次而不是一次。

负数问题与上面有关,负数输入至少需要2个字符,所以问题就出在这里,循环运行 3次输入-9, 2 个字符 2 次,\n 第三次(如果您还没有修复 \n 问题)。


方法 #2:(更好)

要丢弃标准输入中的所有字符,您可以使用类似的东西:

int c;
while(( c = getchar()) != '\n' && c != EOF){}

之后scanf.

使用第二种方法,您不仅可以解决 \n 问题,还可以丢弃您输入的任何额外字符,例如 假设您输入 8asds8 将被解析,但所有其他字符将被丢弃,避免不必要的额外循环。


注意更健壮的方法是使用fgets解析输入的字符串,如果需要转成数值,使用strtoll,不要使用 atoi 这是一个不安全的函数。


input < 1 看起来是个错字,你可能是说 input < '1'.

  • 当您像 (short)input 那样进行转换时,它不会保留位表示,而是将其转换为新类型。将 char c = 255 转换为带符号的 8 位整数不会变成带符号的整数 -1 ,但仍然是 255。要保持位表示,您可以尝试一些方法,例如 int8_t i = -*(int8_t*)&c;。另外,short 是 2 个字节。

  • 比较小于 1 的 char 值似乎很奇怪。 '1' 应该是 49。也许查看 ASCII Table.

  • 循环可能是输入过多或换行符引起的。请记住 %c 一次仅消耗 1 个字符,包括新行。所以,如果你的输入是“-1”,它首先扫描'-',再次进入循环,然后扫描'1'。更改为 scanf(" %c", input); 以删除任何白色 space(space、制表符或 \n