Primeiro método: patch\@startsection

Primeiro método: patch\@startsection

Estou tentando zerar o contador toda vez que encontro um sectioncom base nissodocumento.

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

Isto irá gerar

insira a descrição da imagem aqui

o que significa que funciona.

No entanto, agora quero remover o número antes da seção, então adicionei *depois 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}

No entanto, desta vez, o contador não será zerado como

insira a descrição da imagem aqui

Se eu mudasse para

\newcounter{example}[section*]

Isso gerará erro

Nenhuma 'seção*' do contador definida.

Como zerar o contador quando se encontra section*?

Responder1

Você recebeu um erro \newcounter{example}[section*]porque section*não é um contador no LaTeX. sectioné, mas não section*.

Primeiro método: patch\@startsection

Você pode corrigir \@startsectionpara que quando \section*for chamado (que é um comando de seccionamento de nível 1) e somente neste caso, seu examplecontador seja zerado. O seguinte funciona porque \@ssectsó é chamado para comandos de seccionamento não numerados, e só zeramos o contador quando o nível do comando de corte é 1 ( \sectionou \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}

Segundo método: usando xparsepara redefinir\section

Outra maneira de obter o mesmo resultado é usar xparsepara redefinir \section, como egreg fez emesta resposta. A vantagem desta técnica é que ela não depende de detalhes de implementação de \sectione \@startsection, portanto ela deve sempre funcionar mesmo que \sectiontenha sido redefinida e não seja \sectionmais um comando do LaTeX2e - este pode ser o caso se você redefinir \sectionusando um pacote como titlesec, ou simplesmente se você tentar acumular várias redefinições feitas com a primeira técnica. Assim, eu diria que este segundo método é melhor do ponto de vista da engenharia.

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

Ambas as técnicas levam à seguinte saída:

Captura de tela

Observações sobre a implementação de ambientes definidos pelo usuário

Em seu ambiente real, você pode querer fazer algo assim (ou uma variante) para ter certeza de que sua entrada não introduz espaços indesejados. Esta é uma observação geral sobre ambientes definidos pelo usuário; já que \subsection*normalmente inicia um novo parágrafo - a menos que você esteja usando ocorrer emtipo de layout – \ignorespacesprovavelmente não é necessário aqui, por exemplo. Da mesma forma, \ignorespacesafterendnão deveria ser necessário after \par\medskip, pois \parcoloca o TeX no modo vertical onde os espaços são ignorados - mas não deve prejudicar, no entanto.

\newenvironment{example}[1][]
  {\refstepcounter{example}\par\medskip
   \subsection*{Example~\theexample. #1}%
   \rmfamily
   \ignorespaces}
  {\unskip
   \par\medskip
   \ignorespacesafterend}

informação relacionada