什么导致 \IfFileExists 内部的循环失败?

什么导致 \IfFileExists 内部的循环失败?

以下 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}

相关内容