LaTeX教程(004)-LaTeX文档结构(04)

本文详细解释了LaTeX中的标题编号机制,包括secnumdepth计数器的作用,如何控制标题的编号深度,以及如何使用titlesec包来定制标题样式。还介绍了宏定义和章节划分命令的计数器结构及其应用。
摘要由CSDN通过智能技术生成

LaTeX教程(004)- LaTeX \LaTeX LATEX文档结构(04)

2.2.1 标题编号

为了支持编号, LaTeX \LaTeX LATEX为每一个划分单位使用了一个 计数器,并用这些计数器组合成标题编号。例如,通常2.1表示第二章第一节的编号,这里2是由章(chapter)的计数器提供的,1是节(section)的计数器提供的,低级的划分单位的编号建立在更高级的划分单位编号的之上,以此类推,层层累加。

回顾一下上一篇的中我们使用的一个样例,当时我们特别强调了,\subsubsection命令生成的标题既没有编号,在目录中也没有显示其条目。标题编号到第几层(即编号的深度),由一个叫secnumdepth的计数器控制。例如,在book类中,secnumdepth的值默认是2,因此,从最高级标题\part到2级标题\subsection都会被编号。我们使用一个命令来改变它的值,例如,\setcounter{secnumdepth}{1},可以将它的值改为1。这个命令可以放在导言区,也可以放在正文中。命令会即时生效。我们演示一下它的作用:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\tableofcontents
\chapter{这是第一章}
\section{这是第一章的第一节}
\subsection{这是第一章第一节的第一个子节}
\subsubsection{这是一个子子节}
\end{document}

这是一段secnumdepth的值没有被修改过的book类文档,编译结果如下(这里我们只展示目录和标题):

在这里插入图片描述
在这里插入图片描述

现在在导言区在加上一行代码,以将编号深度改为1:

\setcounter{secnumdepth}{1}

目录和导言区就会发生变化:

在这里插入图片描述
在这里插入图片描述

可以看到,这次仅编号到1级标题,\subsection没有被编号,因为它是二级标题。我们可以在正文中随时使用该命令修改编号的深度,改动会对命令之后的所有内容生效,直到再一次使用该命令。我们再演示一次:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\tableofcontents
\chapter{这是第一章}
\section{这是第一章的第一节}
\subsection{这是第一章第一节的第一个子节}
\subsubsection{这是一个子子节}
\setcounter{secnumdepth}{1}  %从这里开始将编号深度改为1
\chapter{这是第二章}
\section{这是第二章的第一节}
\subsection{这是第二章第一节的第一个子节}
\subsubsection{这是一个子子节}
\setcounter{secnumdepth}{3}  %从这里开始将编号深度改为3
\chapter{这是第三章}
\section{这是第三章的第一节}
\subsection{这是第三章第一节的第一个子节}
\subsubsection{这是一个子子节}
\end{document}

编译结果如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意第三章的子子节,尽管我们将编号深度修改为3,子子节被编号了,但是它仍然没有在目录中显示出来。这是因为secnumdepth的值只能影响编号深度,不能影响目录的结构深度。影响目录的结构深度的一个计数器是tocdepth,我们后面再讲。

如果我们想让所有标题都不编号,最方便的办法是将secnumdepth的值设置为-2,而不是一直使用带星号的划分命令。这种方法的好处是,目录仍然可以生成。

如果我们不知道当前的编号深度是多少,只是想在此基础上加上(或减去)几级,那么可以使用\addtocounter命令。例如,在上面的例子中,我们可以将第三章前面的\setcounter{secnumdepth}{3}换成\addtocounter{secnumdepth}{2},意为将当前的secnumdepth的值加2。如果想减小secnumdepth的值,可以用同一个命令加上一个负数,例如: \addtocounter{secnumdepth}{-1},它可以将当前的secnumdepth的值减1。

每一个章节划分命令都有一个与之关联的计数器,默认情况下,计数器的名称和与之对应的章节划分命令相同,例如,\section对应的计数器就是section\chapter对应的计数器就是chapter。这个计数器存储了它所对应的章节划分命令的数量。我们可以通过使用\the+counter形式的命令将这些已经格式化的完整编号打印出来:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\tableofcontents
\chapter{这是第一章}
\section{这是第一章的第一节}
\thechapter % 输出第一章的编号

\thesection % 输出第一章第一节的编号
\end{document}

输出结果如下:
在这里插入图片描述

实际上,在这个例子中,计数器section的值是1,但为什么\thesection输出的是1.1呢?这和编号命令\the+counter的定义结构有关。

在了解编号命令的定义结构之前,我们先要了解计数器的定义结构。

从前面的例子中,我们可以观察到,每当一个计数器发生变化,它的下一级计数器会被重置,例如,第一章(chapter)有很多节(section),但当第二章开始,section又会被重置为1。当然,重置本身也是一种变化,此时section也发生了变化,subsection也会被重置,以此类推。这是因为计数器就是以这种层层嵌套的形式定义的。例如,在report以及book的类文件中,包含以下声明:

\newcounter{part} % (-1) parts
\newcounter{chapter} % (0) chapters
\newcounter{section}[chapter] % (1) sections
\newcounter{subsection}[section] % (2) subsections
\newcounter{subsubsection}[subsection]% (3) subsubsections
\newcounter{paragraph}[subsubsection] % (4) paragraphs
\newcounter{subparagraph}[paragraph] % (5) subparagraphs

我们用\newcounter命创建一个计数器,它可以创建一个独立的计数器,也可以使用它的选项为该计数器设置一个重置条件。例如\newcounter{section}[chapter]表示创建一个计数器section,并且它随计数器chapter的变化而重置。

这些声明中,默认用这个命令定义了所有的章节划分命令的计数器,可以看到,chapter计数器是独立的,并不会在part变化时重置,如果我们想让chapterpart重置,可以将类文件中的\newcounter{chapter}替换为\newcounter{chapter}[part]

当然,如果我们只是想改变当前的文档中某个计数器的行为,那么最好不要改动类文件。对于已有的计数器,我们可以在当前的文档内部使用命令\counterwithin或者\counterwithout来改变它的行为。例如,\counterwithin{chapter}{part}可以将chapter计数器嵌入到part中,即part变化时,chapter重置。我们可以演示一下:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\tableofcontents
\counterwithin{chapter}{part} % 将chapter嵌入到part中
\part{这是第一部分}
\chapter{这是第一章}
\part{这是第二部分}
\chapter{这是第二章}
\end{document}

输出的结果我们仅截取标题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,Part II中,chapter的计数器仍是从1开始的,这意味着它被重置了。并且\chapter的编号也与\part的计数器关联起来了。

\counterwithout命令可以取消某种嵌套,例如,默认情形下,subsection计数器会在section变化重置,我们可以使用\counterwithout来取消这种结构:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\tableofcontents
\counterwithout{subsection}{section} %取消嵌套
\chapter{这是第一章}
\section{这是第一节}
\subsection{这是第一节的第一个子节}
\subsection{这是第一节的第二个子节}
\section{这是第二节}
\subsection{这是二节的第一个子节}
\end{document}

输出结果如下:

在这里插入图片描述

可以看到,子节的计数器不会被重置,并且编号也独立了。

在讲编号的定义结构之前,我们还要先了解一个概念,即如何将一个计数器格式化输出。一个计数器的值是多少,我们是无法直接看到的。想看到,需要将他们以某种格式打印出来,这一操作叫作格式化输出。

例如,我们如果想知道当前的文档中,默认的编号深度是多少,就可以格式化输出计数器secnumdepth:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\Roman{secnumdepth}、 % 以大写罗马数字形式输出secnumdepth的值
\arabic{secnumdepth}、 % 以阿拉伯数字形式输出secnumdepth的值
\alph{secnumdepth} % 以小写字母形式输出secnumdepth的值
\end{document}

输出结果如下:

在这里插入图片描述

通常我们看到的都是阿拉伯数字。常用的格式化输出命令还有\Alph(大写字母)、\roman(小写罗马数字)等等。我们不再一一列举。

当我们使用一个划分命令时,系统在底层调用了这些格式化的命令,以便我们能看到它们的编号。那么,这些编号是如何组合起来,并且封装到\the+counter命令中的呢?例如,我们可以观察到,节的编号是"计数器chapter的值+一个点.+计数器section的值",而我们只需要使用\thesection就可以将它打印出来。

在这之前,我们先了解一下 LaTeX \LaTeX LATEX的宏定义功能。如果我们有一经常输入的字符串,我们就可以将它定义成一个命令,使用\newcommand命令可以实现这一目的。如果我们声明了\newcommand{\A}{BCDEFG……},那么我们每次在正文中输入\A, LaTeX \LaTeX LATEX就会将它展开成BCDEFG。\A是一个命令,是我们要自定义的一个命令,名称自取,只要不与已有的命令重复即可。BCDEFG是我们要将其定义成\A的东西,可以是任何合法的字符串,包括命令。我们可以做个演示:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\newcommand{\A}{BCDEFG} % 将\A定义成BCDEFG
\newcommand{\T}{\LaTeX} % 将\T定义成\LaTeX
\begin{document}
\A 

\T
\end{document}

输出结果如下:

在这里插入图片描述

对于一个已经存在的命令,我们可以使用\newcommand命令重定义它,例如,我们可以在上面的例子中增加一行\renewcommand{\LaTeX}{这是我们重定义的latex},那么输出结果就会变成:

在这里插入图片描述

我们将\T定义成了\LaTeX,又将\LaTeX重定义成了"这是我们重定义的latex",因此最终输出的就是这句话。可见宏定义是可以嵌套的。

现在我们知道\chapter命令的定义中是包含了\thechapter的,以显示它的编号。那么\thechapter是如何定义的呢?简单地说是

\renewcommand{\thechapter}{\arabic{chapter}}

我们可以做个演示:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\chapter{这是第一章}
这是第一章的编号: \arabic{chapter}
\end{document}

可以得到以下输出:

在这里插入图片描述

那么\section是如何将编号显示为"计数器chapter的值+一个点.+计数器section的值"的呢?因为\thesection命令的定义中包含了\thechapter:

\renewcommand{\thesection}{\thechapter.\arabic{section}}

使用\section时,系统底层调用了\thesection,而\thesection的定义是\thechapter.\arabic{section},由此,就得到了我们看到的编号形式。

我们也可以做个演示:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\begin{document}
\chapter{这是第一章}
这是第一章的编号: \arabic{chapter}
\section{这是第一节}
这是第一章第一节的编号: \thechapter.\arabic{section}
\section{这是第二节}
这是第一章第二节的编号: \thechapter.\arabic{section}
\end{document}

编译:

在这里插入图片描述

同样,\thesubsection的定义中包含了\thesection:

\renewcommand\thesubsection{\thesection.\arabic{subsection}}

以此类推,我们不再一一演示。

我们知道了编号的原理,就可以试着重定义它们,改成我们想要的样子了,例如,我们想将所有的\section计数器输出为大写字母,就可以这样做:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\renewcommand\thesection{\thechapter.\Alph{section}} % 将\section的编号定义成大写字母
\begin{document}
\chapter{这是第一章}
\section{这是第一节}
\section{这是第二节}
\subsection{这是一个子节}
\end{document}

编译:

在这里插入图片描述

这样会显得很奇怪,实际上我们可以将\thesection的定义中的\thechapter.去掉,这样会更好看些。

如果我们想给编号加上一个方框,那么重定义the+counter命令并不是一个好办法,例如:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\renewcommand{\thesection}{\fbox{\thechapter.\arabic{section}}} %重定义\thesection,\fbox命令可以在一个对象外面加上一个可见的盒子
\begin{document}
\chapter{这是第一章}
\section{这是第一节}
\section{这是第二节}
\label{sec:wrong}
\subsection{这是一个子节}
我们在引用 \ref{sec:wrong} 节时会出现我们不想要的结果。% \label和\ref命令是交叉引用命令,我们后面再讲
\end{document}

编译:

在这里插入图片描述

可以看到,如果给一个编号通过重定义的方式加上一个方框,那么他的次级标题的编号就会变得难看,交叉引用的效果(可见计数器的显示命令也被交叉引用的机制使用)也不是我们想要的(通常引用不带样式)。

我们可以重定义 LaTeX \LaTeX LATEX的内部命令\@seccntformat,它负责排版标题的编号部分。但改动内部命令是不太安全的行为,最方便的办法是使用titlesec包:

\documentclass{book}
\usepackage{ctex}
\usepackage[a5paper]{geometry}
\usepackage{titlesec}
\titlelabel{\fbox{\thetitle}\hspace{0.5em}} %我们使用\titlelabel给标题的标头加上一个可见的盒子,而不去重定义编号的样式。0.5em是方框到标题之间的间隙,你可以去掉\hspace{0.5em}再编译一次对比一下效果
\begin{document}
\chapter{这是第一章}
\section{这是第一节}
\section{这是第二节}
\label{sec:OK}
\subsection{这是一个子节}
我们在引用 \ref{sec:OK} 节时不会出现问题。
\end{document}

编译:
在这里插入图片描述
关注【年轻人 你渴望力量么】

  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值