1

我正在学习 c 并且理解这种语言是低级的,在这种情况下缺乏异常处理。

我制作了一个简单的程序,用户可以在其中从菜单中选择一些选项。就是这么简单!

该程序分为几种方法-其中一种方法等待用户按下键-预期为整数。然后将此整数返回到另一个持有开关结构的方法。

按下字符时会出现问题 - 在大多数情况下,else 块的无限循环会启动。

您必须选择替代 0 - 2。请再试一次 :-)

您必须选择替代 0 - 2。请再试一次 :-)

您必须选择替代 0 - 2。请再试一次 :-)

...... 等等

我实际上不知道如何解决这个问题。我试图使用 scanf 函数的返回值但没有成功。我还尝试将一个字符(而不是整数)作为参数传递给 scanf 函数 - 也没有成功。

任何建议如何处理这个问题?

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

void menu();
void runSelection(int selection);
int getSelection();
int pause();


int main(void) {

do{
    menu();
    runSelection(getSelection());
}while(pause());

return 0;
}

int pause() {
int c;
printf("\n\nPress enter to continue!");
fflush(stdout);
/* flush inputstream */
while((c = getchar()) != '\n' && c != EOF);
getchar();
return 1;

}

void menu() {

puts(" * * * * * *   M E N U  * * * * * * *");
puts("1. Do something 1");
puts("2. Do something 2");
puts("3. Do something 3");
fflush(stdout);
}

void runSelection(int selection) {

switch (selection) {
    case 0:
        puts("you pressed 0");
        break;
    case 1:
        puts("you pressed 1");
        break;
    case 2:
        puts("you pressed 2");
        break;
}
}

int getSelection() {

int key;
int true = 0;
do {

    scanf("%d", &key);

    if (key >= 0 && key <=2) {
        true = 1;
    }
    else {
        puts("You must choose an alternative 0 - 2. Please try again :-)");
        fflush(stdout);
    }

} while (true == 0);

return key;
}
4

3 回答 3

2

你有一个无限循环,因为 scanf 正在从输入缓冲区读取一个字符。缓冲区中有一个剩余的字符,换行符'\n'

使用以下宏而不是直接使用 scanf

#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
    char tmp;\
    while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
            || !(COND)) {\
        printf("Invalid input, please enter again: ");\
    }\
} while(0)


int main()

{
    int decision;

    printf("Input data, valid choice 1 or 0: ");
    SCAN_ONEENTRY_WITHCHECK("%d",&decision,(decision==0 || decision==1));
    printf("You have entered good input : %d\n", decision);
}

以下主题包含有关此宏及其使用方法的说明: 读取输入数据并检查其有效性的常用宏

于 2013-10-05T20:15:17.760 回答
0

为什么你没有像其他地方一样'\n'删除尾随?getSelection

利用:

int c;
scanf("%d", &key);
while((c = getchar()) != '\n' && c != EOF); //Add this line

getSelection

于 2013-10-05T20:17:01.987 回答
0

编辑:当我第一次写这个答案时,我对如何scanf()工作非常愚蠢和无知。

  • 首先让我澄清一下,scanf()不是功能损坏,如果我不知道如何scanf()工作并且不知道如何使用它,那么我可能没有阅读手册scans(),这不能是scanf()错的.
  • 其次,为了理解你的代码有什么问题,你需要知道它是如何scanf()工作的。

当您scanf("%d", &key)在代码中使用时,scanf() 会尝试从输入中读取整数,但如果您输入非数值,scanf()则知道它不是正确的数据类型,因此它将读取的输入放回缓冲区,下一个循环周期但是无效的输入仍然在缓冲区中,这将导致scanf()再次失败,因为缓冲区尚未清空,并且这个循环永远持续下去。

为了解决这个问题,您可以使用 的返回值scanf(),这将是成功读取输入的数量,但是您需要通过刷新缓冲区来丢弃无效输入以避免无限循环,输入缓冲区在以下情况下被刷新键被enter按下,您可以使用getchar()暂停功能来获取输入,这将要求您按回车键从而丢弃无效输入,请注意,这不会让您按enter两次键,无论是不是您输入了正确的数据类型,因为newline character仍然会在缓冲区中。成功完成scanf()从输入中读取整数后,它将\n放回缓冲区,因此 getchar() 将读取它,但由于您不需要它,因此丢弃它是安全的:

do
{
    status = scanf("%d", &key);
    getchar();  // flush the buffer by reading a character and discarding it
    if (key >= 0 && key <=2)
    {
        true = 1;
    }
    else
    {
        puts("You must choose an alternative 0 - 2. Please try again :-)");
        fflush(stdout);
    }
} while (true == 0 && status != 1);
于 2013-12-31T12:00:25.823 回答