![Warum verursacht die Verschachtelung einiger XString-Befehle Fehler?](https://rvso.com/image/405343/Warum%20verursacht%20die%20Verschachtelung%20einiger%20XString-Befehle%20Fehler%3F.png)
Warum kombiniert man die Beherrschung derxstring-Paketverursacht Fehler? zB wenn ich folgendes MWE kompiliere:
\documentclass{article}
\usepackage{xstring}
\begin{document}
\section{A}
\StrCompare{\StrChar{bbbb}{4}}{\StrChar{aaaa}{3}}% are 4th character of first argument with 3th character of second argument differ ---> result 1 (yes and in first position)
\end{document}
es gibt den Fehler zurück:
! Undefined control sequence.
\xs_StrChar__ ...ef \xs_arg_ii {#2}\edef \xs_call
{\noexpand \xs_testopt {\n...
l.5 ...mpare{\StrChar{bbbb}{4}}{\StrChar{aaaa}{3}}
% are 4th character of fir...
?
Antwort1
Dies ist ein recht häufiges Problem bei der Verwendung von , xstring
da (die meisten) seiner Befehle nicht in reinen Erweiterungskontexten funktionieren (innerhalb eines \edef
oder \expanded
oder \write
oder ...), sodass jeder Befehl vollständig ausgeführt werden muss, bevor der nächste gestartet wird. Kurz gesagt, sie können nicht verschachtelt werden. Ein einfacheres Beispiel, das dasselbe Problem zeigen würde, wäre die Definition von:
\newcommand\ifequal[2]{%
\def\tempa{#1}%
\def\tempb{#2}
\ifx\tempa\tempb
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
und verwenden Sie dann den Befehl innerhalb von \edef
:
\edef\test{\ifequal{abc}{abc}{true}{false}}
was den Fehler auslösen würde:
! Undefined control sequence.
\ifequal #1#2->\def \tempa
{#1}\def \tempb {#2} \ifx \tempa \tempb \expandaf...
l.13 \edef\test{\ifequal{abc}{abc}
{true}{false}}
?
Wenn Sie es jedoch außerhalb verwenden würden, \edef
würde es funktionieren.
Um die Ergebnisse eines xstring
Befehls in einem anderen verwenden zu können, verfügen die meisten Befehle über ein abschließendes optionales Argument, bei dem es sich um ein Makro zum Speichern des Verarbeitungsergebnisses handelt. Anschließend müssen Sie jeden Schritt separat ausführen und bei jedem Schritt das Ergebnis erfassen:
\documentclass{article}
\usepackage{xstring}
\begin{document}
\section{A}
\StrChar{bbbb}{4}[\tempA]
\StrChar{aaaa}{3}[\tempB]
\StrCompare{\tempA}{\tempB}
\end{document}
Hoffentlich bin ich bald mit meiner erweiterbaren Version fertig xstring
;-)
Antwort2
\StrChar
Sie können im Argument von nicht verwenden \StrCompare
.
Hier sind zwei Implementierungen: eine mit xparse
und expl3
, eine mit xstring
. Beachten Sie, dass die erste vollständig erweiterbar ist, die zweite nicht.
\documentclass{article}
\usepackage{xparse}
\usepackage{xstring} % for comparison
\ExplSyntaxOn
\NewExpandableDocumentCommand{\comparestringitems}{mmmmmm}
{
% #1 = first string
% #2 = item number
% #3 = second string
% #4 = item number
% #5 = true text
% #6 = false text
\str_if_eq:eeTF { \str_item:nn { #1 } { #2 } } { \str_item:nn { #3 } { #4 } } { #5 } { #6 }
}
\prg_generate_conditional_variant:Nnn \str_if_eq:nn { ee } { TF,T,F,p }
\ExplSyntaxOff
\newcommand{\comparestringitemsxstring}[6]{%
\StrChar{#1}{#2}[\compareA]%
\StrChar{#3}{#4}[\compareB]%
\StrCompare{\compareA}{\compareB}[\compareC]
\ifnum\compareC=0 #5\else#6\fi
}
\begin{document}
\comparestringitems{aaaa}{4}{bbbb}{3}{true}{false}
\comparestringitems{aaaa}{4}{bbab}{3}{true}{false}
\comparestringitemsxstring{aaaa}{4}{bbbb}{3}{true}{false}
\comparestringitemsxstring{aaaa}{4}{bbab}{3}{true}{false}
\edef\test{\comparestringitems{aaaa}{4}{bbab}{3}{true}{false}}
\texttt{\meaning\test}
\end{document}
Mit einer einfachen Änderung können Sie Makros auch an Folgendes übergeben \comparestringitems
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\comparestringitems}{mmmmmm}
{
% #1 = first string
% #2 = item number
% #3 = second string
% #4 = item number
% #5 = true text
% #6 = false text
\str_if_eq:eeTF { \str_item:en { #1 } { #2 } } { \str_item:en { #3 } { #4 } } { #5 } { #6 }
}
\prg_generate_conditional_variant:Nnn \str_if_eq:nn { ee } { TF,T,F,p }
\cs_generate_variant:Nn \str_item:nn { e }
\ExplSyntaxOff
\newcommand{\strA}{aaaa}
\newcommand{\strB}{bbbb}
\newcommand{\strC}{bbab}
\begin{document}
\comparestringitems{\strA}{4}{\strB}{3}{true}{false}
\comparestringitems{\strA}{4}{\strC}{3}{true}{false}
\edef\test{\comparestringitems{\strA}{4}{\strC}{3}{true}{false}}
\texttt{\meaning\test}
\end{document}