This is explained by AND simply *NOT* being a logical operator in QB64; it's a binary operation.
Try these simple commands:
PRINT 1 AND 3
PRINT 1 AND 2
PRINT 2 AND 3
The results are:
1
0
2
And how does this relate to your coding example, you ask?
If k$ = "2", and x$ = "123456789", then INSTR$(x$,k$) is going to equal 2 -- it's in the second position of the search string...
Now, since k$ = "2", the LEN(k$) = 1...
And your IF condition test is:
IF LEN(k$) AND INSTR(x$, k$) THEN Which processes as:
IF 1 AND 2 THEN...And, as we saw above, 1 AND 2 are 0 -- which is what QB64 considers to be a FALSE logical value.
You're using BINARY OPERATIONS and expecting LOGIC-BASED RESULTS -- and as you noticed in your code, that's *NOT* going to work properly for you.
The solution is, as you have already noticed, to transform that AND so that you're comparing logic values (TRUE/FALSE) instead of binary numbers.
INSTR(x$, k$) <> 0 can ONLY give you logic values -- 0 for False, -1 for True.
LEN(k$) <> 0 can ONLY give you logic values -- 0 for False, -1 for True.
You can swap out *EITHER* of those binary numbers to make them logical values, and the program will them work as you intend -- the glitch isn't just something in INSTR()...
For example:
PRINT "The first routine uses AND INSTR(x$, k$) THEN. You'll see 'false' zero, for 2, 4, 6, and 8." PRINT "The second routine starts after 9 is processed. It uses 'INSTR(x$, k$) <> 0 THEN' All numbers will be processed." x$
= "123456789":
LOCATE , , 1, 7, 7 PRINT k$:
PRINT "Checkpoint OK: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) =";
LEN(k$
) AND INSTR(x$
, k$
): disp%
= 0 disp% = 0
PRINT k$:
PRINT "Can't Process: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) =";
LEN(k$
) AND INSTR(x$
, k$
): disp%
= 0
PRINT:
PRINT "DEMO 2 with AND LEN(k$) <> 0 AND INSTR(x$,k$) THEN": i
= 0:
PRINT PRINT k$:
PRINT "Checkpoint OK: ";
"LEN(k$) <> 0 =";
LEN(k$
) <> 0;
"INSTR(x$, k$) =";
INSTR(x$
, k$
);
"LEN(k$) AND INSTR(x$, k$) <> 0 =";
LEN(k$
) <> 0 AND INSTR(x$
, k$
): disp%
= 0 disp% = 0
PRINT k$:
PRINT "Can't Process: ";
"LEN(k$) =";
LEN(k$
);
"INSTR(x$, k$) <> 0 =";
INSTR(x$
, k$
) <> 0;
"LEN(k$) AND INSTR(x$, k$) <> 0 =";
LEN(k$
) AND INSTR(x$
, k$
) <> 0: disp%
= 0
As another, even simpler, demo of this process in action, take a close look at the code below:
The LEN(x$) is 1. The VAL(x$) is 2.
1 AND 2 is 0... The first comparison is false.
1 <> 0 AND 2 is 2... (It becomes -1 AND 2, which then becomes 2)... The second comparison is true.
1 AND 2 <> 0 is 1... (It become 1 AND -1, which then becomes 1)... The third comparison is true.
This isn't a glitch at all with INSTR. It's simply how AND behaves when used as a binary operator.
If you want to avoid these type of issues, be certain to ONLY use AND when you're comparing TRUE/FALSE type results.
Either that, or else write yourself a LOGIC_AND and use it for the comparisons: