简体   繁体   中英

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

I'm writing a program which identifies what triangle a user can make by inserting 3 integers. After which based on the conditions and statements it goes through, it identifies whether the triangle they can make is a EQUILATERAL(all sides the same), or SCALENE(No sides the same), or ISOSCELES(Two sides the same). The user is to enter a value between 1-15cm in each occasion its asked. If the user types anything below or above the limit, the program would advise them it cannot be done and simply stop.

Here is my code

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

The image below is the result of when the program is compiled and running. 这是程序运行时的结果。

Basically whether i insert a valid integer or invalid integer, it still gives the same result as the screenshot.

I'm still learning C so I may be missing a thing here and there, so any help is really much appreciated.

Also I want to be able to add a conditional while loop in order to stop the user from inserting an incorrect value or inserting a character when an integer is required. Where about's would I insert the while loop and how would I write it exactly?

UPDATE 1. I have updated the code section

 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)

它的工作!

All responses directed me to the same issue and answer. I have updated the code respectively and it works perfectly fine as seen in the second screenshot.

Also I tested the values for each triangle and it works perfectly fine.

There is one other thing I have come across. When testing to insert a value other than an integer, it comes up with something like the screen shot below.

在此处输入图片说明

I know I have to insert a condition to stop someone inserting anything other than an integer however that's where I'm a little stumbled. I'm not quite sure how to do that without a while loop function. any ideas?

UPDATE 2: I have updated my code to so that float number can be seen as valid since triangles can have a float integer. However..

第4期

By doing so, the while loop condition in the code still makes the statement appear right after asking the user to enter a value for sideB and sideC . Any ideas how to fix?

Also

When testing just inserting a null value or pressing enter, nothing happens to the program. How can we make it so that by a user cannot have null as a value?

UPDATE 3: After debugging I found the issue after Update 2. I just changed %d to %f` and that fixed that issue. Still figuring out the issue with null values or not allowing the enter of spacebar. If anyone has idea regarding this. Please let me know

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

This doesn't test what you think it does. It's parsed as

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

so the test is true if sideA is nonezero, or if sideB is nonzero, or if sideC is negative or zero.

If you're used to other programming languages with a boolean type, you might think that an expression like sideA isn't a boolean, so this should trigger a type error. But C effectively treats integers as booleans: a boolean in C is in fact an integer value that is either 0 (meaning false) or 1 (meaning true). For example, the value of sideC <= 0 is 1 if sideC is less than 0, and 0 otherwise. The value of a || b a || b is 0 if a and b are both 0 and 1 otherwise.

C doesn't have any built-in construct to test if one of three values is negative. The clearest way to express that is

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

You made a similar mistake in other if statements.

As explained very well by @ Gilles ( full credit goes to him for such a nice explanation )

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

is checking

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

it should be

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

Your other if statements are wrong as well, like

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)

All of these might be valid, but they do not do what you expect of them. These can be solved by changing them to

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) )

So, your code should be

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

EDIT

I've edited the code as per your question Update

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

Now, lets explain this piece of code.

Quoting from man , the return type of scanf() is as follows

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.

In this case, we are not going to encounter EOF ( at least I hope we don't ), so I will skip that part.

So, in your case, if scanf("%d", &sideB) successfully assigns the value to sideB , then scanf() will return 1, so I use the condition as given in the loop to make the loop continue as long as scanf() doesn't return 1.

Now lets move onto

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

getchar() reads a character from stdin ( the standard input device, which in your case would be your keyboard, or from the input buffer when something is already present in the buffer ), but a little differently than you expect.

scanf("%d", &sideB) does not assign anything other than integers to sideB ( as you are using %d ). So, what happens when we enter a character. Well, the characters and whitespaces ( spaces, newlines, etc ) remain in the input buffer. Then, your next scanf() would try to read from the buffer, and encounter the character and would not assign it and leaves it in the buffer, and hence, all the remaining scanf() 's would do the same ( as they have %d . Note that if there was a %s type specifier, it would read the characters ). So, in order to prevent such errors, I used that while loop with the getchar() .

Now, the coming back to the code

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

Now, all the trailing characters and whitespaces left behind in the buffer by scanf() are read by getchar() , until a '\\n' is encountered, so in otherwords, the while loop keeps on executing until a '\\n' is read from the buffer, thereby, flushing the buffer to ensure that no newline or character is left in the buffer, or otherwise, the next scanf() would attempt to read from the buffer and would encounter it, and hence, due to the %d type specifier, it just leaves all of those characters in the buffer, and hence no values are actually stored. So, I used that while loop to flush the buffer.

The small detail specified by @ Weather Vane is also Important

Hope you are able to understand all of that ( I'm not good at explaining so please forgive me if what I have said doesn't make sense )

Hope this helps you.....

You have still missed a trick in this: the program lets me input a triangle with sides 1, 1 and 3 and tells me it is a valid isosceles triangle, when it is NOT. Such triangle cannot exist. It needs an additional test so ensure the sum of any two sides is greater than the third

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

Added pseudo code for a loop:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM