0

我用我从网上编辑的代码和我输入的 switch 语句组合了一个简单的货币转换器程序。当我在 Visual Studio 中运行该程序时:

printf("Would you like to make another conversion? y/n\n");
fflush(stdin);
scanf("%c",&marker);

将等待输入,然后返回到 while 语句的开头或退出控制台窗口。现在,如果我在 Mac 上运行这是 Xcode “你想进行另一次转换...”,但不等待输入,它只是直接返回到 while 循环。

我是否将 printf("Would you like...etc 部分放在正确的位置?或者有没有更好的方法让循环在接受用户输入后再次运行?我需要用 'bool 做任何事情吗? ' 声明。我们在课堂上还没有走那么远。

完整代码如下所示:

#include <stdio.h>

int main ()
{
int choice;
float money;
float total;
char marker='y';

printf("\n\nCURRENCY CONVERSION\n");
printf("***Rates correct as of 26 NOV 12***\n");
printf("------------------------------------\n");
printf("1. Australian Dollar (AUD) 1.533=1 GBP\n");
printf("2. Euro (EUR) 1.235=1 GBP\n");
printf("3. Indian Rupee (INR) 89.494=1 GBP\n");
printf("4. Japanese Yen (JPY) 131.473=1 GBP\n");
printf("5. US Dollar (USD) 1.602=1 GBP\n");
printf("Enter the number for the currency to convert...");

while(marker!='n')
{
    printf("\n\nWhat would you like to convert your money to? (1-5): ");
    scanf("%d",&choice);

    printf("\n\nHow much money do you want to convert? (GBP): ");
    scanf("%f",&money);

    switch(choice) {
        case 1:
            total = money * 1.533;
            printf("\n\nYou will have %.2f Australian Dollars \n\n", total);
            break;
        case 2:
            total = money * 1.235;
            printf("\n\nYou will have %.2f Euros \n\n", total);
            break;
        case 3:
            total = money * 89.494;
            printf("\n\nYou will have %.2f Indian Rupees \n\n",total);
            break;
        case 4:
            total = money * 131.473;
            printf("\n\nYou will have %.2f Japanese Yen \n\n", total);
            break;
        case 5:
            total = money * 1.602;
            printf("\n\nYou will have %.2f US Dollars \n\n", total);
            break;
        default:
            printf("You did not choose a correct option\n");
    }

    printf("Would you like to make another conversion? y/n\n");
    fflush(stdin);
    scanf("%c",&marker);
}
return 0;
}

非常感谢收到的任何意见。

4

4 回答 4

2

这与循环无关。这是关于您对 scanf 的调用。

发生的事情是标准输入被缓冲了。如果缓冲区中没有足够的待处理数据,scanf 只会导致程序停止并等待输入。当你这样做时:

scanf("%f", &f);

...然后程序将停止,直到您键入一行文本。假设您键入:

1\n

1 被读入变量 f...但换行符保留在 buffer 中

这意味着您致电:

scanf("%c", &c);

...将立即返回,因为缓冲区中有足够的数据来完成调用。程序只有在缓冲区用完时才会停止并等待更多数据。

Windows 不会像这样进行缓冲,这就是为什么您没有观察那里的行为。

对此有大约一百万种解决方案,从改变标准输入的缓冲方式到使用像 ncurses 这样的基于文本的 UI 库。鉴于默认情况下 stdin 是行缓冲的——一次读取一行数据,以换行符终止——最简单的方法就是确保每次调用都scanf()使用完整的文本行。这意味着每次调用 scanf 时缓冲区都是空的。例如:

scanf("%f\n", &f);

...和:

scanf("%c\n", &c);

请注意,如果用户输入的输入与此格式字符串不匹配,例如1 2第一个或ab第二个,scanf 将使变量保持未初始化状态。所以你绝对必须检查返回参数。

if (scanf("%f\n", &f") != 1)
    error("Oh noes!");

否则你的程序会非常糟糕,非常错误。

顺便说一句:你没有在这个程序中做过,但你知道,scanf("%s")不应该使用它。为了任何东西。

于 2012-11-26T21:48:48.467 回答
2

您的问题很可能scanf("%c", &marker);是读取先前输入留下的换行符。

请注意,这会fflush(stdin)调用未定义的行为。C标准说fflush()

如果流指向一个输出流或更新流,其中没有输入最近的操作,fflush()则应导致该流的任何未写入数据写入文件。

如果该操作清除了 Visual Studio 或 Windows 中的输入队列,那么您刚刚了解到一个平台上的标准扩展并不总是适用于其他平台。特别是,fflush(stdin)不会清除等待读取的排队字符。

请注意,您可以通过将错误输入打印为错误消息的一部分来帮助您的调试工作。


您还应该测试每个scanf()调用:

if (scanf("%c", &marker) != 1)
    ...EOF or other problem...

if (scanf("%f", money) != 1)
    ...EOF or maybe a letter instead of a number...

从风格上讲,最好在开关的标签break;后面加上一个代码。default:

此外,您应该真正避免在菜单和 case 语句中打印的字符串中重复转换率。货币名称也是如此。也许您还没有涉及数组和结构,但从长远来看,这是一个问题的根源(如果只是因为速率发生变化而浪费了重新编译;但是允许从文件或网站中读取它们是另一个主要练习)。

于 2012-11-26T21:38:31.957 回答
0

您可以执行无限循环(例如 while(true){} ),并且在您的 switch 语句中有一个选择 'n' 的案例,它会中断循环(例如,break;)

此外,案例 1 、案例 2 等...我会将它们扫描为字符而不是整数。(例如案例'1':,案例'2':,等等......)

我不确定我刚才所说的是否可行,但这是我最初的想法。希望能帮助到你 :)

于 2012-11-26T21:37:59.773 回答
0

如果您不想处理刷新缓冲区,可以定义 achar buffer[1024]并使用fgetswith sscanf

printf("\n\nWhat would you like to convert your money to? (1-5): ");
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer, "%d", &choice);

while 循环可以包含您的菜单:

while (1) {
  printf("\n\nCURRENCY CONVERSION\n");
  printf("***Rates correct as of 26 NOV 12***\n");

  /* ... */

  printf("Would you like to make another conversion? y/n\n");
  fgets(buffer, sizeof(buffer), stdin);
  sscanf(buffer, "%c", &marker);
  if (marker == '\n')
    break;
}
于 2012-11-26T21:48:09.437 回答