IfSubStr 中的参数扩展

IfSubStr 中的参数扩展

编辑:简化问题

我怎样才能使下面的代码打印“是”?

\IfSubStr{\textbf{AAA}}{AAA}{Yes}{No}

完整问题

我正在玩xstringIfSubStr但我不太明白扩展是如何工作的。

这是一个很大程度上简化的 MWE,展示了我的问题:

\documentclass{minimal}

\usepackage{xstring}

\newcommand{\correctanswer}{}
\newcommand{\mytext}[1]{
    Text :
    \noexpandarg
    \IfSubStr{#1}{\correctanswer}{
        \textbf{\boldmath #1}
    }{
        #1
    }
}
\newcommand{\mymathtext}[1]{\mytext{\ensuremath{#1}}}

\begin{document}
    \mytext{Foo} \mytext{Bar\correctanswer} \mymathtext{\frac{1}{2}} \mymathtext{\frac{1}{4}\correctanswer}
\end{document}

代码的工作原理如下:首先定义一个\correctanswer扩展为空字符串的宏,然后强调(通过粗体排版)包含该宏的文本。

我使用xstring's\noexpandarg来防止\correctanswer过早扩展,但是当参数文本已经传递给另一个命令时,这不起作用,例如\ensuremath尽管Bar以粗体字体显示,但\frac{1}{4}事实并非如此。

我怎样才能\frac{1}{4}将其排版为粗体?

PS:我不太明白扩展是如何工作的。我读过这个网站上的很多帖子,但我仍然找不到这个特定问题的正确解决方案。因此,我没有把我所做的无数次徒劳无功的尝试都写出来,希望有人能给我一个清晰的解释 :)

答案1

只是不要使用\ensuremath:它增加了一个分组级别,使得无法\IfSubStr找到\correctanswer;事实上测试

\IfSubStr{1{2}3}{2}{true}{false}

返回“false”。因此写

\newcommand{\mymathtext}[1]{\mytext{$#1$}}

请注意,您的代码添加了大量虚假空格:

\newcommand{\mytext}[1]{%
    Text :
    \noexpandarg
    \IfSubStr{#1}{\correctanswer}{%
        \textbf{\boldmath #1}%
    }{%
        #1%
    }
}

我会将其重写为

\newcommand{\mytext}[1]{%
    Text : % be sure we want a space
    \noexpandarg
    \IfSubStr{#1}{\correctanswer}
      {\textbf{\boldmath #1}}
      {#1}%
}

但可能最好的办法是定义一个 *-variant:

\makeatletter
\newcommand{\mytext}{\@ifstar\mytext@s\mytext@n}
\newcommand{\mytext@s}[1]{\textbf{\boldmath #1}}
\newcommand{\mytext@n}[1]{#1}
\makeatother

并说\mytext{Yes}\mytext*{No}(正确答案);对于数学,只需添加$\mytext{$\frac{1}{2}$}\mytext*{$\frac{1}{4}$}

这是用 *-variant 定义命令的标准方法;因为我们需要使用@命令,所以代码必须括在\makeatletter和之间\makeatother

命令\mytext被定义为用 来查看其后面的内容\@ifstar;如果后面*跟着 ,则执行\mytext@s,否则\mytext@n,我们正常定义下一个:\mytext@s{x}执行\textbf{\boldmath x},而\mytext@n{x}只是执行x。事实上,TeX 将用 替换\mytext*\mytext@s因此它接下来会看到传递给此命令的参数,如果没有 ,情况也是如此*

为了安排事情\ifsolution,你可以说

\newif\ifsolution
\makeatletter
\newcommand{\mytext}{\@ifstar\mytext@s\mytext@n}
\newcommand{\mytext@s}[1]{%
  \begingroup
  \ifsolution\bfseries\boldmath\fi
  #1%
  \endgroup}
\newcommand{\mytext@s}[1]{#1}
\makeatletter

这样只有当设置为 true\bfseries\boldmath时才会发出命令。\ifsolution

更简单的版本

更简单的定义可能是:

\usepackage{xparse}
\newif\ifsolution

\NewDocumentCommand{\answer}{st{+}m}
  {\begingroup
   \ifsolution\IfBooleanT{#1}{\bfseries\boldmath}\fi
   \IfBooleanT{#2}{$}#3\IfBooleanT{#2}{$}%
   \endgroup}

\answer{Yes} \answer*{No}

\answer+{\frac{1}{2}} \answer*+{\frac{1}{4}}

\solutiontrue

\answer{Yes} \answer*{No}

\answer+{\frac{1}{2}} \answer*+{\frac{1}{4}}

你会得到

是 否
1/2 1/4

1/21/4

当然,在数学模式下使用分数。如您所见,+ 的存在意味着一个公式。

编辑

假设你有一个\answerformat格式化答案的宏,比如说

\newcommand{\answerformat}[1]{\mbox{\checkbox\qquad{#1}}\\}

\checkbox打印一个框),你可以使用如下语法

\answers{Yes}*{No}+{\frac{1}{2}}+{\frac{1}{4}}

甚至

\answers[3]{Yes}{No}*+{\frac{1}{2}}

也就是说,在正确答案前面加上*,在数学答案前面加上+;可选参数告诉您有多少个选择(默认为 4):

\usepackage{xparse}
\NewDocumentCommand{\answer}{st{+}m}
  {\answerformat{%
     \ifsolution\IfBooleanT{#1}{\bfseries\boldmath}\fi
     \IfBooleanT{#2}{$}#3\IfBooleanT{#2}{$}}
   \ifnum\value{anscount}<\answernumber
     \stepcounter{anscount}\expandafter\answer
   \fi}
\NewDocumentCommand{\answers}{O{4}}
  {\setcounter{anscount}{1}\chardef\answernumber=#1\relax
   \answer}
\newcounter{anscount}

答案2

我认为您也可以使用 xstring。使用命令exploregroupnoexpandarg

\documentclass{minimal}

\usepackage{xstring}

\newcommand{\correctanswer}{}
\newcommand{\mytext}[1]{
    Text :
    \noexpandarg
    \exploregroups
    \IfSubStr{#1}{\correctanswer}{
        \textbf{\boldmath #1}
    }{%
        #1
    }
}
\newcommand{\mymathtext}[1]{\mytext{\ensuremath{#1}}}

\begin{document}
    \mytext{Foo} \mytext{Bar\correctanswer} \mymathtext{\frac{1}{2}} \mymathtext{\frac{1}{4}\correctanswer}
\end{document}

enter image description here

答案3

xstring在阅读了手册中的相关部分后,我意识到使用IfSubStr*效果很好=)

相关内容