0
std::string turnsDefined;
std::cin >> turnsDefined;
bool hasPassed;    
while(hasPassed != true){
    for(char c : turnsDefined){
        if(isdigit(c) != true){
            std::cout << "Please only use numbers to describe the amount of turns you'd like to do." << std::endl;
            hasPassed = false;
            break;
            std::cin >> turnsDefined;
        }else{
            hasPassed = true;
        }
    }
}

I've recently stumbled upon this. I shortened down the code (by a reasonable amount) just so you can try it yourself.

This short program should check if what you enter contains (unwanted) letters. The thing I don't understand: The way I wrote it, I was pretty sure that if I typed something like test2test it's gonna pass (even though it contains letters) just because the if statement will recognize one single number and set hasPassed to true.

I hope you could make sense of what I wrote. Happy to answer further questions.

Code0
  • 74
  • 1
  • 10
  • isdigit returns an integer. Anything other than 0 is considered true. Does your if statement cast the integer to a bool, or does it cast the bool to an int? I don't know. Probably lots of people don't know. Please either check against 0, or check check for == false or != false, never == true or != true. – Andy Newman Oct 21 '14 at 14:48
  • [This comment](https://stackoverflow.com/questions/26489075/why-is-this-not-returning-true-loop-logic/26489135#comment95971481_26489135) contains some reasoning about why `int` and `bool` comparison should be avoided. – Mohit Jain Feb 08 '19 at 13:28
  • @LightnessRacesinOrbit `if (4)` passes but `if (4 == true)` fails. Inside that if statement it will either convert the return value of isdigit to a bool and compare it to true, or it will convert true to an integer and compare it to the return value. I don't know which. More importantly, I don't _care_ which. I would like to see code where I don't need to know something that obscure to make sense of it. `if (!isdigit)` for preference and clarity, but specifically never compare integers with true. – Andy Newman Feb 10 '19 at 13:33
  • @AndyNewman Hmm, that's true. – Lightness Races in Orbit Feb 10 '19 at 15:30

2 Answers2

4

bool hasPassed is not initialized in your code. You should declare it as:

bool hasPassed = false;

Live code here

Uninitialized automatic (local and non static) variables contain indeterminate value. Reading them prior to assigning a value results in undefined behavior. (Compiler is free to do some blunder here but in practice it may contain true or false or some other non-sense value)

EDIT
From Andy Newman's comment: Condition if(isdigit(c) != true) is suspectible. Because isDigit returns an int you should avoid comparing it with true.

isDigit returns non-zero value (true) if the character is a numeric character, 0 (false) otherwise.

You can better rewrite the condition as:

if(!isdigit(c)) {

Even if a function returns bool, it is superfluous to compare it with true or false

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • I'd just like to note that for some reason, it always worked. Don't really know why, but thanks. I'll mark as correct answer. – Code0 Oct 21 '14 at 14:39
  • _"Because isDigit returns an int you should avoid comparing it with true."_ Not so. See my comment to Andy. The comparison is absolutely fine. It's not "susceptible" to anything! Though I do agree that the short form is best.... as long as you fix the bug in your example (i.e. make it `if (!isdigit(c))`) – Lightness Races in Orbit Feb 06 '19 at 11:58
  • @LightnessRacesinOrbit `isdigit(c)` would return `0` if `c` is not a digit and `non-zero` value otherwise. If this `non-zero` is not `1` (which is allowed), `isdigit(c) != true` and `!isdigit(c)` would give different results. (Former incorrect) I am thinking of an implementation where `unsigned char` has range `0-256`, `EOF` is `257` and library has bitmap array of size 257 containing attributes (isdigit, isupper etc) of all characters and EOF in this array. Function `isX` would do a quick anding and return zero or non-zero value. [isuuper returnts 256](https://www.ideone.com/dhGjQK)here – Mohit Jain Feb 08 '19 at 07:10
  • Thank you @LightnessRacesinOrbit for catching it. Corrected. – Mohit Jain Feb 08 '19 at 07:14
1

From C++ standard:

Using a bool value in ways described by this International Standard as “undefined,” such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false.

Laura Maftei
  • 1,863
  • 1
  • 15
  • 25
  • 1
    Is it guaranteed to be either true and false and not some non-sense value? – Mohit Jain Oct 21 '14 at 14:34
  • @MohitJain It is not true, and it is not false, and it is not some nonsense value. It is unspecified. i.e. _there is no value_. – Lightness Races in Orbit Feb 06 '19 at 12:00
  • @LightnessRacesinOrbit Could be trap representation also. Right? (My first comment was before the edit questioning the answer then) – Mohit Jain Feb 08 '19 at 06:51
  • 1
    @MohitJain Practically speaking, yes. But the core point is that _there isn't a value_. It cannot be legally observed, so it does not exist. Period! This distinction is important because the compiler can do whatever it likes with those bytes, or with accesses to those bytes, while the object is in this state. And don't think it won't! Compilation is _complicated_. – Lightness Races in Orbit Feb 08 '19 at 10:55