显示计数器的后续值

显示计数器的后续值

我有一个计数器,用于整个文档。在每一章的开头(命令之后\chapter),我想打印下一个\chapter命令之前立即达到的计数器值。例如,在第 1 章中出现的第一个段落,我想显示计数器在第 1 章中达到的最后一个值。在第 2 章中出现的第一个段落,我想显示计数器在第 2 章中达到的最后一个值。

我已经提出了部分解决方案,但我不知道它是否理想:

我有计数器thecounter,用于记录整个文档的长度。我使用了一个自定义宏\chapter\newchapter每当我开始新的一章时,这个宏都会将计数器重置为“0”:

\newmacro{\newchapter}[1]{
    \setcounter{thecounter}{0}
    \chapter{#1}
}

我可以通过创建一个知道重置之前计数器值的变量来进一步添加这个宏:

\newmacro{\newchapter}[1]{
    \def\valuebeforethechapterends{\value{thecounter}}
    \setcounter{thecounter}{0}
    \chapter{#1}
%the last value of the counter before it gets reset for the next chapter should be printed here
}

在每一章的第一段中,我想显示计数器在下次重置之前将达到的值。不幸的是,我不知道如何告诉代码\valuebeforethechapterends使用哪一个,因为它将在文档中定义多次。

\chapter如何在宏中的命令之后立即重置计数器之前打印其最后一个值?

答案1

egreg 的解决方案很有用,因为它调用了\refstepcounter,除了打印计数器的状态/数字之外,它还可能需要执行其他操作。但这里有一个不需要的解决方案引用计数包中没有\refstepcounter,因此更便宜。它要求每个章节都有一个命令,但不需要标签。我使用了 Bruno Le Floch 的示例文本这里

\documentclass{book}
\makeatletter
\newcounter{mycounter}
\newcommand{\newchapter}[1]{%
  \chapter{#1}%
  \ifnum\thechapter<\tw@\else
    \immediate\write\@auxout{%
      \global\noexpand\@namedef
        {mycounter\the\numexpr\thechapter-1}{\number\c@mycounter}%
    }%
  \fi
  \setcounter{mycounter}{0}%
   \@ifundefined{mycounter\thechapter}{}{%
      \textcolor{red}{The value of \texttt{mycounter} at
      the end of this chapter is \@nameuse{mycounter\thechapter}.}\medskip
  }%
}
\AtEndDocument{%
  \immediate\write\@auxout{%
    \global\noexpand\@namedef{mycounter\thechapter}{\number\c@mycounter}%
  }%
}
% All the following is just an example text.
\newlength{\sos@top}
\newlength{\sos@right}
\newcounter{sos@pages}
\newif\ifSOS
\renewcommand{\thepage}{\the\numexpr\value{page}-\value{sos@pages}\relax}
\newcommand{\addfig}[1]{\g@addto@macro\sos@figures{\vbox{\centering#1}\vfill}}
\newcommand{\sos@reset@figures}{\gdef\sos@figures{\sos@reset@figures\vfill}}
\sos@reset@figures

\newcommand{\sos@shipout@figures}{%
    \begingroup
      \stepcounter{page}%
      \stepcounter{sos@pages}%
      \let\protect\relax
      \setbox\z@\vbox to\vsize{\sos@figures}%
      \let\protect\string
      \AtBeginShipoutOriginalShipout\vbox
        {\vbox to\sos@top{}\moveright\sos@right\box\z@}%
    \endgroup
}
\AtBeginShipout{%
  \ifSOS
    \ifodd\c@page
      \begingroup
      \let\protect\string
      \AtBeginShipoutOriginalShipout\box\AtBeginShipoutBox
      \AtBeginShipoutDiscard
      \sos@shipout@figures
      \endgroup
    \fi
  \fi
}
\newcommand{\SOSshipout}{\clearpage\sos@shipout@figures}
\renewcommand{\SOStrue}{\clearpage\global\let\ifSOS\iftrue}
\renewcommand{\SOSfalse}{\clearpage\global\let\ifSOS\iffalse}
\setlength{\sos@top}{2cm}
\setlength{\sos@right}{2cm}
\newcommand*\lipsumnopar[2][1]{{\def\lips@par{ }\lipsum[#1-#2]}}
\makeatother

\usepackage{booktabs,caption}
\usepackage{atbegshi,xcolor}
\usepackage{lipsum}
\usepackage{hyperref}
\begin{document}

\title{Hello world}
\author{Bruno Le Floch}
\maketitle

\tableofcontents
\listoffigures
\listoftables

\part{Abc}

\SOStrue
\newchapter{Hello}


\noindent{\bf\texttt{mycounter} is called 3 times in this chapter.}\medskip

\addtocounter{mycounter}{1}

\addfig{\begin{tabular}{p{5cm}p{5cm}}
    \toprule
    Abc def & ghijk lmno pq \\
    \midrule
    \lipsum[1] & \lipsum[2] \\
    \bottomrule
  \end{tabular}
  \captionof{table}{\label{tab:atable}A table}
}

\addfig{%
  \rule{8cm}{3cm}%
  \captionof{figure}{A figure}
}

\lipsumnopar{10}

\addfig{\rule{1cm}{3cm}\captionof{figure}{Another figure}}
\addfig{\rule{8cm}{3cm}\captionof{figure}{A figure}}
\addfig{\rule{1cm}{3cm}\captionof{figure}{Another figure}}

\addtocounter{mycounter}{1}
\addtocounter{mycounter}{1}

\newchapter{Bye}

\noindent{\bf\texttt{mycounter} is called 2 times in this chapter.}\medskip

\addtocounter{mycounter}{1}

\addfig{\rule{8cm}{3cm}\captionof{figure}{That should be figure 5.}}
\addfig{\rule{1cm}{3cm}\captionof{figure}{Perhaps the sixth}}

\lipsumnopar{10}

\addfig{\rule{8cm}{3cm}\captionof{figure}{Yet another one}}
\addfig{\rule{1cm}{3cm}\captionof{figure}{One last figure for now.}}

\SOSfalse

\addtocounter{mycounter}{1}

\newchapter{Back to normal}

\noindent{\bf\texttt{mycounter} is called 3 times in this chapter.}\medskip

\addtocounter{mycounter}{1}
\addtocounter{mycounter}{1}

\addfig{\rule{8cm}{3cm}\captionof{figure}{That figure won't be lost.}}

\lipsumnopar[11]{15}

\addfig{\rule{4cm}{5cm}\captionof{figure}{Nor will that one.}}

\lipsumnopar[16]{20}

\lipsumnopar[21]{30}

See Table~\ref{tab:atable}.

\SOSshipout
\SOStrue

\addtocounter{mycounter}{1}

\newchapter{Figures, again}

\noindent{\bf\texttt{mycounter} is called 1 time in this chapter.}\medskip

\addtocounter{mycounter}{1}

\addfig{\rule{5cm}{2cm}\captionof{table}{Let's pretend it's a table}}

\lipsumnopar[21]{25}

\addfig{\rule{5cm}{2cm}\captionof{table}{Let's pretend it's a table}}

\lipsumnopar[26]{30}

\addfig{\rule{4cm}{1cm}\captionof{table}{Last table}}

\end{document}

编辑:

这是我尝试推广的解决方案。需要进行更多测试。

\makeatletter
\newcommand\ifstrsame[2]{%
  \@nameuse{@\ifnum\pdfstrcmp{\detokenize{#1}}%
    {\detokenize{#2}}=0first\else second\fi oftwo}%
}
\def\appchap#1{\ifstrsame{chapter}{#1}{}{\thechapter}}
\def\headingnr#1{%
  \ifstrsame{section}{#1}{%
    \expandafter\getheadingnr\romannumeral-`\q\@nameuse{the#1}..\relax
  }{%
    \number\@nameuse{the#1}%
  }%
}
\def\getheadingnr#1.#2.#3\relax{#2}
\def\newchapter@hook{}
\def\DeclareCallsCounter#1#2{%
  \newcounter{#2}%
  \expandafter\newcommand\csname new#1\endcsname[1]{%
    \ifstrsame{section}{#1}{%
      \gdef\newchapter@hook{%
        \immediate\write\@auxout{%
          \global\noexpand\@namedef
            {\appchap{#1}#2@\headingnr{#1}}{\number\@nameuse{c@#2}}%
        }%
      }%
    }{%
      \newchapter@hook
    }%
    \@nameuse{#1}{##1}%
    \ifnum\headingnr{#1}<\tw@\else
      \immediate\write\@auxout{%
        \global\noexpand\@namedef
          {\appchap{#1}#2@\the\numexpr\headingnr{#1}-1}{\number\@nameuse{c@#2}}%
      }%
    \fi
    \setcounter{#2}{0}%
    \@ifundefined{\appchap{#1}#2@\headingnr{#1}}{}{%
      \textcolor{red}{The value of \texttt{#2} at
      the end of this #1 is \@nameuse{\appchap{#1}#2@\headingnr{#1}}.}\medskip
    }%
  }%
  \AtEndDocument{%
    \immediate\write\@auxout{%
      \global\noexpand\@namedef
        {\appchap{#1}#2@\headingnr{#1}}{\number\@nameuse{c@#2}}%
    }%
  }%
}
\DeclareCallsCounter{chapter}{chapcounter}
\DeclareCallsCounter{section}{seccounter}
\makeatother

答案2

您需要使用\label-\ref系统。

首先,您不需要手动重置计数器,只需将其绑定到chapter

\newcounter{mycounter}[chapter]

接下来我将使用该refcount包并在执行之前发出一个(\label这将产生一个“偏差一”,但很容易纠正):\chapter\refstepcounter{mycounter}

\usepackage{refcount}
\newcounter{mycounter}[chapter]
\newcommand{\newchapter}[1]{%
  \refstepcounter{mycounter}\label{mycounterref@\thechapter}%
  \chapter{#1}
  (The value of \texttt{mycounter} at the end of this chapter will be
   \number\numexpr\getrefnumber{mycounterref@\number\value{chapter}}-1\relax)\par}
\AtEndDocument{\refstepcounter{mycounter}\label{mycounterref@\thechapter}}

当然,第一次编译不会像往常一样给出系统的实际\label数字\ref

相关内容