I tried to compare two strings (alphabetically), but I found some problems using the \pdfstrcmp
command: 1- because it needs pdftex; 2- because it is case sensitive.
The first problem is not so relevant, because I can use another compiler.
However the second problem is complicated to me. In \pdfstrcmd
command all lowercase chars in comparison with an uppercase char has the same answer.
So I tried to use the comparison of chars using \ifnum\uccode#1\uccode#2 (...)
, but the reply was "! Improper alphabetic constant"
Is there anyone who knows a solution to this problem?
My code:
\documentclass{article}
\newcounter{auxCountGetCharAt}
\makeatletter
\def\funcGetCharAt#1#2\relax{\stepcounter{auxCountGetCharAt}\edef\@tempb{\the\value{auxCountGetCharAt}}\ifx\@tempa\@tempb#1\else{\ifx\relax#2\relax\else\funcGetCharAt#2\relax\fi}\fi}
\def\getCharAt#1#2{%
\edef\@tempa{#2}%
\setcounter{auxCountGetCharAt}{0}%
\funcGetCharAt#1\relax%
}
\newcommand\compareChars[2]{\ifnum\uccode`#1>\uccode`#2 1\else{\ifnum\uccode`#1=\uccode`#2 0\else -1\fi}\fi}
\newcommand\compareStrings[2]{%
\def\@tempc{\getCharAt{#1}{1}}%
\def\@tempd{\getCharAt{#2}{1}}%
\compareChars{\@tempc}{\@tempd}%
}
\begin{document}
\compareStrings{abcdefg}{bcdefg}
\compareStrings{Abcdefg}{bcdefg}
\compareStrings{Bbcdefg}{acdefg}
\compareStrings{bbcdefg}{acdefg}
\compareStrings{bcdefg}{bcdeag}
\end{document}
Best Answer
If the strings are made only of ASCII characters, you can normalize them to lowercase before comparing:
The
pdftexcmds
package defines\pdf@strcmp
to do the correct thing with pdfLaTeX, XeLaTeX and LuaLaTeX. In all cases the result isThe
\edef
allows also to pass macros to\compareStrings
, as long as their expansion consists of plain ASCII characters (there's no real restriction for XeLaTeX and LuaLaTeX, but UTF-8 characters in pdfLaTeX wouldn't work).If you need to execute something for the different cases, instead of producing –1, 0 or 1, you can add the usual test:
So with
\compareStringsDo{<str1>}{<str2>}{<before>}{<equal>}{<after>}
the<before>
code will be executed when<str1>
comes before<str2>
in the alphabetical order,<equal>
if they are the same and<after>
otherwise (after normalization to lowercase).An
expl3
version that has the big advantage of being fully expandable.The console output: