Reputation: 11
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
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
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
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
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
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