使用布尔标志来检测输入错误,C

时间:2014-07-13 01:32:54

标签: c if-statement char boolean flags

我正在尝试创建一个布尔标志,当输入无效的输入代码时,该标志将输出错误消息。这是一个课堂作业,我只是学习C所以请原谅格式化,并通知我是否可以改进。如果输入或输出变量不正确,除了输出错误消息之外,我有代码执行所有操作。我相信这是代码的布尔检查部分的错误。诊断会很好。

此代码将:

  • 请求和来源货币,目标货币和来源金额
  • 如果输入变量不正确,
  • 输出目的地货币金额或错误消息

参数:

  • 来源和目的地货币必须是加元($),日元(Y)或欧元(E)
  • 必须使用布尔标志

先谢谢。

# include <stdio.h>

int main() {

    char $ = $; 
    char Y = Y;
    char E = E;

    char in_currency, out_currency;

    char flag = 1;
    char new_line;

    float in_value;
    float out_value;

    //Calculation variables

    printf("Enter the source currency: ");
    scanf("%c%c", &in_currency, &new_line);

    printf("Enter the destination currency: ");
    scanf("%c%c", &out_currency, &new_line);

    if ( ( in_currency || out_currency ) != ( '$' || 'Y' || 'E' ) )
        flag = 0;

    printf("Enter the value: ");
    scanf("%f%c", &in_value, &new_line);

    //Calculations

    if (flag) {
        printf("%c%.2f = %c%.2f \n", in_currency, in_value, out_currency, out_value);
    }
    else {
        printf("There was an error with the input. \n");
    }

    return 0;
}

2 个答案:

答案 0 :(得分:2)

感谢@JonathanLeffler的精彩评论。

我认为这可能是由于你的if语句的逻辑顺序

 if ( ( in_currency || out_currency ) != ( '$' || 'Y' || 'E' ) )
    flag = 0;

你打算做的事情如下

 if ( 
  (in_currency == '$' ||  in_currency == 'Y' ||  in_currency == 'E')
  || 
  ( out_currency == '$' ||  out_currency == 'Y' ||  out_currency == 'E') 
  ) flag = 0;

这是由于您的原始行的评估方式。      (in_currency || out_currency)

注意C++ standard(第6.8.4.1节)陈述

  

如果表达式将une等于0,则执行子语句。

与输入相同      (in_currency!= 0 || out_currency =!0) 请注意,测试单个值将始终针对非零进行测试,有时会被视为“真实”值。

简而言之,if语句的第一部分将始终返回true,因为两个测试(非零字符值)都等于true。

可以看到这一点(不为零 OR out 不为零),因为两个值都不为零,两个测试都等于变为真实,成为( OR ) - 显然这反过来也是如此。

if语句的后半部分差别不大

 ( '$' || 'Y' || 'E' ) 

这也等同于(真或假或真),因此总是等于真如下:

( '$' != 0 || 'Y' != 0 || 'E' != 0) 

最后,这会分解为您的代码阅读:

 if ((in_currency != 0 || out_currency =! 0) != ( '$' != 0 || 'Y' != 0 || 'E' != 0)) 

 if ((true || true) != ( true || true || true)) 
 if ((true) != (true))

显然,这将始终等于false,因为true永远不等于true(除非某些通用常量更改; - )

结果是你的旗帜总是假的。 - 始终

我已经给你替换它的行,而是分别测试每个可能的情况场景并比较结果。

您可以将其视为

  if 
      in_currency **is equal to** '$' *or*  
      in_currency **is equal to** 'Y' *or*
      in_currency **is equal to** 'E'
    or 
      out_currency **is equal to** '$' *or*  
      out_currency **is equal to** 'Y' *or*
      out_currency **is equal to** 'E'
 then flag = 0;

[编辑]

用户Turboc在下面回答说您可能希望使用&amp;&amp; ()而不是这两个陈述之间的。(请原谅我在此处提供此信息,但我还不能对答案发表评论)

这取决于您打算如何评估您的语句 - 如果您希望该标志等于false(0)如果货币是上述任何一种,对于输出或输入,那么情况并非如此)。

但是,如果您希望声明为真,只要货币是以上之一,您就会使用以下

  if 
      in_currency **is equal to** '$' *or*  
      in_currency **is equal to** 'Y' *or*
      in_currency **is equal to** 'E'
    and 
      out_currency **is equal to** '$' *or*  
      out_currency **is equal to** 'Y' *or*
      out_currency **is equal to** 'E'
 then flag = 1;

但是,如果是这种情况,您可能希望确定哪种答案是解决问题的更有效方法。

答案 1 :(得分:1)

将一些评论和其他笔记转换为答案

  

这些语句:char $ = $; char Y = Y; char E = E;通过使用自己的未初始化值初始化变量来调用未定义的行为(或者至少不会实现任何有用的行为)。变量$在标准C中无效;您可以找到允许它的C编译器(特别是如果您使用VMS)。遗憾的是,这不是一个好的开始。其余代码不使用变量的事实是另一个问题。你可以简单地删除它们。

     

请注意,如果用户输入了来源货币&#39;作为GPB,new_line变量不会包含换行符。使用" %c"(空格,百分比,&#39; c&#39;)作为格式字符串可能会做得更好;它会跳过(可选)前导空格(空格,制表符,换行符),然后是一个字符。重复目标货币;它将跳过您期望的换行符,然后读取下一个非空格字符。 "%f%c"格式中没有什么意义;它并不能保证你会读取换行符(并且你不会检查它是否存在)。

另外,正如其他人也指出的那样:

if ( ( in_currency || out_currency ) != ( '$' || 'Y' || 'E' ) )

没有做你想做的事。由于C的工作方式,!=的RHS求值为true(因为'$'不为零),并且除非in_currency和{{1},否则它的LHS计算结果为真是零,这是非常不可能的(许多人不知道如何在键盘上键入ASCII NUL - 也就是零字节或out_currency)。

正如我在评论中所说:

  

原文可能意在表示:_如果'\0'不是in_currency'$''Y',或'E'不是out_currency'$''Y'中的一个,然后将标记设置为0.

你需要更像

的东西
'E'

我看到一个条件的版本写成:

if (( in_currency != '$' &&  in_currency != 'Y' &&  in_currency != 'E') ||
    (out_currency != '$' && out_currency != 'Y' && out_currency != 'E'))
    flag = 0;

这不能正常工作。想一想:假设if (( in_currency != '$' || in_currency != 'Y' || in_currency != 'E' ) || (out_currency != '$' || out_currency != 'Y' || out_currency != 'E' )) flag = 0; 是Y(日元)。术语in_currency将为真(因为值为Y),因此整体条件为真(未评估任何其他项),in_currency != '$'将设置为零。如果您flag分隔&&个字词,则in_currency将为真,但in_currency != '$'将为false,因此条件的in_currency != 'Y'部分将为false - 这很好,因为货币代码有效。然后它将继续评估(in_currency != '$' && in_currency != 'Y' && in_currency != 'E')项(也使用out_currency),并且只要out_currency值正确,也会通过。

请注意,将&&形式与同一个变量(a != v1 || a != v2)与两个不同的值av1进行比较的条件始终是真实的。请注意,这个领域的常用英语用法有点滑;你必须非常小心和挑剔才能使条件正确。您还需要了解De Morgan的定理(q.v。)。

您可以使用代码选择其他问题。例如,您的错误消息不是很有用。在您获得足够的信息以确定其无效后,您需要用户继续输入数据。您需要确保您的代码处理用户选择从欧元转换为欧元的情况(或者更常见的是,输入相同的货币代码两次)。

编写好的代码部分是为了理解用户如何破坏你的最佳意图,并在问题发生之前解决问题。