我正在尝试编写一个符号列表的简单实现(更多的是作为技术练习而不是实际使用)。我遇到了一个相当奇怪的编号问题。以下是我对两个相关命令的实现。该命令创建一个包含\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}