Первый метод: исправление\@startsection

Первый метод: исправление\@startsection

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

Связанный контент