纯文本替换问题

纯文本替换问题

有人能告诉我我做错了什么吗?我无法让第二个测试正常工作(并且该命令似乎与手动完成的参数相同)

\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\tempOP 或其他答案中带有“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

引用

相关内容