【问题标题】:A condition in a C program doesn't give the desired resultC 程序中的条件没有给出期望的结果
【发布时间】:2015-03-22 15:58:50
【问题描述】:

我正在编写一个程序,它可以通过插入 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);
}

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

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

我还在学习 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 &lt;= 0 || sideB &lt;= 0 || sideC &lt;= 0) ...。每个条件都必须明确给出。条件 (sideA || sideB || sideC &lt;= 0) 是正确的 C,但它并没有按照您的想法执行:如果 sideAsideB 具有非零值(它们具有)或 sideC 非零,则为真积极的。
  • 你尝试过单步调试代码吗?也许你有一些意想不到的输入?
  • 你所有的条件都没有按照你的想法做
  • 这个if(sideA || sideB || sideC &lt;=0) 相当于if(sideA!=0 || sideB!=0 || sideC &lt;=0)。这就是问题所在。

标签: c if-statement boolean-logic


【解决方案1】:
if(sideA || sideB || sideC <=0)

这并不能测试您的想法。它被解析为

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

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

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

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

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

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

【讨论】:

  • .: 其实很着急我犯了错误编辑的错误。我已经删除了我的帖子。我知道原因。
【解决方案2】:

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

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

引用manscanf()的返回类型如下

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

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

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

因此,在您的情况下,如果scanf("%d", &amp;sideB) 成功地将值分配给sideB,那么scanf() 将返回1,所以我使用循环中给出的条件来使循环继续,只要@987654336 @ 不返回 1。

现在让我们进入

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

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

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

现在,回到代码

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

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

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

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

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

【讨论】:

  • 感谢 Arun,就像其他所有试图解释我遇到的问题的人一样。有了这些解释,它准确地帮助了我做错了什么,我想逻辑在那里,但我不知道它需要那么准确。感谢所有帮助过的人。现在这个问题已经解决了。但是,还有一件事我需要一些帮助。这在帖子的更新部分中进行了解释。
  • 我尝试了代码,它的工作方式与我希望的工作方式非常吻合。给你完整的学分。查看代码,我发现您添加了一个用于 while 循环的 char ch。你能向我解释一下 {while ( (ch=getchar()) != '\n' );} 会发生什么吗另外我怎么能做到这一点,所以插入一个高于或低于我设置的限制的数字也会发生同样的事情?
  • 非常感谢您的深入解释。我了解您所写内容的大约 90%,但是我了解了它的作用以及为什么将 while 循环与 get char 一起使用。这很有道理。我很感激你的解释和帮助。我还有很长的路要走,它的用户,比如你自己和所有帮助过的人,都会激励像我这样的人学习更多。
  • @Shivarn ,很高兴为您提供帮助。您还应该检查Weather Vane 的答案。
  • 我已经更新了代码。我做了一些测试,遇到了 2 个问题。他们在更新中。第一个当用户有空值并按回车时,什么都没有发生,只是转到一个新行,空格键只是跳过一个空格,什么也不做。我更关心的是用户按下回车键,当值为 null 时没有任何反应。
【解决方案3】:

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

【讨论】:

  • 感谢您指出天气。我最初确实想到了这一点,但不太确定我会将这个条件放在代码中的什么位置。你建议我在哪里插入支票?
  • @Weather Vane 我们可以把它放在一个循环中吗?例如,用户插入所有 3 个值,然后程序将检查一侧是否大于两侧,如果不是,则继续,如果是,则返回程序开始,直到给出有效值?
  • 参考@ArunA.S 的答案中改进的代码,您可以像对输入有效性的所有其他检查一样实现它,作为另一个else if 嵌套,我已经调整了我的回答是一样的风格。
猜你喜欢
  • 1970-01-01
  • 2014-11-22
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多