在宏中使用计数器和 \ifthen:有什么问题?

在宏中使用计数器和 \ifthen:有什么问题?

我有 (制成(实际上)一张熊前爪印的图形,我想用它在章节末尾和其他几个地方作为花饰标记。完成图像后,我创建了一个镜像版本,这样我就有了右爪和左爪版本,最初是为了看看哪个看起来更好。然后我想到每次出现时交替使用这两种版本会很有趣,让我的熊在我的书中走来走去(我知道,用它的前爪;我们不要有这个想法远的)。

对于重复的内联图形,我使用\newcommand*创建一个“迷你宏”,它只执行\includegraphic特定大小的给定图像的 ,主要包含在其他宏中;在这种情况下,两者被称为\lbpimage\rbpimage,并且它们本身工作正常。

现在我需要一个中间宏来在两者之间切换。我故意的是一个\newcommand,\bearpaw,它将创建另一个命令(通过\renewcommand*),名为\bpaw,然后运行它。引用名为爪子并使用\ifthen\bpaw其目的是运行其中一个“微型宏”,然后重置爪子从 0 到 1 或反之亦然。

当然,为了能够\renewcommand*使用命令名需要预先存在,因此在\newcommand*\bearpaw\bpaw使用虚拟版本进行初始化之前,\newcommand*\bpaw{foo}因此:

\documentclass[letterpaper,twoside,12pt,final]{memoir}

\usepackage{graphicx}
\usepackage{ifthen}

\newcommand*{\lbpimage}%
  {\includegraphics[width=0.548in]{lbearpaw}}

\newcommand*{\rbpimage}%
  {\includegraphics[width=0.548in]{rbearpaw}}

\newcounter{paw}%     Preset to zero by default.

\newcommand*\bpaw%
  {foo}

\newcommand*\bearpaw%
  {\ifthenelse{\equal{paw}{0}}%
    {\renewcommand*\bpaw%
      {\lbpimage%
      \setcounter{paw}{1}}}{}%
  \ifthenelse{\equal{paw}{1}}%
    {\renewcommand*\bpaw%
      {\rbpimage%
      \setcounter{paw}{0}}}{}%
  \bpaw}

\begin{document}

\bearpaw \bearpaw \bearpaw

\end{document}

我得到的是:

福福福

显然,我的条件没有按预期发挥作用。我做错了什么?

答案1

命令\ifthenelse\equal可以被替换\ifnum以使宏成功工作。

\newcommand*\bearpaw%
  {\ifnum\thepaw=0%
    \renewcommand*\bpaw%
      {\lbpimage%
      \setcounter{paw}{1}}\fi%
  \ifnum\thepaw=1%
    \renewcommand*\bpaw%
      {\rbpimage%
      \setcounter{paw}{0}}\fi%
  \bpaw}

使用这个,你将不需要包ifthen

答案2

\equal宏比较字符串(文本)而不是整数。为此,您需要使用<=或 ,>\ifthenelse{\value{paw}=0}

\ifthenelse用一个宏来简化这个

\newcommand*\bearpaw{%
  \ifthenelse{\value{paw}=0}{%
    \renewcommand*\bpaw{\lbpimage\setcounter{paw}{1}}%
  }{%
    \renewcommand*\bpaw{\rbpimage\setcounter{paw}{0}}%
  }%
  \bpaw}

但是由于您只在两种状态之间切换,因此不需要计数器。您可以改用布尔值。我还删除了宏\paw,您可以直接执行内容。

我已经使用demographicx包,因为我们没有图像,并且还改变了图像的大小以清楚地显示图像是交替的。

xifthen取代旧的ifthen已被使用,因为它改善了其他领域。

[x]ifthen\ifthenelse和宏\boolean在内部使用相同的工具,\newif但保持嵌套安全。

如果你想在组中使用它,但希望切换成为全局事务,你要么需要使用 plainTeX\global\pawrighttrue\global\pawrightfalseetoolbox包提供了更简单的界面并且其宏可以在前面添加\global

手册和etoolbox 包中的 \newbool 和 \newtoggle 之间的区别

代码

\documentclass[letterpaper,twoside,12pt,final]{memoir}

\usepackage[demo]{graphicx}
\usepackage{etoolbox}

\newcommand*{\lbpimage}%
  {\includegraphics[width=0.548in]{lbearpaw}}

\newcommand*{\rbpimage}%
  {\includegraphics[width=1.548in]{rbearpaw}}

\newtoggle{pawright}

\newcommand*\bearpaw{%
  \iftoggle{pawright}
    {\rbpimage\global\togglefalse{pawright}}
    {\lbpimage\global\toggletrue{pawright}}%
}
\newcommand*{\chapend}{\par\smallskip\begin{center}\bearpaw\end{center}}

\begin{document}
\bearpaw \quad \bearpaw \quad \bearpaw

\chapend
\chapend
\chapend
\chapend
\end{document}

输出

在此处输入图片描述

答案3

\newif通过提供布尔开关/条件的老式方法可以轻松实现来回切换:

在此处输入图片描述

\documentclass{article}

\usepackage{graphicx}% http://ctan.org/pkg/graphicx
\newif\ifswitchbearpaw

\newcommand*{\lbpimage}%
  {\includegraphics[width=0.548in]{example-image-a}}

\newcommand*{\rbpimage}%
  {\includegraphics[width=0.548in]{example-image-b}}

\newcounter{paw}%     Preset to zero by default.

\newcommand*\bpaw%
  {foo}

\newcommand*\bearpaw%
  {\ifswitchbearpaw\lbpimage\switchbearpawfalse\else\rbpimage\switchbearpawtrue\fi}

\begin{document}

\bearpaw \bearpaw \bearpaw

\end{document}

因为你只是切换,无需进行反测试。etoolbox提供了类似的方法来触发/翻转(布尔)开关。


更安全的条件宏方法\bearpaw

\makeatletter
\newcommand*\bearpaw{%
  \ifswitchbearpaw\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi%
    {\switchbearpawfalse\lbpimage}{\switchbearpawtrue‌​\rbpimage}}
\makeatother 

相关内容