4

I have an idea. I want to loop through every character in string argument of macro. For example:

\def\dowithchar#1{%
  % some actions with #1
}

\def\mymacro#1{%
  % further pseudocode
  for (every character \ch in #1)
    \dowithchar{\ch}
}

In result I want to have

\mymacro{ABCDEFGH}

render in pdf string like

(A) (B) (C) (D) (E) (F) (G) (H)

Is it possible in LaTeX? If it's possible, tell me please how to do it.

  • Yes. What have you done so far? Do we need to do this as a string (all catcode-12) or on tokenized basis (retaining braces, etc.)? How should spaces be treated? – Joseph Wright May 03 '16 at 06:51
  • I want to show to my students algorithm of quick sort. I think to make macro like \def\charseq#1#2#3#4#5{% where #1 - string every character of which will be render in tikz \node, and #2, #3 - pointers to low and high elements of sorting sequence and #4, #5 current right and left pointers, all pointers will be render as arrows. So one command \charseq will be render one snapshot of sorting array. – Gubin Aleksandr May 03 '16 at 07:03

1 Answers1

3

This is conveniently done using a recursive macro and \nil-delimited arguments:

\documentclass{article}

\def\dowithchar#1{%
  \doWithCharRec#1\nil%
}

%recursive macro
\def\doWithCharRec#1#2\nil{%
  (#1)%
  \ifx\empty#2\empty\else%
    \space\doWithCharRec#2\nil%
  \fi%  
}

\begin{document}
  $\rightarrow$\dowithchar{ABCDEFGH}$\leftarrow$
\end{document}

or, alternatively, as suggested by egreg, using a \@tfor loop:

\documentclass{article}

\makeatletter
\def\dowithchar#1{%
  \begingroup%
  \def\myspace{}% defined with local scope
  \@tfor\elem:=#1\do{\myspace(\elem)\let\myspace\space}%
  \endgroup%
}
\makeatother

\begin{document}
  $\rightarrow$\dowithchar{ABCDEFGH}$\leftarrow$
\end{document}
AlexG
  • 54,894
  • There's already \@tfor for this. – egreg May 03 '16 at 07:22
  • @egreg Yes, but the leftmost element needs special treatment (no preceding \space). How to achieve this easily within the \@tfor body? – AlexG May 03 '16 at 07:52
  • Usually by defining as separator something that redefines itself to what we need between the next objects: \def\blurb{\def\blurb{ }}\@tfor\next:=#1\do{\blurb\next} – egreg May 03 '16 at 08:01
  • @egreg : Thanks for the hint. I did it somewhat differently. – AlexG May 03 '16 at 08:09