So - here's the code
@echo off
setlocal
for %%a in (a A j J z Z) do for %%c in (d D) do if "%%c" geq "%%a" (echo "%%c" geq "%%a") else (echo "%%c" lss "%%a")
for %%a in (Blue blue BLUE Red red RED) do for %%c in (Pink pink PINK) do if "%%c" geq "%%a" (echo "%%c" geq "%%a") else (echo "%%c" lss "%%a")
Here's the result:
Microsoft Windows [Version 10.0.19042.804]
(c) 2020 Microsoft Corporation. All rights reserved.
"d" geq "a"
"D" geq "a"
"d" geq "A"
"D" geq "A"
"d" lss "j"
"D" lss "j"
"d" lss "J"
"D" lss "J"
"d" lss "z"
"D" lss "z"
"d" lss "Z"
"D" lss "Z"
"Pink" geq "Blue"
"pink" geq "Blue"
"PINK" geq "Blue"
"Pink" geq "blue"
"pink" geq "blue"
"PINK" geq "blue"
"Pink" geq "BLUE"
"pink" geq "BLUE"
"PINK" geq "BLUE"
"Pink" lss "Red"
"pink" lss "Red"
"PINK" lss "Red"
"Pink" lss "red"
"pink" lss "red"
"PINK" lss "red"
"Pink" lss "RED"
"pink" lss "RED"
"PINK" lss "RED"
(I just cut/paste/censored the screen to show the Windows version)
So - I'm about to go to do my grocery shopping (since its ~midnight) which will allow me to clear my head.
Am I seeing things? Doesn't batch do an ASCII comparison any more? I recall it used to.
AFAICS, if
has suddenly decided to automatically do a case-insensitive comparison. That'll break many a SO solution.
So - bulk responses. I'm still trying to process it all.
The base problem:
I have a label printer which has 5 inbuilt dot-matrix fonts and allows a multiplier to be assigned to both the X and Y dimension. Obviously, applying 1
for the X
multiplier and 6
for Y
produces ugly tall-and-thin characters. Reversing these produces ugly squat characters. Also, not all multipliers (1-9) are available in each direction.
I therefore have a table of "acceptable" X-Y multiplier-pairs which do not produce obviously-distorted characters. Since I'm dealing with monospaced fonts, each font & multiplier-pair yields a coverage per character, which I want to maximise. Applying each possible combination to resolve the maximum coverage is a simple process, allowing the selection of the font and multiplier for each element of the label.
The fly in the ointment is that one font is upper-case only, so I wanted to apply an exclusion for that font if the element contains a lower-case letter.
The code I used for that exclusion was to apply an if
test to each character %%c
if "%%c" geq "a" if "%%c" leq "z" set "islower=Y"
BUT this doesn't work as advertised. It will set islower
regardless of case. So the caps-only font was always excluded where the text contained alphas and therefore I never observed its being used. Oops.
Hence this question.
I've been doing many experiments as well as catching up on beauty-sleep (which I need) for the past few days, frankly dreading the volume of responses and comments.
Conclusions:
/i
is redacted from the if
if it's the first token.not
is redacted from the if
if it's then the first token.
if string1==string2
if string1
is resolved to not
We're then left with string1 operator string2
and a complex relationship between the operator used and the precise format of the strings.
==
is the simplest. There is no requirement for ==
to be preceded or succeeded by separators. The strings are compared alphabetically, hence you need the /i
switch to perform a case-insensitive comparison.
equ
and its family is where things get more complicated. Each must be preceded and succeeded by separators. The characteristics of the comparison made depends on the structure of the operands.
IF 066 equ 54
evaluates as TRUE because 066-octal equals 54 decimal. ==
predictably evaluates this as FALSEIF "102" gtr "94"
evaluates as FALSE because 1
is not greater than 9
gtr geq lss leq
operators on strings, operation becomes truly bizarre. CAT gtr cat
(quoted or no) evaluates as TRUE, as do dog gtr cat
and "dog" gtr "cat"
, regardless of case of either operand.Sorry - It's really all too complicated for me. I'm off for a rest.
Unfortunately, this problem really doesn't seem to fit SO's Q&A format.
As already described via comments, Strings are compared on a character by character basis, with the comparison returning it's value after the first non-matching character or the last character in the shortest string is encountered.
The value of each character is converted into a non-locale specific binary value as an unsigned char. From IBM's knowledge Centre:
The relation between the strings is determined by subtracting: string1[i] - string2[i], as i increases from 0 to strlen of the smaller string. The sign of a nonzero return value is determined by the sign of the difference between the values of the first pair of bytes (both interpreted as type unsigned char)
References:
docs.microsoft
IBM knowledge Centre
C++
A simple set of tests that demonstrates the returns that should be expected for the manner in which strcmp
assesses strings:
IF "Pink" equ "pink" (Echo true) else Echo false
false
IF "Pink" LSS "pink" (Echo true) else Echo false
false
IF "Pink" GTR "pink" (Echo true) else Echo false
true
IF "Pink" GTR "pinky" (Echo true) else Echo false
false
IF "Pink" lss "pinky" (Echo true) else Echo false
true
IF "Pink" GTR "Pinky" (Echo true) else Echo false
false
IF "Pink" GTR "pinky" (Echo true) else Echo false
false
The confusion arises due to the assesment disregarding characters beyond the first non matching character:
IF "Pink" lss "aaaaa" (Echo true) else Echo false
false
IF "Pink" GTR "Z" (Echo true) else Echo false
false
false is returned as soon as nonmatching character is encountered, rendering string length irrelevent in the comparison. In the first of the above two examples, false is returned by strcmp
as soon as P
is evaluated as being GTR than a
. The result would be the same if the comparison was: IF "Pink" lss "a" (Echo true) else Echo false
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With