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

A condition in a C program doesn't give the desired result

我正在编写一个程序,用于识别用户可以通过插入 3 个整数来组成什么三角形。然后根据它所经过的条件和语句,判断他们能做出的三角形是等边三角形(所有边都相同),还是等边三角形(没有边相同),还是等腰三角形(两边相同)。用户将在每次询问时输入 1-15 厘米之间的值。如果用户键入任何低于或高于限制的内容,程序会告知他们无法完成并简单地停止。

这是我的代码

    /*** 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);
}

下图是程序编译后运行的结果。

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

我还在学习 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)

所有回复都将我指向相同的问题和答案。我已经分别更新了代码,如第二个屏幕截图所示,它工作得很好。

我还测试了每个三角形的值,它工作得很好。

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

我知道我必须插入一个条件来阻止某人插入除整数以外的任何内容,但是我有点迷糊了。如果没有 while 循环函数,我不太确定如何做到这一点。有什么想法吗?

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

通过这样做,代码中的 while 循环条件仍然使语句在要求用户输入 sideBsideC 的值后立即出现。有什么解决办法吗?

还有

当测试只是插入一个 null 值或按回车键时,程序没有任何反应。我们怎样才能使用户不能将 null 作为值?

更新 3: 调试后,我在更新 2 后发现了问题。我只是将 %d 更改为 %f` 并解决了该问题。仍在找出空值或不允许输入空格键的问题。如果有人对此有想法。请告诉我

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

这并没有测试你认为它做了什么。它被解析为

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

所以如果 sideA 是非零,或者如果 sideB 是非零,或者如果 sideC 是负数或零,则测试为真。

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

C 没有任何内置结构来测试三个值中的一个是否为负。最清楚的表达方式是

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

您在其他 if 语句中犯了类似的错误。

@ 解释得很好 (完全归功于他如此好的解释)

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' );
  }

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

引用manscanf()的return类型如下

These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.

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

所以,在你的情况下,如果 scanf("%d", &sideB) 成功地将值分配给 sideB,那么 scanf() 将 return 1,所以我使用中给出的条件只要 scanf() 不 return 1.

就可以使循环继续

现在让我们进入

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

getchar() 从 stdin 读取一个字符(标准输入设备,在您的情况下是键盘,或者当缓冲区中已经存在某些内容时从输入缓冲区读取字符),但与你期待。

scanf("%d", &sideB) 不会将除整数以外的任何内容分配给 sideB (因为您正在使用 %d )。那么,当我们输入一个字符时会发生什么。好吧,字符和空格(空格、换行符等)保留在输入缓冲区中。然后,您的下一个 scanf() 将尝试从缓冲区中读取,并遇到字符并且不会分配它并将其留在缓冲区中,因此,所有剩余的 scanf() 都会做同样的事情(因为它们有 %d。请注意,如果有 %s 类型说明符,它将读取字符)。因此,为了防止此类错误,我将 while 循环与 getchar().

一起使用

现在,回到代码

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

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

@ 指定的小细节也很重要

希望你能理解所有这些(我不善于解释,如果我说的不对,请原谅我)

希望对您有所帮助.....

您仍然错过了其中的一个技巧:程序让我输入一个边长为 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