C程序中的条件不能给出所需的结果

时间:2015-03-22 15:58:51

标签: c if-statement boolean-logic

我正在编写一个程序,通过插入3个整数来识别用户可以制作的三角形。之后,根据它所经历的条件和陈述,它确定它们可以制作的三角形是平衡(所有边都相同),还是SCALENE(没有边相同),或者ISOSCELES(双面相同)。用户在每次询问时输入1-15cm之间的值。如果用户键入低于或高于限制的任何内容,程序会建议他们无法完成并且只是停止。

这是我的代码

    /*** Purpose: To create a C program which takes 3 integers and produces a result that shows which triangle(If valid) they have chosen.***/

   #include <stdio.h>
int main()
{
    /*** Declaring triangle variable sides ****/

  float sideA;
  float sideB;
  float sideC;
  char ch;

  printf("Lets explore triangles! Please insert a value for side 'A' of your triangle.\n");
  printf(" Ranging from 1-15cm.\n");
  while(scanf("%d", &sideA) != 1)
  {
    printf("You inserted an incorrect value. Please insert a number ranging between 1-15cm, and try again.\n");
    while ( (ch=getchar()) != '\n' );
  }

  printf(" Now insert a value for side 'B' of your triangle.\n");
  while(scanf("%d", &sideB) != 1 )
  {
    printf("You inserted an incorrect value. Please insert a number ranging from 1-15cm, and try again.\n");
    while ( (ch=getchar()) != '\n' );
  }

  printf(" And finally, insert a value for side C of your triangle ranging from 1-15cm.\n");
  while(scanf("%d", &sideC) != 1 )
  {
    printf("You inserted an incorrect value. Please insert a number ranging from 1-15cm, and try again.\n");
    while ( (ch=getchar()) != '\n' );
  }

  /*** List of conditions based on user input to identify if the triangle is valid and if so, what type of triangle they get***/

  if(sideA <=0 || sideB<=0 || sideC <=0)
  {
      printf(" You cannot have a triangle with any side having a value of 0.\n");
  }
  else
      if( (sideA+sideB<=sideC) || (sideB+sideC<=sideA) || (sideC+sideA<=sideB) )
      {
          printf("Your triangle is invalid!\n");
          printf("The sum of every pair of sides must be greater than the third side of a triangle.!\n");
          printf("Please try again.\n");
      }
      else
           if( (sideA==sideC && sideB==sideC) || (sideB==sideA && sideC==sideA) || (sideC==sideB && sideA==sideB) ) /*** Code to determine EQUILATERAL TRIANGLE***/
           {
              printf(" Your input creates a valid EQUILATERAL triangle.\n");
           }
           else 
               if( (sideA == sideB ) || (sideB == sideC ) || (sideC == sideA ) )/*** Code to determine ISOSCELES TRIANGLE***/
               {
                   printf("Your input creates a valid ISOSCELES triangle.\n");
               }
               else
                   if( (sideA!= sideB) && (sideB != sideC) )/*** Code to determine SCALENE triangle ***/
                   {
                       printf("Your input creates a valid SCALENE triangle.\n");
                   }
                   else
                   {
                       printf("You have inserted invalid range of values, as a result your triangle is invalid.\n");
                       printf("Please restart the program by closing it and opening it again to retry\n.");
                       printf("Goodbye.\n");
                   }
return(0);
}

下图是编译和运行程序时的结果。 This is the result when the program is running.

基本上,无论我是插入有效整数还是无效整数,它仍然会提供与屏幕截图相同的结果。

我还在学习C所以我可能会在这里和那里错过任何一件事,所以任何帮助都非常感激。

此外,我希望能够添加条件while循环,以阻止用户插入不正确的值或在需要整数时插入字符。我将在何处插入while循环,我将如何编写它?

更新1。 我已更新了代码部分

 if(sideA <=0 || sideB <=0 || sideC <=0)
  {
      printf(" You cannot have a triangle with any side having a value of 0.\n");
  }
  else 
      if(sideA >15 || sideB >15 || sideC >15)

Its working!

所有回复都指导我同样的问题和答案。我已经分别更新了代码,它在第二个屏幕截图中看到的效果非常好。

我也测试了每个三角形的值,它完全正常。

还有另外一件事我遇到过。当测试插入除整数之外的值时,它会出现类似下面的屏幕截图。

enter image description here

我知道我必须插入一个条件来阻止某人插入除整数之外的任何东西,但这就是我有点绊倒的地方。如果没有while循环函数,我不太清楚如何做到这一点。任何想法?

更新2:我已经更新了我的代码,以便浮点数可以被视为有效,因为三角形可以有一个浮点整数。然而..

Issue 4

通过这样做,代码中的while循环条件仍然会在要求用户输入sideBsideC的值后立即显示该语句。任何想法如何解决?

另外

当测试只插入null值或按Enter键时,程序没有任何反应。我们如何才能使用户不能将null作为值?

更新3:  调试后,我在更新2之后发现了问题。我刚刚将%d更改为%f`并修复了该问题。仍在使用空值或不允许输入空格键来解决问题。如果有人对此有所了解。请让我知道

3 个答案:

答案 0 :(得分:5)

if(sideA || sideB || sideC <=0)

这不会测试你的想法。它被解析为

if ( (sideA) || (sideB) || (sideC <= 0) )

因此如果sideA非零,或者sideB非零,或者sideC为负数或零,则测试为真。

如果您习惯使用布尔类型的其他编程语言,您可能会认为像sideA这样的表达式不是布尔值,因此这应该会触发类型错误。但是C有效地将整数视为布尔值:C中的布尔值实际上是一个整数值,它是0(表示假)或1(表示真)。例如,如果sideC <= 0小于0,则sideC的值为1,否则为0。如果a || ba均为0,则b的值为0,否则为{。

C没有任何内置构造来测试三个值中的一个是否为负数。最明确的表达方式是

if (sideA <= 0 || sideB <= 0 || sideC <= 0)

你在其他if陈述中犯了类似的错误。

答案 1 :(得分:1)

正如@ Gilles所解释的那样 (完全可靠的归功于他这么好的解释)

if(sideA || sideB || sideC <=0)

正在检查

if ( (sideA) || (sideB) || (sideC <= 0) )

应该是

if(sideA <=0 || sideB<=0 || sideC <=0)

您的其他if语句也是错误的,例如

if(sideA || sideB || sideC >15)
if(sideA && sideB==sideC || sideB && sideC==sideA || sideC && sideA==sideB)
if(sideA==sideB || sideB==sideC || sideC==sideA)
if(sideA!= sideB && sideC || sideB!= sideC && sideA || sideC!= sideA && sideB)

所有这些都可能有效,但它们没有达到您对它们的期望。这些可以通过将它们更改为

来解决
if(sideA>15 || sideB>15 || sideC >15)
if( (sideA==sideC && sideB==sideC) || (sideB==sideA && sideC==sideA) || (sideC==sideB && sideA==sideB) )
if( (sideA == sideB) || (sideB == sideC) || (sideC == sideA) 
if( (sideA!= sideB) && (sideB != sideC) )

所以,你的代码应该是

#include <stdio.h>
int main()
{
    /*** Declaring triangle variable sides ****/

  int sideA;
  int sideB;
  int sideC;
  char ch;

  printf("Lets explore triangles! Please insert a value for side 'A' of your triangle.\n");
  printf(" Ranging from 1-15cm.\n");
  while(scanf("%d", &sideA) != 1 )
  {
    printf("Please enter a number\n");
    printf("Lets explore triangles! Please insert a value for side 'A' of your triangle.\n");
    printf(" Ranging from 1-15cm.\n");
    while ( (ch=getchar()) != '\n' );
  }

  printf(" Now insert a value for side 'B' of your triangle ranging from 1-15cm.\n");
  while(scanf("%d", &sideB) != 1 )
  {
    printf("Please enter a number\n");
    printf(" Now insert a value for side 'B' of your triangle ranging from 1-15cm.\n");
    while ( (ch=getchar()) != '\n' );
  }

  printf(" And finally, insert a value for side C of your triangle ranging from 1-15cm.\n");
  while(scanf("%d", &sideC) != 1 )
  {
    printf("Please enter a number\n");
    printf(" And finally, insert a value for side C of your triangle ranging from 1-15cm.\n");
    while ( (ch=getchar()) != '\n' );
  }

  /*** List of conditions based on user input to identify if the triangle is valid and if so, what type of triangle they get***/

  if(sideA <=0 || sideB<=0 || sideC <=0)
  {
      printf(" You cannot have a triangle with any side having a value of 0.\n");
  }
  else
      if(sideA>15 || sideB>15 || sideC >15)
      {
          printf("Please insert a value between 1cm-15cm only\n.");
      }
      else
          if( (sideA==sideC && sideB==sideC) || (sideB==sideA && sideC==sideA) || (sideC==sideB && sideA==sideB) ) /*** Code to determine EQUILATERAL TRIANGLE***/
          {
              printf(" Your input creates a valid EQUILATERAL triangle.\n");
          }
          else
              if( (sideA == sideB) || (sideB == sideC) || (sideC == sideA) )/*** Code to determine ISOSCELES TRIANGLE***/
              {
                  printf("Your input creates a valid ISOSCELES triangle.\n");
              }
              else
                  if( (sideA!= sideB) && (sideB != sideC) )/*** Code to determine SCALENE triangle ***/
                  {
                     printf("Your input creates a valid SCALENE triangle.\n");
                  }
                  else
                  {
                      printf("You have inserted invalid range of values, as a result your triangle is invalid.\n");
                      printf("Please restart the program by closing it and opening it again to retry\n.");
                      printf("Goodbye.\n");
                  }
return(0);
}

修改

我根据您的问题更新

编辑了代码
  while(scanf("%d", &sideB) != 1 )
  {
    printf("Please enter a number\n");
    printf(" Now insert a value for side 'B' of your triangle ranging from 1-15cm.\n");
    while ( (ch=getchar()) != '\n' );
  }

现在,让我们解释一下这段代码。

man引用,scanf()的返回类型如下

  

这些函数返回成功匹配和分配的输入项的数量,可以少于提供的数量,或者在早期匹配失败的情况下甚至为零。

     

如果在任何一个输入结束之前到达输入结束,则返回值EOF   第一次成功转换或匹配失败。 EOF是   如果发生读错误也会返回,在这种情况下会出错   设置流的指示符(请参阅ferror(3)),并设置errno   表明错误。

在这种情况下,我们不会遇到EOF(至少我希望我们不会),所以我会跳过那部分。

因此,在您的情况下,如果scanf("%d", &sideB)成功将值分配给sideB,则scanf()将返回1,因此我使用循环中给出的条件来生成循环只要scanf()没有返回1,就会继续。

现在让我们进入

while ( (ch=getchar()) != '\n' );

getchar()从stdin读取一个字符(标准输入设备,在你的情况下是你的键盘,或者当缓冲区中已存在某些东西时从输入缓冲区读取),但与你期望的有点不同

scanf("%d", &sideB)不会将除整数之外的任何内容分配给sideB(因为您正在使用%d)。那么,当我们输入一个角色时会发生什么。好吧,字符和空格(空格,换行符等)保留在输入缓冲区中。然后,你的下一个scanf()将尝试从缓冲区中读取,并遇到该字符并且不会将其分配并将其保留在缓冲区中,因此,所有剩余的scanf()将执行相同的操作(因为他们有%d。请注意,如果有%s类型说明符,它将读取字符)。因此,为了防止出现这种错误,我使用了getchar()。{/ p>

现在,回到代码

while ( (ch=getchar()) != '\n' );

现在,scanf()读取缓冲区中留下的所有尾随字符和空格都被getchar()读取,直到遇到'\n',因此在其他方面,while循环继续执行直到从缓冲区中读取'\n',从而刷新缓冲区以确保缓冲区中没有新行或字符,否则,下一个scanf()将尝试从缓冲区读取会遇到它,因此,由于%d类型说明符,它只是将所有这些字符留在缓冲区中,因此实际上没有存储任何值。所以,我使用while循环来刷新缓冲区。

@ Weather Vane指定的小细节也很重要

希望你能够理解所有这些(我不擅长解释所以请原谅我,如果我说的话没有意义)

希望这可以帮助你......

答案 2 :(得分:1)

你仍然错过了一个技巧:程序让我输入一个边1,1和3的三角形,告诉我它是一个有效的等腰三角形,当它不是时。这种三角形不可能存在。它需要一个额外的测试,所以确保任何两个方面的总和大于第三个

else
    if( (sideA+sideB<=SideC) || (sideB+sideC<=SideA) || (sideC+sideA<=SideB) ) /*** check triangle is even possible ***/
    {
    printf("Your input cannot be a triangle because the sum of every pair of sides must be greater than the third side.\n");
    }

为循环添加了伪代码:

do {
    ok = true
    get 3 inputs
    if input fails
        ok = false
    else if test 1 fails
        print message 1
        ok = false
    else if test 2 fails
        print message 2
        ok = false
    ...
} while (!ok)

if 3 sides equal
    print equilateral message
else if 2 side equal
    print isosceles message
else
    print scalene message