shanerig
shanerig

Reputation: 11

Why does my do while statement work this way?

This code works but I'm confused on how. I was writing this program for a class. I needed to only accept positive integers. I created a do...while loop to do so. My question is, why does this code only check the correct way when I have the or "||" in there and not the "&&". I would assume it would need to test both to make sure that it is taking in the correct integers.

#include <stdio.h>
#include <math.h>


main()
{
  float i, number, sum=0;
  int k;
do
{
  printf( "Sumation Calculator\n" );
  printf( "Enter number: " );
  scanf( "%f", &number );
  k = number;
}while(number < 1 || k != number);

  while (i <= number)
  {
    sum = sum + i;
    i++;
  }
  
  
  printf( "The summation of %f is %f.\n", number, sum);
  return 0;
}

Upvotes: 1

Views: 67

Answers (3)

chux
chux

Reputation: 154315

Others have explain OP's logic issue.

why does this code only check the correct way when I have the or "||" in there ...

Code is not corrct with only that change. It has too many problems - many of which can be identified by enabling all compiler warnings.

scanf( "%f", &number); will round numeric input text to a float, losing non-integer detection.

k = number; is undefined behavior when number is much outisde int range.

i <= number is bad as i is not yet assigned.

The return value of scanf( "%f", &number ) is not tested for success.

Below is a more robust way to test for input of only positive integers.


I needed to only accept positive integers.

Best to:

  1. Read the line of text into a string.

  2. Parse it as an integer with strtol().

  3. Test for range, etc.


char buf[100];
while (fgets(buf, sizeof buf, stdin)) {
  char *endptr;
  errno = 0; 
  long value = strtol(buf, &endptr, 10);
  if (buf == endtpr) {
    puts("No conversion");
    continue;
  }
  if (errno) {
    puts("Out of long range");
    continue;
  }
  if (*endptr != '\n') {
    puts("Non-numeric trailing junk");
    continue;
  }
  if (val < 0) {
    puts("Only positive values");
    continue;
  }
  // Success, now do something with val
}

This will fail input like "123.0" or "1e2" - which are both whole numbers. Additional code could handle most of those cases.

Upvotes: 1

ShadowRanger
ShadowRanger

Reputation: 155507

You have two requirements:

  1. That the value be positive
  2. That the value be an integer (no fractional/decimal component)

Your test needs to be true if you need to ask again, not if you have the correct value; testing for the correct value would involve two "positive tests" joined by &&, but you want to test for incorrect values, which means you want to reject if either "negative test" fails. You need to ask again if either condition is violated. If you test number < 1 && k != number that means "I need to ask again only if it's both not positive and non-integer", so 0 (which is not positive, but is an integer) would be accepted, as would 1.5 (which is not an integer, but is positive).

Testing number < 1 || k != number correctly says "I need to ask again if it's not positive or it's not an integer"; if it fails either criterion, you loop and ask again.

Upvotes: 2

Joop Eggen
Joop Eggen

Reputation: 109597

do
{
  ...
  k = number;  // now k == number
} while (number < 1 || k != number);

} while (number < 1 || FALSE);
} while (number < 1);

As you see the condition is not needed.

What is the initial value of i?

By the way it is "Summation" I believe.

Upvotes: -1

Related Questions