Я пытаюсь сбросить счетчик каждый раз, когда встречаю a, 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}