![IfSubStr 中的参数扩展](https://linux22.com/image/244265/IfSubStr%20%E4%B8%AD%E7%9A%84%E5%8F%82%E6%95%B0%E6%89%A9%E5%B1%95.png)
编辑:简化问题
我怎样才能使下面的代码打印“是”?
\IfSubStr{\textbf{AAA}}{AAA}{Yes}{No}
完整问题
我正在玩xstring
,IfSubStr
但我不太明白扩展是如何工作的。
这是一个很大程度上简化的 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。使用命令exploregroup
和noexpandarg
。
\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}
答案3
xstring
在阅读了手册中的相关部分后,我意识到使用IfSubStr*
效果很好=)