![什么导致 \IfFileExists 内部的循环失败?](https://linux22.com/image/252142/%E4%BB%80%E4%B9%88%E5%AF%BC%E8%87%B4%20%5CIfFileExists%20%E5%86%85%E9%83%A8%E7%9A%84%E5%BE%AA%E7%8E%AF%E5%A4%B1%E8%B4%A5%EF%BC%9F.png)
以下 MWE 是简化版本我的项目。但它已经足够完整,足以产生问题。如果你禁用(注释)循环部分,编译就会成功。否则,你将得到编译错误。是什么导致内部循环\IfFileExists
失败?
\documentclass{book}
\input{repeat}
\def\Foo{%
\IfFileExists{\jobname.tex}{%
\repeat\for{x}\by{0}%
\until{\ifnum\x>10}%
\do{\advance\x by 1}%
}%
{%
File not found.
}%
}
\begin{document}
\Foo
\end{document}
This is pdfTeX, Version 3.1415926-2.3-1.40.12 (Web2C 2011)
restricted \write18 enabled.
entering extended mode
(./dj.tex
LaTeX2e <2011/06/27>
Babel <v3.8m> and hyphenation patterns for english, dumylang, nohyphenation, ge
rman-x-2011-07-01, ngerman-x-2011-07-01, afrikaans, ancientgreek, ibycus, arabi
c, armenian, basque, bulgarian, catalan, pinyin, coptic, croatian, czech, danis
h, dutch, ukenglish, usenglishmax, esperanto, estonian, ethiopic, farsi, finnis
h, french, friulan, galician, german, ngerman, swissgerman, monogreek, greek, h
ungarian, icelandic, assamese, bengali, gujarati, hindi, kannada, malayalam, ma
rathi, oriya, panjabi, tamil, telugu, indonesian, interlingua, irish, italian,
kurmanji, lao, latin, latvian, lithuanian, mongolian, mongolianlmc, bokmal, nyn
orsk, polish, portuguese, romanian, romansh, russian, sanskrit, serbian, serbia
nc, slovak, slovenian, spanish, swedish, turkish, turkmen, ukrainian, uppersorb
ian, welsh, loaded.
(c:/texlive/2011/texmf-dist/tex/latex/base/book.cls
Document Class: book 2007/10/19 v1.4h Standard LaTeX document class
(c:/texlive/2011/texmf-dist/tex/latex/base/bk10.clo))
(c:/texlive/2011/texmf-dist/tex/generic/eijkhout/repeat.tex
Loading loop macro, version 0.93a) (./dj.aux))
! Incomplete \ifeof; all text was ignored after line 16.
<inserted text>
\fi
<*> dj.tex
?
! Emergency stop.
<inserted text>
\fi
<*> dj.tex
! ==> Fatal error occurred, no output PDF file produced!
Transcript written on dj.log.
答案1
正如@Ahmed 指出的那样,repeat.tex 宏与 latex、Plain 和 LaTeX 循环不兼容,\repeat
因此重新定义它会破坏这些。(也许最明显的是\multicolumn
依赖于此。
与大多数 LaTeX 条件命令不同,true 和 false 块实际上是由里面一个原始\if.... \else ....\fi
构造(而不仅仅是使用条件来执行\@firstoftwo
或\@secondoftwo
)。这意味着 true 和 false 分支中的代码都需要在\if.. \fi
标记方面保持良好的平衡。但是您的代码有一个不匹配的ifnum
,如果由 repeat 宏执行,这不会有问题,但意味着代码不能被跳过,因此您引用了错误。
如果你真的想要使用这样的构造,您必须将循环移出真/假参数,如下所示,其中\next
定义为不执行任何操作或根据测试吃掉循环,但如上所述,不建议在乳胶中使用此宏。
\def\Foo{%
\IfFileExists{\jobname.tjex}{%
\let\next\relax
}%
{%
File not found.
\def\next####1\do####2{}
}%
\next\repeat\for{x}\by{0}%
\until{\ifnum\x>10}%
\do{\advance\x by 1}%
}
答案2
解决方案基于tohecz 的评论:
\documentclass{book}
\input{repeat}
\newif\ifFE
\def\Foo{%
\IfFileExists{\jobname.tex}{\FEtrue}{\FEfalse}
\ifFE
\repeat\for{x}\by{0}%
\until{\ifnum\x>10}%
\do{\the\x\advance\x by 1}%
\else
File not found.
\fi
}
\begin{document}
\Foo
\end{document}