Repeat characters n times
No packages:
\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}
Why the group? It allows nested calls.
If you just want to repeat a character:
\documentclass{article}
\newcommand\myrepeat[2]{%
\begingroup
\lccode`m=`#2\relax
\lowercase\expandafter{\romannumeral#1000}%
\endgroup
}
\begin{document}
\myrepeat{4}{x}
\end{document}
As Ulrich Diez rightly comments, this code would not allow a counter register as number of repetitions; in order to support this, a slightly more complicated version is
\newcommand\myrepeat[2]{%
\begingroup
\lccode`m=`#2\relax
\lowercase\expandafter{\romannumeral\number\number#1 000}%
\endgroup
}
\romannumeral
triggers the first \number
which expands the second one; if we have, say, 4 as #1
we get successively (where •
denotes a space token
\romannumeral\number\number4•000
\romannumeral\number4000
\romannumeral4000
mmmm
If, instead, we have \count27
as #1
and \count27
holds the value 4, we get
\romannumeral\number\number\count27•000
\romannumeral\number4000
\romannumeral4000
mmmm
If we have \foo
(a named counter register), again holding the value 4, we have
\romannumeral\number\number\foo•000
\romannumeral\number4•000
\romannumeral4000
mmmm
Therefore two instances of \number
are necessary, in order to cover the third case. This exploits the fact that a space ends the search for an “explicit” number and is then ignored (the space token is not ignored in the third case, after the expansion of the second \number
token).
If you also want a text to put in between the repetitions, the first approach is very simple: just start the loop at 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
(don't call this with zero repetitions).
A different solution with a recursion and the old idea of \romannumeral#1000
that produces a long string of m's that we can consume one at a time.
\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}
The recursion consumes two tokens at a time, in order to distinguish whether it has only one more step to do. The second token is put back when the recursion restarts.
However, this is just for study. In a real world application I'd do
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\myrepeat}{O{}mm}
{
\int_compare:nT { #2 > 0 }
{
#3 \prg_replicate:nn { #2 - 1 } { #1#3 }
}
}
\ExplSyntaxOff
to be called like \myrepeat[-]{4}{x}
to get
x-x-x-x
and \myrepeat{3}{A}
to get
AAA
Here's a version without any package, just using plain \loop
and \repeat
etc.
\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}
FWIW, in ConTeXt you can use \dorecurse
to repeat something. For example:
\dorecurse{10}{Hello world. }
will print Hello world.
10 times. The current iteration number is stored in the macro \recurselevel
.