
Ich wollte einen neuen Befehl erstellen, der es mir ermöglicht, repeat
alle characters
gewünschten Aktionen auszuführen n times
. Nach einigem Suchen und Ausprobieren kam ich auf Folgendes:
\usepackage{multido}
\newcommand{\myrepeat}[2]{%
\newcount\iterations%
\iterations #1%
\advance\iterations -1
\multido{\iN=0+1}{\iterations}{#2\ }#2%
}
Im resultierenden PDF gab es nach dem Befehl einige seltsame Leerzeichen, also habe ich die Kommentarsymbole hinzugefügt %
und dann sind sie verschwunden.
Meine Frage ist: Gibt es hierfür eine bessere Möglichkeit, die ebenso leicht zu verstehen ist wie diese und vorzugsweise nicht zu viele Abhängigkeiten einführt?
Eines ohne multido
ist auch in Ordnung, wenn es nicht zu kompliziert ist oder wenn Sie es erklären können, sodass es nicht mehr kompliziert ist. Ich denke, die Verwendung multido
für so etwas ist in Ordnung, da der Name bedeutet, etwas mehrmals zu tun, aber ich bin nicht sicher, ob ich den einfachsten und saubersten Weg gewählt habe, es zu tun.
Beachten Sie, dass meine Lösung ein Leerzeichen weniger hinzufügt als Elemente zum PDF hinzufügt. Die Art und Weise, eins abzuziehen, erscheint mir verdächtig ausführlich.
Bei mir funktionieren derzeit zwei Versionen:
Der von @egreg geänderte:
\makeatletter
\newcount\my@repeat@count% initialize a new counter for the loop
\newcommand{\myrepeat}[3]{% new command with 2 arguments
\begingroup% ???
\my@repeat@count=1% initialize at 1, so that there are argument - 1 iterations and the last iterations doesn't have a separator following it
\@whilenum\my@repeat@count<#1\do{#2#3\advance\my@repeat@count1}#2% as long as the iteration count is smaller than the argument, advance, meaning that the counter will be increased by 1
\endgroup% ???
}
\makeatother
\newcommand{\mediumgap}{%
\myrepeat{5}{.....}{\ }
}
Das von @christian geänderte:
\newcount\myloopcounter
\newcommand{\repeatit}[3][10]{%
\myloopcounter1% initialize the loop counter
\loop\ifnum\myloopcounter < #1
#2#3%
\advance\myloopcounter by 1%
\repeat% start again
#2%
}
\newcommand{\longgap}{%
\repeatit[5]{.....}{\ }
}
Ich weiß nicht, ob das eine gegenüber dem anderen Vorteile hat. Vielleicht gibt es auch eine bessere Möglichkeit, das letzte Leerzeichen oder Trennzeichen zu entfernen, anstatt eine Iteration weniger durchzuführen und nur die zu wiederholenden Zeichen ohne Trennzeichen zu schreiben. Ich habe das Trennzeichen eingeführt, weil ich dachte, es könnte nützlich sein und es ist nur ein dritter Parameter.
Antwort1
Keine Pakete:
\documentclass{article}
\makeatletter
\newcount\my@repeat@count
\newcommand{\myrepeat}[2]{%
\begingroup
\my@repeat@count=\z@
\@whilenum\my@repeat@count<#1\do{#2\advance\my@repeat@count\@ne}%
\endgroup
}
\makeatother
\begin{document}
\myrepeat{4}{x}
\myrepeat{4}{\myrepeat{2}{x}}
\end{document}
Warum die Gruppe? Sie ermöglicht verschachtelte Aufrufe.
Wenn Sie nur ein Zeichen wiederholen möchten:
\documentclass{article}
\newcommand\myrepeat[2]{%
\begingroup
\lccode`m=`#2\relax
\lowercase\expandafter{\romannumeral#1000}%
\endgroup
}
\begin{document}
\myrepeat{4}{x}
\end{document}
Wie Ulrich Diez richtig bemerkt, würde dieser Code kein Zählerregister als Anzahl der Wiederholungen zulassen; um dies zu unterstützen, gibt es eine etwas kompliziertere Version
\newcommand\myrepeat[2]{%
\begingroup
\lccode`m=`#2\relax
\lowercase\expandafter{\romannumeral\number\number#1 000}%
\endgroup
}
\romannumeral
löst den ersten aus \number
, der den zweiten erweitert; wenn wir beispielsweise 4 haben, wie #1
wir nacheinander erhalten (wobei •
ein Leerzeichen bezeichnet
\romannumeral\number\number4•000
\romannumeral\number4000
\romannumeral4000
mmmm
Wenn wir stattdessen haben \count27
und den Wert 4 #1
haben \count27
, erhalten wir
\romannumeral\number\number\count27•000
\romannumeral\number4000
\romannumeral4000
mmmm
Wenn wir \foo
(ein benanntes Zählerregister) haben, das wieder den Wert 4 enthält, haben wir
\romannumeral\number\number\foo•000
\romannumeral\number4•000
\romannumeral4000
mmmm
daherzweiInstanzen von \number
sind notwendig, um den dritten Fall abzudecken. Dabei wird die Tatsache ausgenutzt, dass ein Leerzeichen die Suche nach einer „expliziten“ Zahl beendet und dann ignoriert wird (das Leerzeichen-Token wird im dritten Fall nach der Erweiterung des zweiten \number
Tokens nicht ignoriert).
Wenn Sie zwischen den Wiederholungen zusätzlich einen Text einfügen möchten, ist die erste Vorgehensweise ganz einfach: Starten Sie die Schleife einfach bei 1.
\makeatletter
\newcount\my@repeat@count
\newcommand{\myrepeat}[3]{%
% #1 = number of repetition
% #2 = text to repeat
% #3 = text in between
\begingroup
#2
\my@repeat@count=\@ne
\@whilenum\my@repeat@count<#1\do{#2#3\advance\my@repeat@count\@ne}%
\endgroup
}
\makeatother
(rufen Sie dies nicht mit null Wiederholungen auf).
Eine andere Lösung mit Rekursion und der alten Idee, \romannumeral#1000
die eine lange Zeichenfolge von m erzeugt, die wir einzeln verwenden können.
\documentclass{article}
\makeatletter
\newcommand\myrepeat[3]{%
% #1 is the number of repetitions
% #2 is the code to repeat
% #3 is the code to put in the middle
\expandafter\myrepeat@aux\expandafter{\romannumeral\number\number#1 000}{#2}{#3}%
}
\newcommand{\myrepeat@aux}[3]{\myrepeat@auxi{#2}{#3}#1;;}
\def\myrepeat@auxi#1#2#3#4{%
\ifx#3;%
\expandafter\@gobble % recursion has ended
\else
\expandafter\@firstofone % still one m to swallow
\fi
{\myrepeat@auxii{#1}{#2}{#4}}%
}
\def\myrepeat@auxii#1#2#3{%
#1\ifx#3;\else#2\fi
\myrepeat@auxi{#1}{#2}#3% restart the recursion
}
\makeatletter
\begin{document}
\myrepeat{4}{x}{-}
\myrepeat{1}{x}{-}
X\myrepeat{0}{x}{-}X
\end{document}
Die Rekursion verbrauchtzweiToken auf einmal, um zu unterscheiden, ob nur noch ein Schritt zu tun ist. Das zweite Token wird zurückgesetzt, wenn die Rekursion neu gestartet wird.
Dies ist jedoch nur für Studienzwecke. In einer realen Anwendung würde ich Folgendes tun:
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\myrepeat}{O{}mm}
{
\int_compare:nT { #2 > 0 }
{
#3 \prg_replicate:nn { #2 - 1 } { #1#3 }
}
}
\ExplSyntaxOff
genannt werden wie \myrepeat[-]{4}{x}
bekommen
xxxx
und \myrepeat{3}{A}
zu bekommen
AAA
Antwort2
Hier ist eine Version ohne Paket, die nur Plain \loop
usw. verwendet \repeat
.
\documentclass{article}
\newcount\myloopcounter
\newcommand{\repeatit}[2][10]{%
\myloopcounter0% initialize the loop counter
\loop\ifnum\myloopcounter < #1 % Test if the loop counter is < #1
#2%
\advance\myloopcounter by 1 %
\repeat % start again
}
\begin{document}
\repeatit[5]{A}
\repeatit[20]{And now for something completely different\par}
\end{document}
Antwort3
In ConTeXt können Sie Folgendes verwenden, \dorecurse
um etwas zu wiederholen. Beispiel:
\dorecurse{10}{Hello world. }
wird 10 Mal gedruckt Hello world.
. Die aktuelle Iterationsnummer wird im Makro gespeichert \recurselevel
.
Antwort4
In OpTeX können Sie \fornum
folgende Makros verwenden:
\def\myrepeat#1#2{\fornum 1..#1\do {#2}}
\myrepeat{4}{x}
\myrepeat{4}{\myrepeat{2}{x}}
\message{\myrepeat{4}{\myrepeat{2}{x}}} % prints xxxxxxxx on the terminal.
\bye
Das \fornum
Makro ist vollständig erweiterbar, Sie können verschachtelte Schleifen ohne öffnende oder schließende Gruppe verwenden.