Abfrage nach "leerem String" mit unklarem Ergebnis

Redefinition von Makros, Definition eigener Befehle sowie neuer Umgebungen


Juetho
Forum-Anfänger
Forum-Anfänger
Beiträge: 14
Registriert: Do 28. Okt 2010, 15:59
Wohnort: Berlin

Abfrage nach "leerem String" mit unklarem Ergebnis

Beitrag von Juetho »

Hallo, in einem Makro möchte ich prüfen, ob ein String, der als Argument übergeben wird, leer ist oder nicht. Nach vielen Versuchen habe ich festgestellt, dass \ifstr immer richtig arbeitet, aber \ifx nur teilweise das erwartete Ergebnis liefert. Hier der Beispielcode:
\documentclass[paper=b5]{scrbook}

\begin{document}

\newcommand{\myif}[1]
{
\def\val{#1}
\newcommand{\cmd}{#1}

**** ifx **** \\
\#1 \ifx#1\empty leer \else voll \fi \\
val \ifx\val\empty leer \else voll \fi \\
cmd \ifx\cmd\empty leer \else voll \fi \\

**** ifstr **** \\
\#1 \ifstr{#1}{}{leer}{voll} \\
val \ifstr{\val}{}{leer}{voll} \\
cmd \ifstr{\cmd}{}{leer}{voll} \\
}

\myif{}

\end{document}
Das Ergebnis bei ifx:
**** ifx ****
#1 voll
val leer
cmd voll
Kann mir jemand kurz erklären (oder einen Link auf eine solche Erklärung geben), warum ifx bei #1 und newcommand das leere Argument als nicht-leer interpretiert? Danke! Jürgen

PS. Die Forumssuche nach "leere Zeichenkette" u.ä. hat mir keine erkennbaren Ergebnisse gebracht, oder ich habe die Hinweise übersehen.

phi
Moderator
Moderator
Beiträge: 420
Registriert: Fr 6. Feb 2009, 21:28

Beitrag von phi »

Hallo,
eine umfassende Erklärung wäre relativ schwierig. Falls du dich für die Details interessierst, kommst du um die Lektüre eines Buches, welches die TeX-Interna erklärt, nicht herum, beispielsweise TeX by Topic.
Bei der Expansion eines Makros („Befehl“ in LaTeX-Sprechweise) werden Parametertoken wie #1 durch die entsprechenden Argumente ersetzt, bevor irgendeine andere Verarbeitung stattfindet. D.h. \myif{} wird ersetzt durch
\def\val{} 
\newcommand{\cmd}{} 

**** ifx **** \\ 
\#1 \ifx\empty leer \else voll \fi \\ 
val \ifx\val\empty leer \else voll \fi \\ 
cmd \ifx\cmd\empty leer \else voll \fi \\ 

**** ifstr **** \\ 
\#1 \ifstr{}{}{leer}{voll} \\ 
val \ifstr{\val}{}{leer}{voll} \\ 
cmd \ifstr{\cmd}{}{leer}{voll} \\ 
\ifx überprüft nun, ob die beiden darauffolgenden Token die gleiche Bedeutung haben. Im ersten Fall vergleicht \ifx die Bedeutung des Makros \empty mit dem Buchstaben „l“ (denn das sind die beiden folgenden Token, das #1 ist durch die Makro-Ersetzung komplett verschwunden!), diese sind natürlich nicht gleich, und der Vergleich expandiert zum \else-Zweig.
Im zweiten Fall werden die beiden Makros \val und \empty verglichen. Da \empty als
\def\empty{}
definiert ist, sind diese Token gleich, und die Expansion ist „leer“.
Im dritten Fall werden die beiden Makros \cmd und \empty verglichen. Da der LaTeX-Befehl \newcommand das zu definierende Makro als \long definiert (d.h. es akzeptiert Argumente, die Absatzendetoken enthalten) und \ifx auch den \long-Status von Makros vergleicht, sind diese beiden Makros ebenfalls nicht gleich.

Wenn du in einem Makro überprüfen willst, ob ein übergebenes Argument leer ist, musst du erst definieren, was als „leer“ gilt. Vier häufig anzutreffende Definitionen sind:
  1. Ein Argument gilt als leer, wenn es keine Token enthält.
  2. Ein Argument gilt als leer, wenn es ausschließlich Leerzeichentoken enthält, beispielsweise „ “ (ein einzelnes explizites Leerzeichen).
  3. Ein Argument gilt als leer, wenn seine vollständige Expansion keine Token enthält, beispielsweise „\empty“.
  4. Ein Argument gilt als leer, wenn seine vollständige Expansion ausschließlich Leerzeichentoken enthält, beispielsweise „\space“.
(1) ist ein Spezialfall von (2), (3) und (4); (2) ist ein Spezialfall von (4); (3) ist ebenfalls ein Spezialfall von (4). Dein Vergleich \ifx\val\empty verwendet Bedingung (1); die Tests mit \ifstr verwenden Bedingung (3); \ifstrempty aus dem etoolbox-Paket verwendet Bedingung (1) (ist allerdings expandierbar), \ifblank verwendet Bedingung (2). D.h. \ifstr arbeitet nur dann „richtig“ (aus deiner Sicht), wenn du tatsächlich auf Bedingung (3) testen willst.

Juetho
Forum-Anfänger
Forum-Anfänger
Beiträge: 14
Registriert: Do 28. Okt 2010, 15:59
Wohnort: Berlin

Beitrag von Juetho »

Danke, diese Erklärung gefällt mir und genügt mir vollständig. Weiter in die Details will ich mich nicht einarbeiten, aber ich wollte verstehen, unter welchen Umständen welche Variante hilfreich ist. Jürgen

Antworten