我正在尝试使用该totcount
包,并注意到一些我无法解释的奇怪行为。
具有以下 MWE:
\documentclass{book}
\usepackage{lipsum}
\usepackage{totcount}
\newtotcounter{mycount}
\let\oldsec=\section
\def\section{\stepcounter{mycount}\oldsec}
\newcounter{testcount}
\setcounter{testcount}{\totvalue{mycount}}
\begin{document}
\total{mycount} \\
\arabic{testcount}
\section{First section header}
\lipsum[1]
\section{Second section header}
\lipsum[2]
\end{document}
即使经过多次编译,仍能按预期\total{mycount}
打印,而打印。2
\arabic{testcount}
-1
但是,如果我添加\AtBeginDocument
,\setcounter{}{}
那么这两个命令就会打印2
,这是预期的行为。
也许我错过了软件包文档中的一些要点totcount
,但是有什么理由不能totvalue
在序言中使用吗?
答案1
这是有原因的:LaTeX 在运行期间保存值以便在下次运行中使用它们的唯一方法是通过一些辅助文件。
该totcount
包使用标准.aux
文件,这是一个非常合理的选择,因为这个文件总是\nofiles
在开始时(除非已声明)写入并读入(并在结束时,进行比较并在必要时发出警告)。
然而还有一个问题:第一次读取是作为其中的一部分发生的\begin{document}
,而且这样做也有一个很好的理由:只有在所有包都已加载后才能解释其内容,因为其中一些包定义了可以在文件中找到自己位置的东西(hyperref
就是一个很好的例子)。
命令\totvalue
的定义方式是,如果值尚未确定(计数器刚刚声明时总是会发生这种情况),则返回 -1。因此,您描述的行为是预期的。
使用\AtBeginDocument
,它是在读取.aux
使用设置计数器的文件后执行的\totvalue
。
用 定义命令是\totvalue
安全的,只要该命令仅在文档中使用,因为\newcommand
不会解释替换文本,它只是将其存储不变。\totvalue
使用该命令时,宏将被扩展。
实际上,有一种方法可以在序言中读取总值,但它需要使用不同的辅助文件。另一方面,我仍然认为在开始文档中进行设置更干净。
\documentclass{book}
\usepackage{totcount}
\usepackage{etoolbox}
\usepackage{lipsum}
\newtotcounter[auxfile=\jobname.tot]{mycount}
\newcounter{testcount}
\setcounter{testcount}{\totvalue{mycount}}
\preto\section{\stepcounter{mycount}}
\begin{document}
\total{mycount} \\
\arabic{testcount}
\section{First section header}
\lipsum[1]
\section{Second section header}
\lipsum[2]
\end{document}
答案2
xassoccnt
请参阅末尾的新版本
它使用将assoccnt
计数器与驱动器计数器关联的包,此处的section
计数器既是主计数器又mycount
是从计数器,每次步进时都会步进section
,无论section
中间是否重置。这样就不需要重新定义\section
。
在文档的末尾,总节数存储到totalsections
。
但是,即使使用计数器,也应该能够使用\AtBeginDocument{
它来设置计数器totcount
,因为这应该被执行后 .aux
文件已被读取。
\documentclass{book}
\usepackage{lipsum}
\usepackage{assoccnt}
\newcounter{mycount}
\newcounter{totalsections}
\DeclareAssociatedCounters{section}{mycount}
\makeatletter
\AtEndDocument{%
\immediate\write\@auxout{\string\setcounter{totalsections}{\number\value{mycount}}}
}%
\newcounter{anothercounter}
\AtBeginDocument{%
\setcounter{anothercounter}{\value{totalsections}} % Not really needed here, but works ;-)
}
\begin{document}
There are \arabic{totalsections} in this document
\section{First section header}
\lipsum[1]
\section{Second section header}
\lipsum[2]
\end{document}
带有 xassoccnt 的版本,更短
\documentclass{book}
\usepackage{lipsum}
\usepackage{xassoccnt}
\NewTotalDocumentCounter{totalsections}
\DeclareAssociatedCounters{section}{totalsections}
\begin{document}
There are \TotalValue{totalsections} sections in this document
\section{First section header}
\lipsum[1]
\section{Second section header}
\lipsum[2]
\end{document}
更新 2
可以xassoccnt v1.2
稍微简化一下计数器的定义:
\documentclass{book}
\usepackage{lipsum}
\usepackage{xassoccnt}
% Defines totalsections as a counter and associates it to section
\DeclareTotalAssociatedCounters{section}{totalsections}
\begin{document}
There are \TotalValue{totalsections} sections in this document
\section{First section header}
\lipsum[1]
\section{Second section header}
\lipsum[2]
\end{document}