
我想創建一個新命令,它允許我執行repeat
任何characters
我想要的n times
.經過一番搜索和嘗試,我想出了這個:
\usepackage{multido}
\newcommand{\myrepeat}[2]{%
\newcount\iterations%
\iterations #1%
\advance\iterations -1
\multido{\iN=0+1}{\iterations}{#2\ }#2%
}
在生成的 PDF 中,命令後面有一些奇怪的間距,因此我添加了註釋符號%
,然後它就消失了。
我的問題是:有沒有更好的方法來做到這一點,它和這個一樣容易理解,最好不要引入很多依賴項?
multido
如果不是太複雜,或者如果你能解釋它,那麼它就不再複雜了,沒有也可以。我想用於multido
這樣的事情是可以的,因為它的名字意味著多次做某事,但我不確定我是否採取了最簡單和最乾淨的方法來做到這一點。
請注意,我的解決方案添加的空間比向 pdf 添加的項目少了一個。在我看來,減去一個的方式似乎過於冗長。
我現在有兩個版本可以使用:
@egreg 修改後的:
\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}{.....}{\ }
}
@christian 修改後的:
\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]{.....}{\ }
}
我不知道一個比另一個有什麼優勢。也許還有一種更好的方法來刪除最後一個空格或分隔字符,而不是少做一次迭代並只寫入要在沒有分隔符的情況下再次重複的字符。我引入了分隔符,因為我認為它可能很有用,而且它只是第三個參數。
答案1
沒有套餐:
\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}
為什麼要組?它允許嵌套調用。
如果您只想重複一個字元:
\documentclass{article}
\newcommand\myrepeat[2]{%
\begingroup
\lccode`m=`#2\relax
\lowercase\expandafter{\romannumeral#1000}%
\endgroup
}
\begin{document}
\myrepeat{4}{x}
\end{document}
正如 Ulrich Diez 正確評論的那樣,這段程式碼不允許將計數器註冊為重複次數;為了支援這一點,一個稍微複雜的版本是
\newcommand\myrepeat[2]{%
\begingroup
\lccode`m=`#2\relax
\lowercase\expandafter{\romannumeral\number\number#1 000}%
\endgroup
}
\romannumeral
觸發第一個\number
,擴展第二個;如果我們#1
連續得到 4 個(其中•
表示空間標記
\romannumeral\number\number4•000
\romannumeral\number4000
\romannumeral4000
mmmm
相反,如果我們有\count27
as#1
並且\count27
保持值 4,我們得到
\romannumeral\number\number\count27•000
\romannumeral\number4000
\romannumeral4000
mmmm
如果我們有\foo
(一個命名的計數器暫存器),再次保存值 4,我們有
\romannumeral\number\number\foo•000
\romannumeral\number4•000
\romannumeral4000
mmmm
所以二\number
為了涵蓋第三種情況,的實例是必要的。這利用了這樣一個事實:空格結束了對「顯式」數字的搜索,然後被忽略(在第三種情況下,在擴展第二個\number
令牌之後,不會忽略空格令牌)。
如果您還想在重複之間插入文本,第一種方法非常簡單:只需從 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
(不要以零重複來呼叫它)。
具有遞歸的不同解決方案和舊的想法\romannumeral#1000
會產生一長串 m,我們可以一次使用一個。
\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}
遞迴消耗二一次標記,以區分是否只剩下一步要做。當遞歸重新開始時,第二個令牌被放回。
然而,這僅用於研究。在現實世界的應用程式中我會做
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\myrepeat}{O{}mm}
{
\int_compare:nT { #2 > 0 }
{
#3 \prg_replicate:nn { #2 - 1 } { #1#3 }
}
}
\ExplSyntaxOff
被稱為喜歡\myrepeat[-]{4}{x}
得到
xxxx
並\myrepeat{3}{A}
得到
AAA
答案2
這是一個沒有任何包的版本,僅使用 plain\loop
等\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}
答案3
FWIW,在 ConTeXt 中您可以用來\dorecurse
重複某些內容。例如:
\dorecurse{10}{Hello world. }
將列印Hello world.
10 次。當前迭代次數儲存在巨集中\recurselevel
。
答案4
在 OpTeX 中,您可以使用\fornum
巨集:
\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
該\fornum
巨集是完全可擴展的,您可以使用巢狀循環而無需開啟或關閉群組。