西安交通大学本科生毕业论文 LaTeX 写作

毕业了终于有空来一个个地填博客的坑了。毕业论文无疑是决定能否毕业的关键,要是正好碰上比较水的老师,毕业论文可以说是唯一需要花时间的东西,老师根本不会在意你的实验结果。有一句话这么说,每年国内高校的毕业论文最大的作用是培养了一批了解基本的排版常识、熟悉日常办公软件(Word、Excel、PowerPoint)基本操作的「大学生」。由于我选择了使用 $\LaTeX$,在魔改现有模板的过程中,也极大地提高了我使用 $\LaTeX$ 的能力。

1. 为什么使用 $\LaTeX$

无论是在知乎还是在 V2EX 我都看见过很多关于到底是使用 Word 还是 $\LaTeX$ 书写 本科生毕业论文 的讨论。我的看法是:Word 能够满足 本科生毕业论文 的一切需求,但是要想以正确姿势使用 Word 排版论文,所要学习的东西不比 $\LaTeX$ 少,在我周围使用 Word 排版的同学中几乎没有一个能够正确插入奇偶页分页符、所有图表的标注和引用正确使用了交叉引用功能、参考文献使用文献管理工具自动生成并且以正确的方法引用、图表能转换成 Word 能处理的矢量图格式并正确插入的同学。而如果找到了一个理想的 $\LaTeX$ 模板,这些页码、交叉引用、图片排版等问题几乎不用考虑。我在使用现有模板的同时,尽可能地完善模板的功能,希望能够把 $\LaTeX$ 的优势体现得更加明显。

此模板适用的对象

虽然 $\LaTeX$ 模板的初衷是让使用者用起来更加方便,但此模板并不适合那些希望配置好模板后一劳永逸的人,因为不同的编译环境可能会产生不同的结果,学校对于论文排版的要求随时可能变化,指导老师随时可能提出一些奇怪的要求,模板里面的代码可能过时或者有更好的解决方案。因此我认为喜欢折腾且对于排版有一定追求的人更适合使用此模板。

2. 编译环境选择和配置

推荐到清华镜像站下载最新版本的Tex Live(Windows / Linux)或 MacTeX(macOS)。该软件的安装过程其实就是把大量的文件解压并放到指定位置,所以安装过程比较简单。安装好了之后注意检查一下环境变量,确保能够找到 xelatex 命令即可。

推荐使用VSCode作为文本编辑工具,配合LaTeX Workshop插件可以非常方便地进行编译和预览。

以下是 LaTeX Workshop 插件的配置代码,latex-workshop.latex.tools 表示单个编译命令及其参数。latex-workshop.latex.recipes 表示一次编译过程所需经历的编译命令(们)。

"latex-workshop.latex.tools": [
    {
        "name": "xelatex",
        "command": "xelatex",
        "args": [
            "-shell-escape",
            "%DOC%"
        ]
    },
    {
        "name": "biber",
        "command": "biber",
        "args": [
            "%DOCFILE%"
        ]
    },
],
"latex-workshop.latex.recipes": [
    {
        "name": "xelatex",
        "tools": [
            "xelatex"
        ]
    },
    {
        "name": "xelatex -> biber -> xelatex*2",
        "tools": [
            "xelatex",
            "biber",
            "xelatex",
            "xelatex"
        ]
    }
]

3. 基本写作方法

下面是写作环境的文件目录。bibliography.bib 文件包含了准备引用的参考文献的 BibTeX 信息。figures 目录下是文章中出现的图形图像文件集合。pages 目录下是各章节的 $\LaTeX$ 源代码,将论文的各个部分拆分成不同的文件,管理起来更方便。thesis.pdf 是生成的 PDF 文件,thesis.tex 是总的 $\LaTeX$ 源代码,里面包含了各种声明和定义,比如文件的主题样式、字体、各章节的文件路径、各种宏定义等。xjtuthesis.cls 是论文的模板,修改自Aetf/xjtuthesis,也参考了 Tedxz/xjtuthesis-x的内容。与它们最主要的区别在于我这个增加了封面、任务书等一堆乱七八糟的文件,使得整个从论文写作到论文打印变成了一个 one-stage 的过程,不需要再从其它地方导出封面、任务书等一堆乱七八糟的文件、外文翻译及原文(如果能得到原文的 $\LaTeX$ 源码的话,可以很方便地使得整篇论文的排版格式完全一致,在arXiv上很容易找到 $\LaTeX$ 源码)再拼凑到生成的 PDF 文件里面。

├── bibliography.bib
├── figures
│   └── some_figures.pdf
├── pages
│   ├── ch00.0-cover.tex               # 封面
│   ├── ch00.1-task.tex                # 任务书
│   ├── ch00.2-review.tex              # 考核评议书 & 答辩结果
│   ├── ch00.3-abstract.tex            # 摘要
│   ├── ch00.4-denotation.tex          # 符号表
│   ├── ch01-introduction.tex          # 引言
│   ├── ch02-theory.tex                # 理论
│   ├── ch03-algorithm.tex             # 算法
│   ├── ch04-experiment.tex            # 实验
│   ├── ch05-conclusion.tex            # 结论
│   ├── ch06-acknowledgements.tex      # 致谢
│   ├── ch07-appendice.tex             # 附录 & 外文翻译 & 外文原文
│   ├── ch99.0-topicreview.tex         # 选题审核表
│   ├── ch99.1-interimchecklist.tex    # 中期检查表
│   └── ch99.2-progresschecklist.tex   # 进度表
├── thesis.pdf
├── thesis.tex
└── xjtuthesis.cls

编译文档

在安装好 TeX Live 并且确定能够通过系统环境变量找到 xelatex 命令的情况下,LaTeX Workshop 插件也能够找到编译器,那么像上述那样配置好插件后,在 VSCode 里面按 Ctrl + Shift + p 输入类似 labui 之类的关键词就能模糊搜索到 LaTeX Workshop: Build with recipe 命令,回车之后再选择 xelatex 即可完成一次快速编译(选择 xelatex -> biber -> xelatex*2 是完成一次完整的编译,包括交叉引用等)。

如果倾向于使用命令行(推荐第一次编译以及在排查编译错误的时候使用命令行编译,方便查看编译错误信息),那么一次快速编译:

xelatex thesis

完整编译:

xelatex thesis && biber thesis && xelatex thesis && xelatex thesis

不出意外的话,不管用以上任何一种方式编译都会报错,原因是没有找到字体。下面先讲一下怎么修改字体。

修改字体

学校规定的英文字体是 Times New Roman,中文是宋体。Times New Roman 貌似是商业字体,宋体没说是什么宋体,不过在 Windows 的语境下指的应该是中易宋体,在官方的 Word 模板上就是这样,而中易宋体也是 Windows 系统附带的,没有正版的系统按理说是不能合法使用的。我认为这样的规定很不负责任,因为在学校没有向我们提供版权的情况下这不就增加学生负担或者鼓励盗版?好在学校对于这个字体要求并没有严格执行(其实主要还是看指导老师找不找茬,大部分老师是看不出来的),所以我全部使用了开源 / 自由版权的字体。

xjtuthesis.cls 文件的第 262 - 288 行附近是对论文字体的定义,该位置预定义了几个选择:truefontsourcefontnofont 以及什么都不设置。设置的方式是在 thesis.tex 文件开头 \documentclass 后面的选项中添加或删除。

truefont 表示将使用中易宋体(SimSum)、中易黑体(SimHei)、华文中宋(STZhongsong)、楷体(KaiTi)、Times New Roman 字体。sourcefont 表示思源宋体、思源黑体、FandolKai、Nimbus Roman No9 L。若没有任何设置(也没有设置 nofont),那么将默认使用 FandolSong、FandolHei、FandolKai、Nimbus Roman No9 L。(这里有一份中文开源字体列表,可以挑选自己喜欢的字体。)

若设置之后出现编译错误,那么要么检查相应的字体是否正确安装(以及字体的实际名称是不是与模板中声明的一致),要么将设置改为 nofont,然后在正文(thesis.tex)中进行如下设置。

\setmainfont[Ligatures=TeX]{Nimbus Roman No9 L}
\setCJKmainfont[BoldFont=思源宋体 Bold, ItalicFont=FandolKai]{Source Han Serif SC}

开始书写

实际上我更建议在现有的项目上修改而不是把模板放到一个新项目中从头开始书写。在有模板的前提下,使用 $\LaTeX$ 书写更像是在做「填空」,只需要把自己的内容填入正确的位置即可,无需关心任何排版的琐事,而一个现有的项目就能很清楚地告诉你每个空应该在哪里填。

整个论文的写作过程几乎只用修改 pages 目录下的文件。例如摘要的写作方式就是把 ch00.3-abstract.tex 文件中的空全部填上即可。各章节的写作方式就如同在写其它 $\LaTeX$ 文件一样,只管写就好了。

填写信息

此模板的一个优点就是集成了各种各样的表格,要在空白表格的下划线上填写内容,只需打开 pages 目录下相应的 tex 文件,再相应地写上要填的内容。下面是填写封面的例子:

% 标题,中文
\ctitle{这是完整的标题}
\covertitlefirst{这是标题的第一行}
\covertitlesecond{这是标题的第二行,如果标题无需分行则可留空}
\cschool{xx学院}
\cactualinstitution{西安交通大学}
\cmajor{xx专业}
\cclass{计算机44}
\cyear{\the\year}
\cmonth{\the\month}

% 作者,中文
\cauthor{作者姓名}
\stuid{作者学号}

% 导师姓名,中文
\csupervisor{老\quad 师}

插入图片

简单的插入图片示例如下:

\begin{figure}[!ht]
    \centering
    \includegraphics[width=0.7\textwidth]{vis3}
    \caption{测试结果可视化}
    \label{fig:testvis}
\end{figure}

!ht 表示强制安排图片的位置为当前位置(若该页空间不足,则强制放在下页的顶部)。\centering 表示水平居中。vis3 是图片的文件名,扩展名可以省略,支持 pdfsvgpngjpg 等常见格式。\caption 是图片的标题,\label 是图片的标签,用于交叉引用。

插入表格

下面是插入表格的示例:

\begin{table}[!ht]
    \centering
    \caption{学习后选择的部署方案}
    \label{tab:rlresult}
    \begin{tabularx}{\textwidth}{ccc}
    \toprule
    方案                & 频次 & 占比~(\%)  \\ \midrule
    (1, 2, 7, 10, 14)  & 190  & 65.97     \\
    (1, 2, 7, 10, 13)  & 78   & 27.08     \\
    (1, 2, 7, 9, 14)   & 18   & 6.15      \\
    (1, 3, 7, 10, 14)  & 1    & 0.35      \\
    (0, 2, 7, 10, 14)  & 1    & 0.35      \\ \bottomrule
    \end{tabularx}
\end{table}

推荐一个非常好用的制作 $\LaTeX$ 表格的网站,所见即所得,最后自动生成 $\LaTeX$ 代码。

插入算法

插入算法用到了 algorithmicx 宏包,使用方法也很简单,就是记得所有的 keyword 都是形如 \For ... \EndFor 这样的就 OK 了。

\begin{algorithm}[!htb]
    \caption{Q-Learning 算法求当前状态的长期价值}
    \label{alg:qlearning}
    \begin{algorithmic}[1]
        \Require 状态集合$S$、动作集合$A$、生命周期数$N$、学习率$\alpha$、远见性$\gamma$
        \Ensure 长期价值矩阵$Q$
        \Function {QLearning}{$S, A, N, \alpha, \gamma$}
            \State 随机初始化长期价值矩阵$Q$
            \For{$i=0\to N$}
                \State $t\gets1$
                \Repeat
                    \State $t\gets  t+1$
                \Until{$\boldsymbol{s}^{(t)}=\boldsymbol{s}^{(0)}$}
            \EndFor
            \State\Return $Q$
        \EndFunction
    \end{algorithmic}
\end{algorithm}

参考文献

首先需要将要引用的文献的 BibTeX 代码加入 bibliography.bib 文件中,BibTeX 代码可以在 Google Scholar 网站上找到。

随意搜索一篇文章,在每一条搜索结果下方会有一个 Cite 按钮:

在弹出的窗口中点击「BibTeX」:

将弹出窗口中的代码加入 bibliography.bib 文件中:

引用的方式为 \cite{shen2018performance}

注意引用之后如果使用快速编译是不会显示结果的,因为 bib 文件需要使用 biber 命令转化成 bbl 文件,之后 tex 文件才能找到相应的文献序号。因此需要一次完整的编译。

4. 踩过的坑

TeX Live 2018

  • 如果使用 TeX Live 2018 版本,不出意外应该会报这样的错误:

    ! Package xkeyval Error: `gbnamefmt' undefined in families `blx@opt@pre'.
    
    See the xkeyval package documentation for explanation.
    Type  H <return>  for immediate help.
    ...
    
    l.13809 \blx@processoptions
    

    原因是 biblatex-gb7714-2015 宏包不够新,所以需要到项目网站上下载最新的 Release 文件,替换掉以下目录中的四个文件(gb7714-2015.bbxgb7714-2015.cbxgb7714-2015ay.bbxgb7714-2015ay.cbx):

    $TEX_HOME/texmf-dist/tex/latex/biblatex-gb7714-2015
    

    $TEX_HOME 表示 TeX Live 2018 的安装目录。

任务书参考文献下划线

  • 这个需求纯属指导老师找茬,也许其没想过要想在 biblatex 自动生成的参考文献上加入下划线是多么地困难,我曾到StackExchange提问过,大佬们表示无能为力。于是我只能使用最粗暴的方法:用 Tikz 宏包直接画线。如果你的论文项目是在我的项目上直接修改的,请务必关掉 thesis.tex 文件前面的 taskunderline 选项。如果你也想画上下划线,那么请自行修改 xjtuthesis.cls 文件的 879 -- 927 行。

  • 其实画下划线的需求使用 bibtex 而不是 biblatex 是相对容易实现的,不过由于我想要在一个文档里面加入两个相互独立的参考文献(任务书中的和正式论文中的),于是便使用了 biblatex 而非 bibtex。(实际上使用 bibtex 大概也能实现双参考文献,不过作为一个有新技术绝不使用旧技术的人,我还是选择了 biblatex。)

字体加粗导致字符缺失

  • 由于 xelatex一个 bug,在使用非 OTF 字体且使用了「伪粗体」后,生成的 PDF 文件看起来没什么异常,实际上是无法从中复制文本的。这个 bug 最直接的影响是最后提交上去进行字数统计就会少很多字(最简单的 bug 是否重现的判定方式是用 Word 打开 PDF 文件,如果有大量字符缺失就说明触发 bug 了)。

  • 这个问题可以通过将字体换成 OTF 字体(如思源宋体、FandolSong)来解决,也可以通过避免使用伪粗体来解决(例如使用华文中宋来代替自动生成的伪粗体)。我的项目中的三种字体设置方案(中易宋体、思源宋体、FandolSong)都用上述方式避开了这个 bug,如果你自定义了其它字体,最好检查一下是否触发了这个 bug。