将宏中的当前计数器值添加到其他变量?

将宏中的当前计数器值添加到其他变量?

我在扩展另一个宏内的计数器时遇到了麻烦。似乎我不能在这里使用简单的 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

您期望的输出与您获得的输出在两个方面有所不同:

  1. 短语“第一”和“第二”不在数学模式中。
  2. 该宏\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而不是\\或将内容包装到\hboxes 中,同时\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}

编译示例后的输出

相关内容