我在一个非常庞大的项目中看到了来自 pdflatex 的以下错误消息:
(see the transcript file for additional information)pdfTeX warning (dest): name
{lstnumber.-14.11} has been referenced but does not exist, replaced by a fixed
one
pdfTeX warning (dest): name{lstnumber.-18.22} has been referenced but does not
exist, replaced by a fixed one
pdfTeX warning (dest): name{lstnumber.-9.40} has been referenced but does not e
xist, replaced by a fixed one
pdfTeX warning (dest): name{lstnumber.-4.3} has been referenced but does not ex
ist, replaced by a fixed one
我的主文件顶部如下所示:
\documentclass[ebook,10pt,oneside,final]{memoir}
\usepackage{microtype}
% support for code listings
\usepackage[final]{listings}
\include{autodedent}
\lstset{
basicstyle=\ttfamily\footnotesize,
numberstyle=\footnotesize,
breaklines=true,
numbers=left,
firstnumber=1,
rangeprefix=//,
includerangemarker=false
}
% support for indexing
\usepackage{makeidx}
\makeindex
% make _ a non-special character
\usepackage{underscore}
% support for cross-references
\usepackage{hyperref}
% \newcommand{\href}[2]{#2}
% fix spacing in \tableofcontents
\renewcommand\partnumberline[1]{#1\hspace{1em}}
% custom commands for use in the text of the book itself
\newcommand{\newterm}[1]{\textit{#1}}
\newcommand{\code}[1]{\mbox{\lstinline[basicstyle=\ttfamily]$#1$}}
\newcommand{\slurl}[1]{\href{https://#1}{\textsl{#1}}}
\newcommand{\codeblock}[2]{\label{foo#1#2}\hspace{1em}\lstinputlisting[linerange=ex#2-dex#2,autodedent]{examples-ch#1.cc}}
\newcommand{\codeblockref}[2]{\pageref{foo#1#2}}
\newcommand{\Csharp}{C\#}
\begin{document}
\frontmatter
\include{preface}
\tableofcontents
\mainmatter
% ...and so on...
\codeblock
来自正文的一个例子:
Let's write a function to multiply each of the elements
in an array by 2.
\codeblock{1}{1}
Our function \code{double_each_element} works \emph{only} with objects of type
\code{array_of_int}...
例如\codeblockref
:
Compare this version of the code to the version on page
\codeblockref{1}{1}.
不幸的是,如果你把这些代码片段放在一个测试文件中并运行pdflatex test.tex; pdflatex test.tex
— 它会运行良好!(除了数字“1”上的超链接实际上指向目录,而不是第 1 页。)但是当我在多章的规模上做同样的事情时,我得到了关于lstnumber.-14.11
此问题顶部所见的错误消息。
我确实发现这lstnumber.-<some number>
是由包自动生成的标签的格式,因此我认为这是和listings
之间的一些不良交互。但究竟出了什么问题,我该怎么做才能解决它?listings
hyperref
\hspace{1em}
我的宏\codeblock
是我天真的尝试解决所描述的错误这里,以防这是问题所在。
答案1
以下是我认为应该如何做的示例:
在\codeblock
命令\label
应用之前\lstinputlisting
,即在listings
计数器增加以允许引用之前\refstepcounter
——使用\label
之前\refstepcounter
是一个非常常见的错误,因此,写入的交叉引用信息\label
来自\refstepcounter
之前使用的潜在信息,该信息可能与等计数器结合使用section
,因此信息是错误的,并且超锚点坐标取自之前较旧的锚点实例。这样,链接指向错误的位置。
事实上,\lstinputlisting
有一个label=
指定标签名称的选项。
以下是非 MWE 给出的非常简化的形式,但有效。
\documentclass[ebook,10pt,oneside,final]{memoir}
\usepackage{microtype}
% support for code listings
\begin{filecontents}{examplehelloworld.c}
#include<stdio.h>
int main(int argc,char **argv)
{
printf("Hello World!\n");
return(0);
}
\end{filecontents}
\usepackage[final]{listings}
%\include{autodedent}
\lstset{
basicstyle=\ttfamily\footnotesize,
numberstyle=\footnotesize,
breaklines=true,
numbers=left,
firstnumber=1,
rangeprefix=//,
includerangemarker=false
}
% support for indexing
\usepackage{makeidx}
\makeindex
% make _ a non-special character
\usepackage{underscore}
% support for cross-references
\usepackage{hyperref}
% \newcommand{\href}[2]{#2}
% fix spacing in \tableofcontents
\renewcommand\partnumberline[1]{#1\hspace{1em}}
% custom commands for use in the text of the book itself
\newcommand{\newterm}[1]{\textit{#1}}
\newcommand{\code}[1]{\mbox{\lstinline[basicstyle=\ttfamily]$#1$}}
\newcommand{\slurl}[1]{\href{https://#1}{\textsl{#1}}}
\newcommand{\codeblock}[2]{\hspace{1em}\lstinputlisting[language={C},label={lst:#1-#2}]{examplehelloworld.c}}
\newcommand{\codeblockref}[2]{\pageref{lst:#1-#2}}
\newcommand{\Csharp}{C\#}
\usepackage{blindtext}
\begin{document}
\frontmatter
%\include{preface}
\tableofcontents
\mainmatter
\blindtext[3]
Reference: \codeblockref{1}{4}
\blindtext[5]
\codeblock{1}{4}
\end{document}
答案2
在发布这个问题的过程中,我偶然发现了答案!(虽然我不明白为什么有用...)
如果您将这些代码片段放在一个测试文件中并运行
pdflatex test.tex; pdflatex test.tex
— 它会运行良好!(除了数字“1”上的超链接实际上指向目录,而不是第 1 页。)
当它抛出错误时,我并不惊讶于超链接指向了错误的地方。然而,由于测试用例减少,我感到很困惑。所以我去阅读了那问题,发现我想要的是\phantomsection
,像这样:
\newcommand{\codeblock}[2]{\phantomsection\label{lst:#1-#2}\lstinputlisting[linerange=ex#2-dex#2,autodedent]{examples-ch#1.cc}}
\newcommand{\codeblockref}[2]{\pageref{lst:#1-#2}}
请注意,我的 cargo-cult\hspace{1em}
不再需要(据我所知);并且我能够放回lst:#1-#2
我在foo#1#2
尝试减少测试用例时替换的特殊字符。
...神奇的是,我的大型项目突然编译成功了!不再有神秘的错误消息。所有超链接都转到正确的页面,并显示正确的正文。
我不知道为什么省略\phantomsection
会造成如此大的破坏,但放进去之后,一切都解决了!