我在扩展另一个宏内的计数器时遇到了麻烦。似乎我不能在这里使用简单的 expandafter 链,因为我的计数器可能会变得非常高。我发现强制扩展命令参数中的计数器值但无法弄清楚如何在我的示例代码中应用它:
\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{0pt}
\newcounter{Mynumbers}
\makeatletter
\def\printmylist{}
\makeatother
\newcommand{\addtomylist}[2]{ %
\stepcounter{Mynumbers}%
$^{( \theMynumbers , #1 ) }~$%
}
\begin{document}
first\addtomylist{0}{one}\\
second\addtomylist{4}{four} \\
~
\printmylist \\
~\\~\\~\\~\\
expected outcome:\\
$first^{(1,0)}$ \\
$secound^{(2,4)}$ \\
1: one \\
2: four \\
\end{document}
答案1
根据您真正想要做的事情,可能会有更好的方法。以下内容似乎产生了您请求的输出,所以我认为这可能符合您的要求:
\documentclass[a4paper,10pt]{report}
\parindent=0pt
\usepackage{etoolbox}
\def\printmylist{}
\newcounter{Mynumbers}
\newcommand{\addtomylist}[2]{%
\stepcounter{Mynumbers}%
${}^{(\theMynumbers, #1 )}~$%
\xappto\printmylist{\theMynumbers: \unexpanded{#2\\}}%
}
\begin{document}
first\addtomylist{0}{one}
second\addtomylist{4}{four}
\printmylist
\end{document}
得出的结果为:
我已经使用\xappto
了电子工具箱包。此命令将第二个参数的扩展版本附加到第一个参数指定的宏:
\xappto<macro><stuff to append>
我已将其放入,\unexpanded
因为您不希望该部分在添加到时扩大\printmylist
。
另外,请注意,我删除了
\newcommand{\addtomylist}[2]{ % <-- unwanted space????
\stepcounter{Mynumbers}%
$^{( \theMynumbers , #1 ) }~$%
}
这就是导致MWE 中的one
和上标之间存在差距的原因。(1,0)
答案2
您必须先扩展计数器的值,然后才能将其添加到列表中。
\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{0pt}
\newcounter{Mynumbers}
\newcommand\printmylist{}
\makeatletter
\newcommand{\addtomylist}[2]{%
\stepcounter{Mynumbers}%
{\textsuperscript{(\theMynumbers,#1)}}%
\edef\@tempa{\theMynumbers}%
\expandafter\addto@mylist@\expandafter{\@tempa}{#2}%
}
\newcommand{\addto@mylist@}[2]{%
\g@addto@macro\printmylist{#1: #2\par}%
}
\makeatother
\begin{document}
first\addtomylist{0}{one}
second\addtomylist{4}{four}
\printmylist
\end{document}
强制expl3
版本:
\documentclass[a4paper,10pt]{report}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\addtomylist}{mm}
{
\int_gincr:N \g_mylist_index_int
\textsuperscript{(\int_use:N \g_mylist_index_int,#1)}
\mylist_add:fn { \int_use:N \g_mylist_index_int }{ #2 }
}
\NewDocumentCommand{\printmylist}{}
{
\seq_use:Nn \g_mylist_list_seq { \par }
}
\int_new:N \g_mylist_index_int
\seq_new:N \g_mylist_list_seq
\cs_new_protected:Nn \mylist_add:nn
{
\seq_gput_right:Nn \g_mylist_list_seq { #1:~#2 }
}
\cs_generate_variant:Nn \mylist_add:nn { f }
\ExplSyntaxOff
\setlength{\parindent}{0pt}
\begin{document}
first\addtomylist{0}{one}
second\addtomylist{4}{four}
\printmylist
\end{document}
输出是一样的。
答案3
您期望的输出与您获得的输出在两个方面有所不同:
- 短语“第一”和“第二”不在数学模式中。
- 该宏
\printmylist
未提供输出1: one \\ 2: four \\
。
除此之外,您不需要\makeatletter
使用-macro\makeatother
的定义,\printmylist
因为该定义不包含符号“@”。此外,您的\addtomylist
-command 的定义将包含可能产生水平空间的空格标记。
以下是经过轻微修改的代码。我希望它现在能实现你的期望:
\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{0pt}
\newcounter{Mynumbers}
\newcommand*\printmylist{}
\makeatletter
\newcommand{\addtomylist}[2]{%
\stepcounter{Mynumbers}%
$^{(\theMynumbers,#1) }~$%
\expandafter\g@addto@macro\expandafter\printmylist\expandafter{\number\value{Mynumbers}: #2 \\}%
}%
\makeatother
\begin{document}
$first$\addtomylist{0}{one}\\
$second$\addtomylist{4}{four}\\
\printmylist\\
\hrulefill\\
expected output:\\
$first^{(1,0)}$\\
$second^{(2,4)}$ \\
1: one \\
2: four \\
\end{document}
\ensuremath
使用而不是可能会获得更好的结果$..$
。
您可能会得到更好的结果,或者使用\par
而不是\\
或将内容包装到\hbox
es 中,同时\par
确保 TeX 处于垂直模式,其中每个最外层\hbox
都被视为单行:
\documentclass[a4paper,10pt]{report}
\setlength{\parindent}{1cm}
\newcounter{Mynumbers}
\newcommand*\printmylist{\par}
\makeatletter
\newcommand{\addtomylist}[2]{%
\stepcounter{Mynumbers}%
\ensuremath{^{(\theMynumbers,#1)}}%
\expandafter\g@addto@macro
\expandafter\printmylist
\expandafter{%
\expandafter\hbox
\expandafter{%
\number\value{Mynumbers}: #2}}%
}%
\makeatother
\begin{document}
\verb|\parindent| is set to 1cm so you can see the difference between \TeX{}
acting in horizontal mode (where it also does the horizontal line-indenting with
the first line of a paragraph and the line breaking within a paragraph and the
\verb|\parfillskip|-glue-thingie at the end of a paragraph) and \TeX{} acting
in vertical mode where each outermost \verb|\hbox| is treated as a single
"line" whose content in turn gets processed in restricted horizontal mode:
\noindent\hrulefill
received output:
$first\addtomylist{0}{one}$
$second\addtomylist{4}{four}$
\printmylist
\noindent\hrulefill
expected output:
$first^{(1,0)}$
$second^{(2,4)}$
\hbox{1: one}
\hbox{2: four}
\end{document}