Tex csname 索引在循环内关闭一个

Tex csname 索引在循环内关闭一个

我正在尝试编写一个符号列表的简单实现(更多的是作为技术练习而不是实际使用)。我遇到了一个相当奇怪的编号问题。以下是我对两个相关命令的实现。该命令创建一个包含\notation“符号”和当前页码的自定义宏(这似乎可以正常工作),该\listofnotation命令将所有定义的符号打印到列表中。问题是,调用\notation{one}定义宏\notation@1并按预期\notation{two}创建\notation@2。但是,当我调用时\listofnotation,输出是\notation@1 two 1\notation@1 one 1\par\notation@2 two 1不像我预期的那样。将的起始索引更改\loopingindex为 0 使其按预期工作,但输出是 \notation@0 one 1\par\notation@1 two 1。这很奇怪。

\documentclass[12pt]{article}

\makeatletter
\newcount\notationcount

\newcommand\notation[1]{%
\global\advance\notationcount by1%
\expandafter\protected@edef\csname notation@\the\notationcount%
\endcsname{\protect{#1}\hskip1em\thepage}%
\expandafter\string\csname notation@\the\notationcount\endcsname%
}

\newcommand\listofnotation{%
\newcount\loopingindex%
\loopingindex=1%
\expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax\else
\section*{List}%
\noindent%
\loop\expandafter\ifx%
\csname notation@\the\loopingindex\endcsname\relax%
\else%
\expandafter\string\csname notation@\the\loopingindex\endcsname~%
\csname notation@\the\loopingindex\endcsname\par\noindent%
\advance\loopingindex by1%
\repeat%
\fi%

}
\makeatother

\begin{document}

\notation{one}
\notation{two}

\listofnotation

\end{document} 

我注意到实现方式与第二个示例类似https://www.tug.org/tug2012/booklet/hendrickson/AmyTugProc.pdf

免责声明:我快速查找了重复项,但我并不确定要搜索什么。

谢谢。

答案1

%您在行末写了一个错误:

\newcommand\notation[1]{%
\global\advance\notationcount by1%
\expandafter\protected@edef\csname notation@\the\notationcount%
\endcsname{\protect{#1}\hskip1em\thepage}%
\expandafter\string\csname notation@\the\notationcount\endcsname%
}

多余的部分%位于第 2 行的末尾;当 TeX 对 进行赋值时\notationcount,它会扩展标记,直到找到不能解释为数字的内容。在您的例子中,它会扩展\expandafter,触发\csname从找到的标记中生成一个标记\endcsname,直到扩展随着它的进行,它也会\the\notationcount扩展对它的赋值已经完成,因此变为先前的值!

我称之为缺少必需空间综合症;-)解决方案:

\newcommand\notation[1]{%
\global\advance\notationcount by1
\expandafter\protected@edef\csname notation@\the\notationcount%
\endcsname{\protect{#1}\hskip1em\thepage}%
\expandafter\string\csname notation@\the\notationcount\endcsname%
}

数字常量后的空格将被忽略。

您的代码中还有其他问题;例如,

\newcount\loopingindex

应该超出定义范围\listofnotation;在这里并不重要,但无论如何都是更好的编程风格。

这个\protect令牌完全放错了地方,它的影响可以从无所作为到造成灾难。你\protect可以标记,而不是它们的支撑列表。

但主要的缺陷是,使用\thepage并不安全,除非您处于输出例程中,或者页面刚刚在\newpage\clearpage或之后启动\cleardoublepage。如何解决这个问题取决于您打算如何使用宏;通过文件传递.aux通常是最安全的方法。

这是您的宏的修复版本,位于%适当的位置。不过,我还没有尝试过应该需要的两遍方法。

\documentclass[12pt]{article}

\makeatletter
\newcount\notationcount

\newcommand\notation[1]{%
  \global\advance\notationcount by 1
  \expandafter\protected@xdef\csname notation@\the\notationcount\endcsname{%
    #1\hskip1em \thepage
  }%
  \texttt{\expandafter\string\csname notation@\the\notationcount\endcsname}%
}

\newcount\loopingindex % NOT inside the definition!

\newcommand\listofnotation{%
  \loopingindex=1
  \expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
  \else
    \section*{List}
    \noindent
    \loop\expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
    \else
      \texttt{\expandafter\string\csname notation@\the\loopingindex\endcsname}~%
      \csname notation@\the\loopingindex\endcsname\par\noindent
    \advance\loopingindex by 1
    \repeat
  \fi
}
\makeatother

\begin{document}

\notation{one}
\notation{two}

\listofnotation

\end{document} 

在此处输入图片描述

使用该文件的实现.aux,因此在任何情况下都能给出精确的页码(前提是该列表在上次运行中没有被修改过):

\documentclass[12pt]{article}

\makeatletter
\newcount\notationcount

\newcommand\notation[1]{%
  \global\advance\notationcount by 1
  \protected@write{\@auxout}{}{%
    \string\stored@notation{\the\notationcount}{#1}{\thepage}%
  }%
  \texttt{\expandafter\string\csname notation@\the\notationcount\endcsname}%
}
\newcommand{\stored@notation}[3]{%
  \global\@namedef{notation@#1}{#2\quad#3}%
}

\newcount\loopingindex % NOT inside the definition!

\newcommand\listofnotation{%
  \loopingindex=1
  \expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
    \typeout{No notation defined; rerun LaTeX}%
  \else
    \section*{List}
    \noindent
    \loop\expandafter\ifx\csname notation@\the\loopingindex\endcsname\relax
    \else
      \texttt{\expandafter\string\csname notation@\the\loopingindex\endcsname}~%
      \csname notation@\the\loopingindex\endcsname\par\noindent
    \advance\loopingindex by 1
    \repeat
  \fi
}
\makeatother

\begin{document}

\notation{one}
\newpage
\notation{two}
\newpage
\notation{thr\'ee}

\listofnotation

\end{document} 

在此处输入图片描述

相关内容