How to repeat text
Solution 1
Your \append
macro cannot work in the argument to tabular
, where macros can be used as long as they are fully expandable; this isn't, because it contains assignments.
Here's a quick version with LaTeX3 functions. Note that this won't work in the argument of tabular
if array
is loaded, because this package disables expanding the argument.
However, typing l*{2}{c}
as the argument seems not so complicated to need a macro.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\append}{mmm}
{
#1\prg_replicate:nn{#3}{#2}
}
\ExplSyntaxOff
\begin{document}
\noindent\append{c}{c}{0}
\noindent\append{cd}{c}{1}
\noindent\append{c}{c}{2}
\noindent\append{c}{c}{3}
\noindent\begin{tabular}{\append{l}{c}{2}}
1&2&3\\
\append{start}{&test}{1}\\
\append{start}{&test}{2}
\end{tabular}
\end{document}
Solution 2
There is really no need to reinvent the wheel. There are a number of looping packages out there that you can use to iterate over a sequence. I've used multido
below:
\documentclass{article}
\usepackage{multido}% http://ctan.org/pkg/multido
\makeatletter
\newcommand{\append}[3]{ % #1 = start of text, #2 = text to repeat, #3 = number of repetitions
\def\@looop{#1}% start of text
\ifnum#3>0\multido{\iA=1+1}{#3}{\g@addto@macro\@looop{#2}}\fi% text to repeat
\@looop}% Execute
\makeatother
\begin{document}
\noindent\append{c}{c}{0}
\noindent\append{c}{c}{1}
\noindent\append{c}{c}{2}
\noindent\append{c}{c}{3}
\noindent\begin{tabular}{*{3}{c}}
1 & 2 & 3 \\
\append{start}{&test}{1} \\
\append{start}{&test}{2}
\end{tabular}
\end{document}
The idea is to construct a macro \@looop
that contains the starting element, and repeated elements are added using \g@addto@macro
. Then, at the end of \append
, \@looop
is executed.
Note that tabular
column specifications already provide a type of duplication/repetition using a *{<num>}{<col spec>}
style, where the column specification <col spec>
is repeated <num>
times.
Solution 3
The spaces are due to an extra space that you have in the definition of \append
, between the opening brace and the comment. You have one more before the \else
. This is how I'd write it:
\newcommand{\append}[3]{%
% #1 = start of text, #2 = text to repeat, #3 = number of repetitions
\ifnum #3>0
\setcounter{tempcount}{#3}%
\addtocounter{tempcount}{-1}%
\append{#1#2}{#2}{\arabic{tempcount}}%
\else
#1%
\fi}
The rest works, except when you try to use \append
in the argument of tabular
. The problem there is that \append
is not expanded before the column information is needed. If you want this to work as well, I suggest that you follow @Werner's answer. It's not worth the effort re-inventing everything. However, if you must, you'll need to understand how precisely macro expansion works.
Solution 4
Others have explained he origin of the spaces, and the fact that the argument of tabular
must be completely expandable. The other errors come from the fact that after the first expansion of \append
, TeX sees an &
, and different parts of the macro's code occur in different cells of the alignment. You need to delay the point at which the ampersands are recognized. The following will work in this example, but I can't say it if it will work anywhere else:
\def\amp{&}
\noindent
\begin{tabular}{ccc}
1&2&3\\
\append{start}{\amp test}{1}\\
\append{start}{\amp test}{2}
\end{tabular}

John Kormylo
Updated on August 01, 2022Comments
-
John Kormylo 10 months
I get interesting errors with the following macro. Mostly it works, but I get extra spaces after
\noindent
(but not after\newline
). I tried using\loop
or\whiledo
(fromifthen
) but get stack overflows. The really strange stuff occurs when I try to repeat&
symbols (the log shows everything working until TeX throws in an extra\fi
).\documentclass{article} \tracingmacros=1 \newcounter{tempcount} \newcommand{\append}[3]{ % #1 = start of text, #2 = text to repeat, #3 = number of repetitions \ifnum #3>0% \setcounter{tempcount}{#3}% \addtocounter{tempcount}{-1}% \append{#1#2}{#2}{\arabic{tempcount}} \else #1 \fi} \begin{document} \noindent\append{c}{c}{0} \noindent\append{c}{c}{1} \noindent\append{c}{c}{2} \noindent\append{c}{c}{3} \noindent\begin{tabular}{\append{c}{c}{2}} 1&2&3\\ \append{start}{&test}{1}\\ \append{start}{&test}{2} \end{tabular} \end{document}
I should mention that I've played with
\noexpand
to no avail.-
egreg over 9 yearsYou have several spaces in the definition of
append
; as it stands it can't be used in the argument oftabular
, which must be fully expandable.
-
-
egreg over 9 yearsI've removed two
%
: the one after\else
was redundant; the one after0
is wrong: the space (end-of-line here) terminates the numeric constant and is better to make TeX see it. -
nickie over 9 years@egreg: You're the master, whatever you say... :-)
-
John Kormylo over 9 yearsExcellent, but I still have the problem with & and the error messages I forgot to mention.
-
John Kormylo over 9 yearsThe column specification was mostly what I was looking for. I am so embarassed. I actually have the documentation for that. (multido, on the other hand...)
-
barbara beeton over 9 yearsthe (lack of) vertical space between the last row of "c"s and the
tabular
doesn't look good. a strut would fix it. -
egreg over 9 years@barbarabeeton It's just because the
tabular
isn't protected in acenter
or similar environment; that's just for the example.