这是一些代码。
\documentclass{article}
\usepackage{xstring}
\begin{document}
\def\xloop#1{%
\ifx\relax#1
\else
**\IFInteger{#1}{first integer is here.}** % need to be modified
\expandafter\xloop%
\fi}
\def\test#1{\xloop#1\relax}
\test{abc3de5f}
\end{document}
5 个回答
5
此答案依赖于以下事实:数字 0-9 在 ASCII 表上按顺序位于第 48 和第 57 个位置之间(含)。紧接在 之前的位置0
包含/
,而紧接在 之后的位置9
包含:
。
我们利用 TeX 语法,即符号前的重音符(反引号)会生成符号的槽号(ASCII 值)。因此,我设置了两个\ifnum
测试…第一个测试查看当前符号的槽是否超出了 的槽/
,第二个测试检查当前符号的槽是否在 的槽之前:
。
如果这两个条件都为真,则符号的槽位属于整数槽位范围。否则,它不在该范围。
\documentclass{article}
\def\xloop#1{%
\ifx\relax#1
\else
%
\ifnum`#1>`/
\ifnum`#1<`:
\def\next{#1 is first integer\\}%
\else
\def\next{#1 is not an integer\\\expandafter\xloop}
\fi
\else
\def\next{#1 is not an integer\\\expandafter\xloop}
\fi
\next%
\fi}
\def\test#1{\xloop#1\relax}
\begin{document}
\test{abc3de5f}
\end{document}
3
-
1你能解释一下这是什么意思吗?
– -
这可以检查变量名是否包含数字。
– -
@XCN 我已根据 cfr 的要求添加了解释。
–
|
关于如何终止循环的原始问题:
如果您\xloop
有终止的\relax
。 假设您的输入从不包含\relax
标记(这已经是您自己的循环的先决条件),您可以通过吞下所有内容来终止循环,直到\relax
,您只需要注意,因为您吞下了 ,所以\fi
您需要重新插入一个。 以下操作可以做到这一点(但随后相当于expl3
我的另一个答案中更干净的解决方案):
\documentclass{article}
\usepackage{xstring}
\begin{document}
\def\xloop#1{%
\ifx\relax#1%
\else
\IfInteger{#1}{\xloopDone}{}%
\expandafter\xloop
\fi}
\def\xloopDone#1\relax{\fi first integer was here}
\def\test#1{\xloop#1\relax}
\test{abc3de5f}
\end{document}
仅产生收益first integer was here
,没有其他。
|
这是一个仅使用 TeX 原语的可扩展解决方案:
\def\xloop#1{%
\ifx\relax#1\else
\ifnum 2<1#1 \loopE \else non-integer:#1 \fi
\expandafter \xloop
\fi
}
\def\loopE #1\relax{\fi\fi}
\xloop abc3de0f\relax
\bye
测试是否#1
为整数是通过 完成的\ifnum
。有两种情况:
\ifnum 2<1x \loopE \else non-integer:x\fi
此测试为假,因为 2<1 不成立。处理 else-text。
\ifnum 2<10 \loopE \else non-integer:0\fi
此测试为真,因为 2<10(或 11、12 等)为真。宏\loopE
执行最后工作:忽略下一个文本\relax
并关闭两个打开的\if
分支。
0
|
如果这只是为了检查是否包含数字,以下是一种相当快速的方法:
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand\ifcontainsnum{mmm}
{ \xcn_if_contains_num:nTF {#1} {#2} {#3} }
\prg_new_conditional:Npnn \xcn_if_contains_num:n #1 { TF, T, F, p }
{
\str_map_function:nN {#1} \__xcn_if_contains_num:n
\prg_return_false:
}
\cs_new:Npn \__xcn_if_contains_num:n #1
{ \xcn_if_digit:nT {#1} { \str_map_break:n { \use_i:nn \prg_return_true: } } }
\prg_new_conditional:Npnn \xcn_if_digit:n #1 { TF, T, F, p }
{
\if_int_compare:w 1 < 1\exp_not:N#1 \exp_stop_f:
\prg_return_true:
\else:
\prg_return_false:
\fi:
}
\ExplSyntaxOff
\begin{document}
\ifcontainsnum{abc}{yes}{no}
\ifcontainsnum{abc1}{yes}{no}
\ifcontainsnum{ab{c1}}{yes}{no}
\end{document}
由此得到no
、yes
和yes
。
|
为什么只做数字?
这里\defineclass
提供了一种形式\str_case:nnF
,因此可以测试循环中的当前项是否属于该类。
你可以通过 来\loopbreak
停止循环。参见最后的例子。
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\stringloop}{mmmmm}
{% #1 = string to test
% #2 = class name (CN)
% #3 = what to do if the item is in the class (YES)
% #4 = what to do if the item is not in the class (NO}
% #5 = what to do at the end if not stopped (END)
\xcn_stringloop:ennnn {\tl_to_str:n {#1}} {#2} {#3} {#4} {#5}
}
\cs_new:Nn \xcn_stringloop:nnnnn
{
\__xcn_stringloop:w {#2} {#3} {#4} {#5} #1 \q_nil
}
\cs_generate_variant:Nn \xcn_stringloop:nnnnn {e}
\cs_new:Npn \__xcn_stringloop:w #1 #2 #3 #4 #5
{% #1 = CN, #2 = YES, #3 = NO, #4 = END, #5 = current item in string
\quark_if_nil:nTF {#5}
{
#4
}
{
\__xcn_stringloop_item:nnnnn {#1} {#5} {#2} {#3} {#4}
}
}
\cs_new:Nn \__xcn_stringloop_item:nnnnn
{% #1 = CN, #2 = current item in string, #3 = YES, #4 = NO, #5 = END
\use:c {__xcn_stringloop_class_#1:nTF} {#2} {#3} {#4}
\__xcn_stringloop:w {#1} {#3} {#4} {#5}
}
\NewDocumentCommand{\defineclass}{mm}
{% #1 = class name, #2 = members
\cs_new:ce {__xcn_stringloop_class_#1:nTF}
{
\exp_not:N \str_case:nnF {##1}
{ \tl_map_function:nN {#2} \__xcn_stringloop_make_case:n }
{ ##3 }
}
}
\cs_new:Nn \__xcn_stringloop_make_case:n { {#1}{##2} }
\NewExpandableDocumentCommand{\loopbreak}{m}
{
#1 \__xcn_stringloop_break:w
}
\cs_new:Npn \__xcn_stringloop_break:w #1 \q_nil {}
\NewExpandableDocumentCommand{\checkforTF}{mmmm}
{
\xcn_stringloop:ennnn {\tl_to_str:n {#1}} {#2} {\loopbreak{#3}} {} {#4}
}
\ExplSyntaxOff
\defineclass{digits}{0123456789}
\defineclass{unknowns}{xyz}
\begin{document}
\raggedright
\stringloop{abc3def5g}{digits}{DIGIT }{NONDIGIT }{END}
\bigskip
\stringloop{abc3def5g}{digits}{\loopbreak{DIGIT, STOP}}{NONDIGIT }{END}
\bigskip
\checkforTF{abc3def5g}{digits}{There's a digit}{There's no digit}
\bigskip
\checkforTF{abcdefg}{digits}{There's a digit}{There's no digit}
\bigskip
\edef\test{\checkforTF{abc3def5g}{digits}{There's a digit}{There's no digit}}
\texttt{\meaning\test}
\bigskip
\stringloop{abxcy}{unknowns}{(unknown)}{(parameter)}{}
\bigskip
\stringloop{abxc}{unknowns}{\loopbreak{(unknown)}}{(parameter)}{end}
\bigskip
\stringloop{abc}{unknowns}{\loopbreak{(unknown)}}{(parameter)}{end}
\end{document}
|
|