18

I am having trouble with using a loop inside a tabular environment:

\newcounter{it}
\setcounter{it}{0}

\begin{tabular}{ll}
  \loop\ifnum\theit<4
    \addtocounter{it}{1}
    Q & A\\
  \repeat
\end{tabular}

I receive an error about argument of loop having an extra } and the compilation stops at &. I don't get an error when it is a single column table, but even in that case the result is not as expected: I get a single execution of the loop in place of 4.

Can someone tell me what I am missing? Is there special considerations when using loops inside tabular?

2

6 Answers 6

11

Yep, don't do that. tabulars are really special and macro-unfriendly (for instance every & closes a group).

Try

\def\mylines{}%
\loop\ifnum\theit<4
  \addtocounter{it}{1}
  \expandafter\def\expandafter\mylines\expandafter{%
    \mylines
    Q & A\\
  }%
\repeat

outside the tabular and then

\begin{tabular}{ll}
  \mylines
\end{tabular}
12

collect all lines with a token register and then print the lines:

\documentclass{article}
\newcounter{it}  \setcounter{it}{0}
\newtoks\tabtoks
\newcommand\addtabtoks[1]{\tabtoks\expandafter{\the\tabtoks#1}}
\newcommand*\resettabtoks{\tabtoks{}}
\newcommand*\printtabtoks{\the\tabtoks}
\begin{document}

\resettabtoks
\loop\ifnum\theit<4
  \stepcounter{it} \addtabtoks{Q & A\\}
\repeat

\begin{tabular}{ll}
\printtabtoks
\end{tabular}

\end{document}
1
  • 2
    This technique has been introduced here by you as well. Commented Apr 1, 2012 at 7:09
3

Your own answer has to deal with the extra line problem. Here is a way to do that without having to separately construct the last line thereby keeping your table line structure in one place inside the loop. I threw in a \hline or two to show they don't upset the applecart either.

Solution Output

\documentclass[12pt]{article}
\usepackage[a6paper,landscape]{geometry}

\usepackage{ifthen}

\def\tand{&}

\begin{document}
%
\newcounter{it}
\begin{tabular}{ll}
\hline
  \setcounter{it}{1}%
  \whiledo{\theit<4}{%
    Q \tand A \\%
    \ifnum\value{it}=3\hline\end{tabular}\fi
  \stepcounter{it}%
  }%
 \par Immediately after the table
%
\end{document}
3

The latex kernel has some loops, but with the @ letter, thus their use is not so widespread. The \whiledo of ifthen is a wrapper of the \@whilesw of the latex kernel; the latter is expandable, whereas the \whiledo wrapper of ifthen is not. However, here as shown in the answer of the OP's as well as in this answer, one can use with success \whiledo.

It is possible to recycle the \@whilesw of LaTeX and then, there is no problem with the final line in the tabular.

\documentclass[12pt]{article}

% \usepackage{ifthen} % not needed

% \def\tand{&} % not needed

% recycling the \@whilesw of LaTeX into a num test
% pay attention to correctly end explicit numbers in 
% \ifnum tests with a space, if they are last.
\makeatletter
  \def\xwhilenum #1\do{\@whilesw{\ifnum #1}\fi }
\makeatother

\begin{document}
\newcounter{it}

\begin{tabular}{ll}
\hline
  \setcounter{it}{1}%
  \xwhilenum{4>\value{it}}\do {%
    \stepcounter{it}%
     Q & A \\
  }%
\hline
\end{tabular}
\makeatother
 \par Immediately after the tabular
%

\begin{tabular}{ll}
\hline
  before & the loop \\
  \setcounter{it}{1}%
  \xwhilenum{4>\value{it}}\do {%
    \stepcounter{it}%
     Q & A \\
  }%
  still in & the tabular \\
\hline
\end{tabular}
\makeatother
 \par Immediately after the tabular
%
\end{document}

while loop in tabular

2

I solved my problem by using a while loop instead:

\def\tand{&}

\newcounter{it}
\begin{tabular}{ll}%
  \setcounter{it}{1}%
  \whiledo{\theit<3}{%
    Q \tand A \\%
  \stepcounter{it}%
  }%
  {\theit} \tand \\
\end{tabular}

PS: if wondering why I need to print the last one separately, the reason is that the execution leave a partial line (I am using tabular{|l|l|}).

1

I solved a same problem using different approach. For me this solution is more beginner-friendly, very comprehensive while simpler. BUT here you no more need to loop inside a macro-unfriendly environment like tabular{} but loop outside to make a temporary file that will be \inputted inside it.

\documentclass{article}
\begin{document}

\newwrite\tempfile
\immediate\openout\tempfile=Rows.txt

\newcount\foo
\foo=1
\loop
  \immediate\write\tempfile{\the\foo & Q &  \unexpanded{\bf}{A 
\the\foo} \unexpanded{\\}}
\advance \foo +1
\ifnum \foo<5
\repeat

\immediate\closeout\tempfile

\begin{tabular}{lll}
\csname @@input\endcsname Rows.txt
\end{tabular}

\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .