第一种方法:修补\@startsection

第一种方法:修补\@startsection

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重新定义,或者只是尝试堆积使用第一种技术完成的几个重新定义,情况可能就是这样。因此,我认为从工程角度来看,第二种方法更好。\sectiontitlesec

\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}

相关内容