使用 Plain 中的 \ifcase 宏重置计数器

使用 Plain 中的 \ifcase 宏重置计数器

我无法使用 Plain TeX 中的宏将计数器重置为零。

此代码使用\ifcase计数器animalnum输出动物名称列表中的一个,每次调用时计数器都会递增,以便下一次调用将产生列表中的后续名称。如果调用次数超过最大次数,则会输出错误消息。

该命令\resetanimalnum应该将计数器重新设置为零并重新开始列表,但由于某种原因,它不能按预期工作。

计数器为何会出现这种情况?我该如何修复它?

\newcount\animalnum

\def\nextanimal{%                                                                                                                                                                              
  \ifcase\animalnum%                                                                                                                                                                           
    \animalI\or
    \animalII\or
    \animalIII%                                                                                                                                                                                
  \fi%                                                                                                                                                                                         
  \ifnum\animalnum > 2
    \exclaim%                                                                                                                                                                                  
  \fi%                                                                                                                                                                                         
  \advance\animalnum by 1%                                                                                                                                                                     
}

\def\resetanimalnum{\animalnum=0}

\def\animalI   {Lions}
\def\animalII  {Tigers}
\def\animalIII {Bears}
\def\exclaim   {Oh my!}

\nextanimal\ \nextanimal\ \nextanimal\ \nextanimal

\resetanimalnum\nextanimal\ \nextanimal

\bye

在此处输入图片描述

答案1

主要原因是%1 后面的错误使用导致 1 无法终止,以及 0 后面缺少空格。在某些情况下,您可以用 终止数字,\relax但这会在令牌流中留下\relax,这并不总是可取的,空格会被吸收作为数字的一部分。

\newcount\animalnum

\def\nextanimal{%
  \ifcase\animalnum
    \animalI\or
    \animalII\or
    \animalIII
  \fi
  \ifnum\animalnum > 2
    \exclaim
  \fi
  \advance\animalnum by 1
}

\def\resetanimalnum{\animalnum=0 }

\def\animalI   {Lions}
\def\animalII  {Tigers}
\def\animalIII {Bears}
\def\exclaim   {Oh my!}

\nextanimal\ \nextanimal\ \nextanimal\ \nextanimal

\resetanimalnum\nextanimal\ \nextanimal

\bye

答案2

书中(以某种方式)提到了这一点TeX by Topic(第 66 页)

在进行反向评估的情况下,TeX 可能会扩展得太远,并会尝试找到一些非数字的东西,也就是说,它可能会吸收并扩展下一个语句,\nextanimal这是一个错误。

如果\relax插入了,则可以停止。(\relax该页面上没有提到,但可以使用然后停止扩展\relax

一次性解决方案是在\resetanimalnum和下一次调用之间放置一个换行符\nextanimal,但这可能会变得繁琐。

\newcount\animalnum

\def\nextanimal{%
    \ifcase\animalnum%                                                                                                                                      
    \animalI\or
    \animalII\or
    \animalIII%                                                                                                                                             
    \fi%
    \ifnum\animalnum > 2
    \exclaim%
    \fi%
    \advance\animalnum by 1%
}

\def\resetanimalnum{\animalnum=0\relax}%

\def\animalI   {Lions}
\def\animalII  {Tigers}
\def\animalIII {Bears}
\def\exclaim   {Oh my!}

\nextanimal\ \nextanimal\ \nextanimal\ \nextanimal

\resetanimalnum\nextanimal\ \nextanimal

\bye

在此处输入图片描述

相关内容