
나는 내가 원하는 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에 항목을 추가하는 것보다 공간을 하나 더 적게 추가합니다. 1을 빼는 방법이 의심스러울 정도로 장황해 보입니다.
현재 두 가지 버전이 작동 중입니다.
@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를 갖고 값 4를 유지하면 다음을 얻습니다 #1
.\count27
\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}
받다
xxxxx
그리고 \myrepeat{3}{A}
얻으려면
AAA
답변2
다음은 패키지 없이 일반 등을 사용하는 버전 \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
는 완전히 확장 가능하므로 그룹을 열거나 닫지 않고도 중첩 루프를 사용할 수 있습니다.