Zeichen n-mal wiederholen

Zeichen n-mal wiederholen

Ich wollte einen neuen Befehl erstellen, der es mir ermöglicht, repeatalle charactersgewü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 multidoist 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 multidofü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.

Bildbeschreibung hier eingeben

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
}

\romannumerallöst den ersten aus \number, der den zweiten erweitert; wenn wir beispielsweise 4 haben, wie #1wir nacheinander erhalten (wobei ein Leerzeichen bezeichnet

\romannumeral\number\number4•000
\romannumeral\number4000
\romannumeral4000
mmmm

Wenn wir stattdessen haben \count27und den Wert 4 #1haben \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 \numbersind 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 \numberTokens 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#1000die 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}

Bildbeschreibung hier eingeben

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 \loopusw. 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}

Bildbeschreibung hier eingeben

Antwort3

In ConTeXt können Sie Folgendes verwenden, \dorecurseum 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 \fornumfolgende 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 \fornumMakro ist vollständig erweiterbar, Sie können verschachtelte Schleifen ohne öffnende oder schließende Gruppe verwenden.

verwandte Informationen