Search code examples
cif-statementnegationlogical-orlogical-and

Conditional statement `if ( ( i != '7' ) && ( j != '8' ) && ( k != '9' ) )` yields erratic results


#include <unistd.h>
void triplet(void);

int main(void)
{
     triplet();
}

void triplet(void)
{
    char i, j, k;
    i = '0';
    j = '1';
    k = '2';
    while (i < j)
    {
        i + 1;
        k = j + 1;
        while (j < k)
        {
            k = j + 1;
            while (k <= '9')
            {
                write(1, &i, 1);
                write(1, &j, 1);
                write(1, &k, 1);
                if ( ( i != '7' ) && ( j != '8' ) && ( k != '9' ) )
                {
                    write(1, ", ", 2);
                }
                k++;
            }
            j++;
        }
        i++;
    }
}

The goal of the if statement is to control when to print the comma-space separator (", ") between the digit combinations. I want to print the separator after every combination except the last one ("789").

The following conditional statement does not work as intended:

if ( ( i != '7' ) && ( j != '8' ) && ( k != '9' ) )

This one does:

if ( !( i == '7' && j == '8' && k == '9' ) )

What is wrong with the first conditional?


Solution

  • The following could be read as "all three match":

    i == '7' && j == '8' && k == '9'
    

    You are negating that.

    !( i == '7' && j == '8' && k == '9' )
    

    The negation of "all three match" is "at least one doesn't match".

    i != '7' || j != '8' || k != '9'
    

    This is quite different than "none match".

    i != '7' && j != '8' && k != '9'
    

    In logic terms, we can derive i != '7' && j != '8' && k != '9' from i == '7' && j == '8' && k == '9' using De Morgan's laws.

    • !( p && q ) = !p || !q
    • !( p || q ) = !p && !q

    Vlad from Moscow's answer shows the steps.