section
每次遇到基于此的情况时,我都会尝试重置计数器文档。
\documentclass{article}
\newcounter{example}[section] % This line reset the counter every time meet a section
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1} \rmfamily}
{\medskip}
\begin{document}
\section{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section{Another section}
\begin{example}
C
\end{example}
\end{document}
这将产生
这意味着它有效。
但是,现在我想删除部分之前的数字,因此我*
在之后添加了section
。
\documentclass{article}
\newcounter{example}[section] % Tried to change `section*`, but throws error
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1} \rmfamily}
{\medskip}
\begin{document}
\section*{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section*{Another section}
\begin{example}
C
\end{example}
\end{document}
然而,这一次,计数器不会像
如果我改为
\newcounter{example}[section*]
它会抛出错误
没有定义计数器‘section*’。
见面时如何重置计数器section*
?
答案1
您收到错误,\newcounter{example}[section*]
因为section*
在 LaTeX 中不是计数器。section
是,但不是section*
。
第一种方法:修补\@startsection
您可以进行修补\@startsection
,以便在\section*
调用时(这是级别 1 的分段命令)并且仅在这种情况下,您的example
计数器才会重置为 0。以下有效是因为\@ssect
仅在未编号的分段命令中调用,并且我们仅在分段命令的级别为 1(\section
或\section*
)时重置计数器。
\documentclass{article}
\usepackage{etoolbox}
\newcounter{example}[section]
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1}%
\rmfamily}
{\medskip}
\makeatletter
\patchcmd{\@startsection}
{\@ssect}{\ifnum#2=1 \setcounter{example}{0}\fi\@ssect}
{}{\FAILED}
\makeatother
\begin{document}
\section*{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section*{Another section}
\begin{example}
C
\end{example}
\begin{example}
D
\end{example}
\section{Numbered section}
\begin{example}
E
\end{example}
\begin{example}
F
\end{example}
\end{document}
第二种方法:使用xparse
重新定义\section
实现相同结果的另一种方法是使用xparse
以重新定义\section
,就像 egreg 在这个答案。此技术的优点是它不依赖于\section
和的实现细节\@startsection
,因此即使\section
已被重新定义并且不再是 LaTeX2e 的命令,它也应该始终有效——如果您使用诸如这样的包\section
重新定义,或者只是尝试堆积使用第一种技术完成的几个重新定义,情况可能就是这样。因此,我认为从工程角度来看,第二种方法更好。\section
titlesec
\documentclass{article}
\usepackage{xparse}
\newcounter{example}[section]
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1}%
\rmfamily}
{\medskip}
% Save the original \section command
\let\latexsection\section
% Simple redefinition of \section (including \section*)
\RenewDocumentCommand{\section}{sO{#3}m}{%
\IfBooleanTF{#1}
{\setcounter{example}{0}%
\latexsection*{#3}}
{\latexsection[#2]{#3}}%
}
\begin{document}
\section*{Section}
\begin{example}
A
\end{example}
\begin{example}
B
\end{example}
\section*{Another section}
\begin{example}
C
\end{example}
\begin{example}
D
\end{example}
\section{Numbered section}
\begin{example}
E
\end{example}
\begin{example}
F
\end{example}
\end{document}
这两种技术都会产生以下输出:
关于用户定义环境实现的备注
在实际环境中,您可能需要执行类似这样的操作(或变体),以确保输入不会引入不必要的空格。这是关于用户定义环境的一般性说明;因为\subsection*
通常会开始一个新段落——除非您使用跑进布局类型——\ignorespaces
例如,这里可能不需要。同样,\ignorespacesafterend
在之后也不需要\par\medskip
,因为\par
将 TeX 置于垂直模式,其中空格会被忽略——但无论如何,这不会造成任何损害。
\newenvironment{example}[1][]
{\refstepcounter{example}\par\medskip
\subsection*{Example~\theexample. #1}%
\rmfamily
\ignorespaces}
{\unskip
\par\medskip
\ignorespacesafterend}