Es gibt \if… Befehle in allen möglichen Variationen: \ifx, \ifnum, \ifdim, \@ifundefined, \@ifpackageloaded, \ifodd, etc., und zusätzlich gibt es noch die persönlichen mit \newif\if… kreierten Befehle.

Doch was genau macht das ganz normale \if, und wann wird dieses verwendet?

gefragt 15 Aug '13, 16:36

Epllus's gravatar image

Epllus
620269
Akzeptiert-Rate: 46%

bearbeitet 15 Aug '13, 16:47

cgnieder's gravatar image

cgnieder
22.1k253463

\if<token1><token2> testet beide Token in Bezug auf den Character-Code. Die Token werden dabei expandiert, wenn es sich um Makros handelt. Ich verwende es v.a. um auf leere Argumente zu testen: \if\relax\detokenize{#1}\relax: wenn #1 leer ist, wird \relax mit \relax verglichen, die Abfrage ist wahr. Enthält #1 irgendwas (selbst \relax), dann ist die Abfrage falsch, weil \detokenize eine Reihe von Charaktern mit Kategorie-Code 12 zurücklässt (was aus \relax sechs Charaktere machen würde).

(15 Aug '13, 16:52) cgnieder

@Clemens: Das Leerzeichen (Zeichencode 32) ist bei \detokenize übrigens ein Space-Tokens, bekommt also als Ausnahme Kategorie-Code 10, was natürlich für Dein Beispiel keine Rolle spielt, weil ein Leerzeichen ja nicht nichts ist, auch wenn manche Anwender das anders sehen.

(15 Aug '13, 17:15) saputello

@saputello Ich weiß, ich hatte nur das Gefühl, dass mein Kommentar schon zu lang würde, deshalb hab ich das einfach unterschlagen ;)

(15 Aug '13, 17:20) cgnieder

@Clemens Gut zu wissen, dass man auch mit \if testen kann, ob ein Argument leer ist. Bisher kannte ich nur \ifx\\#1\\.

(16 Aug '13, 09:23) Epllus

Nach \if expandiert TeX so lange, bis zwei nicht expandierbare Tokens gefunden werden. Ist das nicht expandierbare Token eine Kontrollsequenz, also beispielsweise ein TeX Primitiv, so wird diesem der Code 256 zugeordnet. Ansonsten wird der Zeichencode des Tokens (kann bei TeX zwischen 0 und 255 liegen, da TeX nur 8-Bit-Zeichen verarbeitet) genommen. Diese beiden Codes werden dann verglichen.

Beispiele:

  • \if\noexpand\end\relax ja\else nein\fi

Ergibt: ja, weil \noexpand\end zu einem nicht expandierbaren \end expandiert und diesem als Kontrollsequenz dann 256 zugeordnet wird und \relax nicht expandierbar ist und direkt 256 zugeordnet bekommt.

  • \ifx abja\else nein\fi

Ergibt: nein, weil a und b nicht expandierbare Tokens sind und der Zeichencode von a und b nicht gleich ist.

  • \def\a{a}\if a\a ja\else nein\fi

Ergibt: ja, weil das erste a nicht expandierbar ist, \a ebenfalls zu a expandiert und dann die beiden a den gleichen Zeichencode haben.

  • \def\a{a}\if \a aja\else nein\fi

Ergibt: ja, weil \a zu a expandiert und dann die beiden a den gleichen Zeichencode haben.

  • \def\a{ab}\def\b{ab}\if \a\b ja\else nein\fi

Ergibt: nein, weil \a zu ab expandiert, das zwei nicht expandierbare Tokens sind, a und b unterschiedlichen Zeichencode haben und damit der \else-Teil ausgeführt wird.

  • \def\a{aa}\def\b{bb}\if \a\b ja\else nein\fi

Ergibt: bbja, weil \a zu aa expandiert, das zwei nicht expandierbare Tokens sind, a und a denselben Zeichencode haben und dann \b ja vor dem \else übrig bleiben.

  • \def\a{aa}\def\b{bb}\ifx \a\b ja\else nein\fi

Ergibt: nein, weil \ifx anders als \if funktioniert.

Als weiterführende Literatur empfehle ich hierzu »TeX by Topic« (Kapitel 13) oder »The TeXbook«.

Im LaTeX-Kern wird \if beispielsweise verwendet, um zeichenweise die Ein-Zeichen-Optionen für die Gleitumgebungsoptionen mit einzelnen Buchstaben zu vergleichen oder die einzelnen Zeichen einer kleinen, römischen Zahl in Großbuchstaben für eine große, römische Zahl zu wandeln oder die Platzierungs-Optionen von \makebox, \parbox, minipage oder tabular zeichenweise mit entsprechenden Buchstaben zu vergleichen.

\@ifundefined und \@ifpackageloaded sind übrigens nicht mit \if, \ifx oder \ifodd zu vergleichen, da sie eine ganz andere Syntax haben. Die \if… … \else … \fi-Syntax ist für diese nicht verwendbar, da TeX bei dieser Syntax eine Abkürzung nimmt, sobald es weiß, ob die Bedingung zutrifft oder nicht. Es wird nämlich je nachdem der true-Teil oder der else-Teil einfach übersprungen, wobei nicht mehr expandiert wird, sondern lediglich Ebenen von \iftrue … \else … \fi und \iffalse … \else … \fi mit berücksichtigt werden. Deshalb darf man auf keinen Fall eine Definition wie:

\def\@ifundefined#1{\expandafter\ifx\csname #1\endcsname\relax}

verwenden. Diese würde beispielsweise in

\iffalse
  \def\test{ok}%
  \@ifundefined\test ok\fi
\else
  not ok
\fi

Zu einem Extra \else-Fehler führen, weil \@ifundefined\test nicht expandiert würde und damit das erste \fi bereits das Ende von \iffalse wäre. Aus genau diesem Grund, ist \@ifundefined im LaTeX-Kern stattdessen eine Anweisung mit drei Argumenten (wobei die letzten beiden von \@firstoftwo oder \@secondoftwo gelesen werden). Ich erwähne das, weil Anfänger gerne solche Fehler machen.

Permanenter link

beantwortet 15 Aug '13, 16:52

saputello's gravatar image

saputello
11.1k174365
Akzeptiert-Rate: 51%

bearbeitet 15 Aug '13, 17:21

Perfekt! Danke :)

(16 Aug '13, 09:24) Epllus
Deine Antwort
Vorschau umschalten

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs fügen Sie einfach zwei Leerzeichen an die Stelle an der die neue Linie sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Frage-Themen:

×22
×14

gestellte Frage: 15 Aug '13, 16:36

Frage wurde gesehen: 14,336 Mal

zuletzt geändert: 16 Aug '13, 09:24