user224234
user224234

Reputation: 11

Weird behavior with the logical and operator in a while loop

This will be the first question I post here, please advise me if anything is wrong.

So I get this piece of C code:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(int argc, char const* argv[]) {
    char array[3][50] = {
        "theoretical computer science",
        "programming puzzles and code golf",
        "ebooks"
    };
    int randIdx = 0;
    srand(time(NULL));

    int i;
    for (i=0; i<10; i++) {
        // discard everything longer than 27
        while((randIdx = rand() % 3) && (strlen(array[randIdx]) >= 27));

        printf("outside while: randIdx = [%d]\tstrlen = [%ld]\n",
                randIdx, strlen(array[randIdx]));
    }

}

Since the order of the logical and operator is left to right, I was hoping that the empty while loop will be able to discard the first and second array member. However, the output of the program (looped 10 times) looks like this:

outside while: randIdx = [2]    strlen = [6]
outside while: randIdx = [0]    strlen = [28]
outside while: randIdx = [0]    strlen = [28]
outside while: randIdx = [0]    strlen = [28]
outside while: randIdx = [2]    strlen = [6]
outside while: randIdx = [2]    strlen = [6]
outside while: randIdx = [2]    strlen = [6]
outside while: randIdx = [2]    strlen = [6]
outside while: randIdx = [0]    strlen = [28]
outside while: randIdx = [0]    strlen = [28]

Any idea why randIdx = [0] strlen = [28] can escape the while loop?

Upvotes: 0

Views: 175

Answers (5)

molbdnilo
molbdnilo

Reputation: 66459

I think this is one of those cases where you actually want to use the comma operator:

while (randIdx = rand() % 3 , strlen(array[randIdx]) >= 27))
    ;

in order to both perform the assignment and ignore its result.

I would make a note that it's meant to be like that, so nobody tries to "correct" it in the future.

It's also a good idea to make intentionally empty loops look intentional, either with the semicolon on its own line, or by being even more explicit:

while (randIdx = rand() % 3 , strlen(array[randIdx]) >= 27))
{
    /* Empty loop */
}

Upvotes: 1

Kalu
Kalu

Reputation: 290

while((randIdx = rand() % 3) && (strlen(array[randIdx]) >= 27));

In this case of randIdx = [0] strlen = [28] if you check the condition inside the while loop then randIDX is equal to 0. Which means while(0 && 1) ----> Here 1 is returned for strlen(array[randIdx])=28 which is greater than 27.

Hence I believe this answers the question

why randIdx = [0] strlen = [28] can escape the while loop?

Upvotes: 0

Jonny Henly
Jonny Henly

Reputation: 4233

You have a semicolon(;) directly following your while loop. Making your while loop do nothing other than change the value of randIdx. You should change your code to:

for (i=0; i<10; i++) {

    // discard everything longer than 27
    while((randIdx = rand() % 3) && (strlen(array[randIdx]) >= 27)) {
        printf("outside while: randIdx = [%d]\tstrlen = [%ld]\n",
            randIdx, strlen(array[randIdx]));
    }

}

Upvotes: 0

BlackMamba
BlackMamba

Reputation: 10252

   for (i=0; i<10; i++) 
   {
        // discard everything longer than 27
        while((randIdx = rand() % 3) && (strlen(array[randIdx]) < 27))
        {
            printf("outside while: randIdx = [%d]\tstrlen = [%ld]\n", randIdx, strlen(array[randIdx]));
        }
    }

Maybe you can modify your code.

Upvotes: 0

Amit
Amit

Reputation: 46351

That's because the while statement loops as long as the condition is truthy. In the cases of randIdx == 0 & strlen(array[randIdx]) < 27, the expression is false (0), and the while loop is stopped.

So, if you wanted to only let randIdx values such that randIdx != 0 and that strlen(array[randIdx]) < 28, you could reverse the logic and use logical OR instead:

while(!(randIdx = rand() % 3) || (strlen(array[randIdx]) >= 27));

This will continue generating new random values as long as randIdx is 0 OR the length is >= 27.

Effectively, only randIdx = [2] strlen = [6] will go through.

Upvotes: 0

Related Questions