5 How to define a custom counter and listof-environment for Exercises? 悬赏已过期

发布于 2025-09-08 21:32:41

In LaTeX’s book class, how to define a custom counter for Exercises that is tied to the current chapter (e.g., Exercise 1.1, 1.2 in Chapter 1, Exercise 2.1 in Chapter 2, etc.), and also create a separate List of Exercises (similar to a Table of Contents)?

查看更多

关注者
0
被浏览
1.4k
3 个回答
Sagittarius Rover
Sagittarius Rover 2025-09-08
这家伙很懒,什么也没写!

It seemly consists two questions:

  • define a custom counter for Exercises that is tied to the current chapter
  • create a separate List of Exercises (similar to a Table of Contents)

Noted that, one post should just focused on just one core point. BTW, you'd better provide an MWE, which make it convenient for users on the site to test and start with.


For the first one, you may have a look at chngcntr package(which has been in the 2e-kernel)

For the second one, maybe you can give a glance on tocbasic package in koma-script bundle.


这里第一个需求非常简单,只补充下第二个需求的相关信息:

SolutionA

正如OP给出的回答,可以直接里用latex.ltx以及book.cls已中的部分代码:

\documentclass[openany]{book}

\newcounter{exercise}[chapter]
\renewcommand{\theexercise}{\thechapter.\arabic{exercise}}

\newcommand{\listexercisename}{List of Exercises}

\makeatletter
\newcommand{\listofexercises}{%
  \chapter*{\listexercisename}%
  \@starttoc{loe}%
}

\newcommand{\l@exercise}[2]{%
  \@dottedtocline{1}{1.5em}{2.3em}{#1}{#2}%
}
\makeatother

\newenvironment{exercise}[1][]
{%
  \refstepcounter{exercise}%
  \par\medskip
  \addcontentsline{loe}{exercise}{Exercise \theexercise\if\relax\detokenize{#1}\relax\else: #1\fi}%
  \noindent\textbf{Exercise \theexercise}%
  \if\relax\detokenize{#1}\relax\else\space(#1)\fi
  \par\smallskip
}
{%
  \par\medskip
}

\begin{document}

\tableofcontents
\listofexercises

\chapter{First Chapter}

\begin{exercise}[A short algebra exercise]
Solve $x^2 - 1 = 0$.
\end{exercise}

\begin{exercise}[A short geometry exercise]
Show that the angles of a triangle add up to $180^\circ$.
\end{exercise}

\chapter{Second Chapter}

\begin{exercise}[A short calculus exercise]
Compute $\int_0^1 x^2\,dx$.
\end{exercise}

\end{document}

image.png

这里的关键在于:

\makeatletter
\newcommand{\listofexercises}{%
  \chapter*{\listexercisename}%
  \@starttoc{loe}%
}

\newcommand{\l@exercise}[2]{%
  \@dottedtocline{1}{1.5em}{2.3em}{#1}{#2}%
}
\makeatother

模仿了book.cls中的\listoffigures的定义:

\newcommand\listoffigures{%
    ...
    \chapter*{\listfigurename}%
    ...
    \@starttoc{lof}%
    ...
}
\newcommand*\l@figure{\@dottedtocline{1}{1.5em}{2.3em}}
\let\l@table\l@figure

控制生成辅助文件.loe以及当 \@starttoc{loe} 读到 .loe 文件里一条类型为 exercise 的记录时,LaTeX 会调用 \l@exercise 来决定这一条如何排版。

同时对「练习环境」的定义:

\newenvironment{exercise}[1][]
{%
  \refstepcounter{exercise}%
  \par\medskip
  \addcontentsline{loe}{exercise}{Exercise \theexercise\if\relax\detokenize{#1}\relax\else: #1\fi}%
  \noindent\textbf{Exercise \theexercise}%
  \if\relax\detokenize{#1}\relax\else\space(#1)\fi
  \par\smallskip
}
{%
  \par\medskip
}

其中最关键的:

\addcontentsline{loe}{exercise}{Exercise \theexercise\if\relax\detokenize{#1}\relax\else: #1\fi}%

把当前习题写入 .loe 文件。下一次编译时,\listofexercises 就能把它读出来,显示在 List of Exercises 里。

SolutionB

事实上tocbasic也可以处理类似的方案,这提供了一个更加用户友好的接口:

\documentclass[openany]{book}
\usepackage{tocbasic}
\DeclareNewTOC[
  type=exercise,
  types=exercises,
  float=false,
  nonfloat,
  name=Exercise,
  listname={List of Exercises}
]{loe}

% \BeforeTOCHead[loe]{\cleardoublepage}
\counterwithin{exercise}{chapter}
\renewcommand{\theexercise}{\thechapter.\arabic{exercise}}

\newenvironment{exercise}[1][]
{%
  \refstepcounter{exercise}%
  \addxcontentsline{loe}{exercise}{Exercise~\theexercise\if\relax\detokenize{#1}\relax\else: #1\fi}%
  \par\medskip
  \noindent\textbf{Exercise \theexercise}%
  \if\relax\detokenize{#1}\relax\else\space(#1)\fi
  \par\smallskip
}
{%
  \par\medskip
}

\begin{document}

\tableofcontents
\listofexercises

\chapter{First Chapter}

\begin{exercise}[A short algebra exercise]
Solve $x^2 - 1 = 0$.
\end{exercise}

\begin{exercise}[A short geometry exercise]
Show that the angles of a triangle add up to $180^\circ$.
\end{exercise}

\chapter{Second Chapter}

\begin{exercise}[A short calculus exercise]
Compute $\int_0^1 x^2\,dx$.
\end{exercise}

\end{document}

image.png


Appendix. Solution C

对于想要直接生成一个自定义的「浮动体」需求,类似的最佳实践应该是newfloat:

\documentclass[openany]{book}
\usepackage{graphicx}
\usepackage{newfloat}

\DeclareFloatingEnvironment[
  fileext=lod,
  listname={List of DuckFigs},
  name=Duck Figure,
  within=chapter,
  placement=tbp
]{duckfig}

\begin{document}

\tableofcontents
\listofduckfigs

\chapter{First Chapter}

\begin{duckfig}[ht]
\centering
\includegraphics[width=.45\textwidth,page=1]{example-image-duck}
\caption{A duck on the page}
\end{duckfig}

\begin{duckfig}[ht]
\centering
\includegraphics[width=.45\textwidth,page=2]{example-image-duck}
\caption{Another duck figure}
\end{duckfig}

\chapter{Second Chapter}

\begin{duckfig}[ht]
\centering
\includegraphics[width=.45\textwidth,page=3]{example-image-duck}
\caption{A duck in the second chapter}
\end{duckfig}

\begin{duckfig}[ht]
\centering
\includegraphics[width=.45\textwidth,page=4]{example-image-duck}
\caption{A duck in the second chapter}
\end{duckfig}

\end{document}

image.png

追风少年
追风少年 2025-09-08
这家伙很懒,什么也没写!

Exactly! The first requirement has been meet. The second question remains unresolved. Please see the MWE below for more details.

\documentclass{book}

% Implementation for the first requirement.
% It do work but I don't know if it is a good practice.
\newcounter{exercise}[chapter]
\renewcommand{\theexercise}{\noindent\textbf{Exercise \thechapter.\arabic{exercise}}\quad}
\newcommand{\ex}{\addtocounter{exercise}{1}\theexercise}

\begin{document}

\chapter{Some basic mathematics}

\chapter{Differentiable manifolds and tensors}

\section{Definition of a manifold}

\ex $a^{2}+b^{2}=c^{2}$

\ex $\exp(\mathrm{i}\pi)=-1$

\section{The sphere as a manifold}

\ex $\cos^{2}\theta + \sin^{2}\theta = 1$

\ex $E=\hbar \omega$

\end{document} 
追风少年
追风少年 2025-09-08
这家伙很懒,什么也没写!

This is a MWE.

\documentclass{book}
\usepackage{lipsum}

% -------------------------------
% Counter
\newcounter{exercise}[chapter]
\renewcommand{\theexercise}{\thechapter.\arabic{exercise}}
% -------------------------------
% Exercises environment (list-based)
\newenvironment{exercises}
{%
    \par\vspace{\baselineskip}%
    \noindent\rule{\textwidth}{0.8pt}\par%
    \vspace{0.5\baselineskip}%
    \begin{list}{}{%
        \setlength{\leftmargin}{0pt}%
        \setlength{\itemindent}{0pt}%
        \setlength{\listparindent}{0pt}%
        \setlength{\labelwidth}{0pt}%
        \setlength{\labelsep}{0pt}%
        \setlength{\itemsep}{1.5\baselineskip}%
        \setlength{\parsep}{0pt}%
        \setlength{\topsep}{0pt}%
    }%
}
{%
    \end{list}%
    \vspace{0.5\baselineskip}%
    \noindent\rule{\textwidth}{0.8pt}\par%
    \vspace{\baselineskip}%
}
% -------------------------------
% List of Exercises machinery
\newcommand{\listexercisename}{List of Exercises}
\makeatletter
\newcommand{\listofexercises}{%
  \chapter*{\listexercisename}%
  \@starttoc{loe}%
}
\newcommand\l@exercise[2]{%
  \@dottedtocline{1}{1.5em}{2.3em}{#1}{#2}}
\makeatother
% -------------------------------
% Patch \item to also add to .loe
\let\olditem\item
\renewcommand{\item}[1][]{%
  \refstepcounter{exercise}%
  \addcontentsline{loe}{exercise}{Exercise~\theexercise\ifx\relax#1\relax\else: #1\fi}%
  \olditem[\textbf{Exercise \theexercise}\quad]%
}

\begin{document}

\tableofcontents
\listoftables
\listofexercises

\chapter{Some basic mathematics}

\begin{table}
  \centering
  \begin{tabular}{c|c}
    \hline\hline
    (1,1) & (1,2) \\
    \hline
    (2,1) & (2,2) \\
    \hline\hline
  \end{tabular}
  \caption{This is a table.}\label{tbl:1}
\end{table}

\chapter{Differentiable manifolds and tensors}

\section{Definition of a manifold}

\begin{exercises}
\item \lipsum[2][1-3] $a^{2}+b^{2}=c^{2}$
\begin{equation}
  a^{2}+b^{2}=c^{2}
\end{equation}

\item \lipsum[2][1-3] $\exp(\mathrm{i}\pi)=-1$
\begin{equation}
  \exp(\mathrm{i}\pi)=-1
\end{equation}

\item \lipsum[2][1-3] $\cos^{2}\theta + \sin^{2}\theta = 1$
\begin{equation}
  \cos^{2}\theta + \sin^{2}\theta = 1
\end{equation}
\end{exercises}

\section{The sphere as a manifold}

\begin{exercises}
\item \lipsum[2][1-3] $E=\hbar \omega$
\begin{equation}
  E=\hbar \omega
\end{equation}
\end{exercises}

\end{document}

image.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览