有人能告诉我我做错了什么吗?我无法让第二个测试正常工作(并且该命令似乎与手动完成的参数相同)
\magnification\magstep1
\hsize 5.5 true in
\hoffset 0.5 true in
\vsize 8.25 true in
\voffset = 2\baselineskip
\vbadness11000
\parskip\smallskipamount \tolerance1000
\font\narbold=cmb10 %% Bold non-extended
\font\titlefont=cmbx10 scaled \magstep3 %% For heading
\font\smc=cmcsc10 %% For running head
\parindent=0pt
\centerline{\titlefont What is wrong with this implementation}
\nobreak\bigskip\hrule\bigskip
\global\newcount\containsnum%
\global\containsnum=0 % 1 they contain that number
% 0 they don't contain that number
\def\dead#1xxx,{}%
\def\endpiece{xxx}%
%based on the following code
%TeX by Topic unknown number of arguments p105
%\White(K1a,Q2b,3c,P4d)%
\def\xContains#1,{\def\temp{#1}%
\ifx\temp\endpiece% no more to process
\else
\ifx\temp\tosearch
\global\containsnum=1%
\let\xxContains=\dead
% we no longer need the rest of the row it has been found
\else
\fi%
\expandafter\xxContains%
\fi}%
\def\Contains(#1)#2{\let\xxContains=\xContains\global\containsnum=0%\foundfalse
\def\tosearch{#2}\expandafter\xxContains#1,xxx,}%
This is a list of test for contains where the row (4,5,6,7,9,10,11) is input manually
as an argument (this works correctly)
\Contains(4,5,6,7,9,10,11){1}
1 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){2}
2 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){5}
5 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){11}
11 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){15}
15 is \ifodd\containsnum \else NOT \fi found
\def\listtypeno{1}
\expandafter\def\csname giveAttToFile\listtypeno\endcsname{4,5,6,7,9,10,11}
\def\testrow{(\expandafter\csname giveAttToFile\listtypeno\endcsname)}
This is a list of test for contains where the row is input from a command \testrow
and for some reason this doesn't work correctly?? why??
\expandafter\Contains\testrow{1}
1 is \ifodd\containsnum \else NOT \fi found
\expandafter\Contains\testrow{2}
2 is \ifodd\containsnum \else NOT \fi found
\expandafter\Contains\testrow{5}
5 is \ifodd\containsnum \else NOT \fi found
\expandafter\Contains\testrow{11}
11 is \ifodd\containsnum \else NOT \fi found
\expandafter\Contains\testrow{15}
15 is \ifodd\containsnum \else NOT \fi found
\bye
答案1
您的令牌太少\expandafter
,但是您拥有的令牌甚至放错了位置:带有 的\expandafter\csname giveAttToFile\listtypeno\endcsname
正在\expandafter
尝试扩展g
。
你需要二从 到\csname ...\endcsname
构建宏的第一级扩展的扩展步骤:第一级用于扩展\csname
,第二级用于扩展宏。因此,在 和\expandafter
之前需要三个\Contents
,当然,要交换\expandafter
和(
。
\magnification\magstep1
\hsize 5.5 true in
\hoffset 0.5 true in
\vsize 8.25 true in
\voffset = 2\baselineskip
\vbadness11000
\parskip\smallskipamount \tolerance1000
\font\narbold=cmb10 %% Bold non-extended
\font\titlefont=cmbx10 scaled \magstep3 %% For heading
\font\smc=cmcsc10 %% For running head
\parindent=0pt
\centerline{\titlefont What is wrong with this implementation}
\nobreak\bigskip\hrule\bigskip
\newcount\containsnum % initialized to 0
\def\dead#1xxx,{}%
\def\endpiece{xxx}%
%based on the following code
%TeX by Topic unknown number of arguments p105
%\White(K1a,Q2b,3c,P4d)%
\def\xContains#1,{\def\temp{#1}%
\ifx\temp\endpiece% no more to process
\else
\ifx\temp\tosearch
\global\containsnum=1%
\let\xxContains=\dead
% we no longer need the rest of the row it has been found
\else
\fi%
\expandafter\xxContains%
\fi}%
\def\Contains(#1)#2{\let\xxContains=\xContains\global\containsnum=0%\foundfalse
\def\tosearch{#2}\expandafter\xxContains#1,xxx,}%
This is a list of test for contains where the row (4,5,6,7,9,10,11) is input manually
as an argument (this works correctly)
\Contains(4,5,6,7,9,10,11){1}
1 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){2}
2 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){5}
5 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){11}
11 is \ifodd\containsnum \else NOT \fi found
\Contains(4,5,6,7,9,10,11){15}
15 is \ifodd\containsnum \else NOT \fi found
\def\listtypeno{1}
\expandafter\def\csname giveAttToFile\listtypeno\endcsname{4,5,6,7,9,10,11}
\def\testrow{\expandafter(\csname giveAttToFile\listtypeno\endcsname)}
This is a list of test for contains where the row is input from a command {\tt\string\testrow}
and for some reason this doesn't work correctly?? why??
\expandafter\expandafter\expandafter\Contains\testrow{1}
1 is \ifodd\containsnum \else NOT \fi found
\expandafter\expandafter\expandafter\Contains\testrow{2}
2 is \ifodd\containsnum \else NOT \fi found
\expandafter\expandafter\expandafter\Contains\testrow{5}
5 is \ifodd\containsnum \else NOT \fi found
\expandafter\expandafter\expandafter\Contains\testrow{11}
11 is \ifodd\containsnum \else NOT \fi found
\expandafter\expandafter\expandafter\Contains\testrow{15}
15 is \ifodd\containsnum \else NOT \fi found
\bye
当然,我会用不同的方式来做,使用expl3
(可以与 Plain 一起使用,但需要像 这样的 e-TeX 引擎pdftex
)。
\input expl3-generic
\ExplSyntaxOn
\cs_new_protected:Npn \Contains(#1)#2#3#4
{
\lampter_contains:nnnn { #1 } { #2 } { #3 } { #4 }
}
\cs_new_protected:Npn \lampter_contains:nnnn #1 #2 #3 #4
{
\clist_if_in:nnTF { #1 } { #2 } { #3 } { #4 }
}
\cs_generate_variant:Nn \lampter_contains:nnnn { f }
\cs_new_protected:Npn \xContains#1#2#3#4
{
\lampter_contains:fnnn { #1 } { #2 } { #3 } { #4 }
}
\ExplSyntaxOff
\parindent=0pt
This is a list of test for contains where the row {\tt\string\testrow} is input manually
as an argument (this works correctly)
1 is \Contains(4,5,6,7,9,10,11){1}{}{NOT} found
2 is \Contains(4,5,6,7,9,10,11){2}{}{NOT} found
5 is \Contains(4,5,6,7,9,10,11){5}{}{NOT} found
11 is \Contains(4,5,6,7,9,10,11){11}{}{NOT} found
15 is \Contains(4,5,6,7,9,10,11){15}{}{NOT} found
\def\listtypeno{1}
\expandafter\def\csname giveAttToFile\listtypeno\endcsname{4,5,6,7,9,10,11}
\def\testrow{\csname giveAttToFile\listtypeno\endcsname}
This is a list of test for contains where the row is input from a command {\tt\string\testrow}
and it works as well
1 is \xContains\testrow{1}{}{NOT} found
2 is \xContains\testrow{2}{}{NOT} found
5 is \xContains\testrow{5}{}{NOT} found
11 is \xContains\testrow{11}{}{NOT} found
15 is \xContains\testrow{15}{}{NOT} found
\bye
答案2
我觉得你的宏太复杂了。如果你需要通过
\ifodd\containsnum
那么你可以使用这个:
\newcount\containsnum
\def\contains(#1)#2{\def\tmpa{#2}\containsnum=0 \containsA#1,,\relax}
\def\containsA#1,{\def\tmpb{#1}%
\ifx\tmpb\empty
\else \ifx\tmpa\tmpb \containsB \fi
\expandafter\containsA \fi
}
\def\containsB#1,\relax{\fi\fi \containsnum=1 }
\def\containsCS#1#2{\def\tmpa{#2}\containsnum=0
\expandafter\expandafter\expandafter\containsA\csname#1\endcsname,,\relax}
\contains(4,5,6,7,9,10,11){1}
1 is \ifodd\containsnum \else NOT \fi found
\contains(4,5,6,7,9,10,11){2}
2 is \ifodd\containsnum \else NOT \fi found
\contains(4,5,6,7,9,10,11){5}
5 is \ifodd\containsnum \else NOT \fi found
\contains(4,5,6,7,9,10,11){11}
11 is \ifodd\containsnum \else NOT \fi found
\contains(4,5,6,7,9,10,11){15}
15 is \ifodd\containsnum \else NOT \fi found
\def\listtypeno{1}
\expandafter\def\csname giveAttToFile\listtypeno\endcsname{4,5,6,7,9,10,11}
\containsCS{giveAttToFile\listtypeno}{1}
1 is \ifodd\containsnum \else NOT \fi found
\containsCS{giveAttToFile\listtypeno}{2}
2 is \ifodd\containsnum \else NOT \fi found
\containsCS{giveAttToFile\listtypeno}{5}
5 is \ifodd\containsnum \else NOT \fi found
\containsCS{giveAttToFile\listtypeno}{11}
11 is \ifodd\containsnum \else NOT \fi found
\containsCS{giveAttToFile\listtypeno}{15}
15 is \ifodd\containsnum \else NOT \fi found
\bye
答案3
也许您打算\containsnum
计算发生次数?如果不是,那么\count
为此使用寄存器就太浪费了。您可以简单地使用宏。
可以进行更经济的编码。
更新我添加了对在逗号分隔值中使用空格的支持(\ifx\temp
OP 或其他答案中带有“etc...”的方法 - 除了 egreg 答案的第二部分 - 不支持在逗号前留空格的可能性,因此我觉得没有必要在我的回答中考虑这种可能性,但这个问题出现在评论中)。
\long\def\ZapSpaces #1 #2{#1#2\ZapSpaces }%
% TO BE USED IN A COMPLETE EXPANSION AS \ZapSpaces foo bar<SPACE>\Gobble
\long\def\Gobble #1{}%
% this will not work with an empty (or expanding to empty) #1
% feature can be added if needed
\def\contains (#1)#2{%
\def\containsi ##1,#2,##2##3\containsi
{\ifx\relax##2\def\containsnum{0}\else\def\containsnum{1}\fi}%
\edef\containsLIST
{\expandafter\ZapSpaces\romannumeral-`0#1 \Gobble }%
\expandafter\containsi\expandafter,\containsLIST,#2,\relax\containsi
}
\def\containsCS #1{\contains (\csname #1\endcsname)}
\contains (4,5,6,7,9,10,11){1}
1 is \if0\containsnum NOT \fi found
\contains (4,5,6,7,9,10,11){2}
2 is \if0\containsnum NOT \fi found
\contains (4,5,6,7,9,10,11){4}
4 is \if0\containsnum NOT \fi found
\contains (4,5,6,7,9,10,11){7}
7 is \if0\containsnum NOT \fi found
\contains (4,5,6,7,9,10,11){11}
11 is \if0\containsnum NOT \fi found
\contains (4,5,6,7,9,10,11){15}
15 is \if0\containsnum NOT \fi found
\def\mylist { 4, 5, 6, 7 , 9 , 10 , 11 }% trying out with spaces
\contains (\mylist){1}
1 is \if0\containsnum NOT \fi found
\contains (\mylist){2}
2 is \if0\containsnum NOT \fi found
\contains (\mylist){4}
4 is \if0\containsnum NOT \fi found
\tracingmacros1
\contains (\mylist){7}
\tracingmacros0
7 is \if0\containsnum NOT \fi found
\contains (\mylist){11}
11 is \if0\containsnum NOT \fi found
\contains (\mylist){15}
15 is \if0\containsnum NOT \fi found
\def\listtypeno{1}
\expandafter\def\csname giveAttToFile\listtypeno\endcsname {4,5,6,7,9,10,11}
\containsCS {giveAttToFile\listtypeno}{1}
1 is \if0\containsnum NOT \fi found
\containsCS {giveAttToFile\listtypeno}{2}
2 is \if0\containsnum NOT \fi found
\containsCS {giveAttToFile\listtypeno}{4}
4 is \if0\containsnum NOT \fi found
\containsCS {giveAttToFile\listtypeno}{7}
7 is \if0\containsnum NOT \fi found
\containsCS {giveAttToFile\listtypeno}{11}
11 is \if0\containsnum NOT \fi found
\containsCS {giveAttToFile\listtypeno}{15}
15 is \if0\containsnum NOT \fi found
\nopagenumbers
\bye