如何测试字符串是否为空

如何测试字符串是否为空

我尝试了几种方法来测试参数是否为空或等于特定字符。应该如何进行?

顺便问一下,对可以有三个值的参数使用条件代码的最佳方法是什么:空,v,h?

\documentclass{standalone}
\newcommand{\Test}[3]{%
    \ifnum #1=1 C'est \'egal à 1 \fi
    \if #2v C'est \'egal à v \fi
    \ifx #2v C'est \'egal à v \fi
    \if #3\empty C'est vide \fi
    \ifx #3\empty C'est vide \fi
    }

\begin{document}
\Test{1}{v}{}
\end{document}

永远不要说视频......

答案1

如果使用原始的 TeX if 语法,你应该始终注意将测试标记第一的在用户提供令牌之前,否则您无法控制正在测试的内容:

\documentclass{standalone}
\newcommand{\Test}[3]{%
    \ifnum #1=1 C'est \'egal à 1 \fi
    \if #2v C'est \'egal à v \fi
    \ifx #2v C'est \'egal à v \fi
    \if #3\empty C'est vide \fi
    \ifx #3\empty C'est vide \fi
    }

\begin{document}
\Test{2=2}{aa}{!!}
\end{document}

第四个测试永远不会测试是否#3为空,如果给定一个字符,它会测试它是否为C

您应该使用的确切测试取决于您对空的定义。其中哪个是“空”,其中外部{}是参数的分隔符:{} { } {\empty} {\mbox{}}

我通常会做类似的事情

 \ifx\som@internal@macro#1\som@internal@macro

\som@internal@macro一些在哪里定义文件中不太可能在参数中使用的宏。然后,如果#1为空,则测试为

 \ifx\som@internal@macro\som@internal@macro

所以测试为真,如果#1非空(并且不以 开头\som@internal@macro)则测试为假。

答案2

以下是大卫·卡莱尔的解决方案在一个名为 的宏中\ifempty。使用它代替 ,\if如下所示。确保将参数括\ifempty在花括号中。

\def \ifempty#1{\def\temp{#1} \ifx\temp\empty }

\def \mymacro#1{ \ifempty{#1} empty \else not empty \fi }

\mymacro{something} % prints "not empty"
\mymacro{}          % prints "empty"

答案3

如图所示此线程上的 egreg使用\ifstremptyetoolbox 包中的命令,可以测试给定的字符串是否为空,另外还有一个好处给定字符串中的换行符不会引起问题

下面是在宏中使用此命令来测试字符串 #1 是否为空的示例:

\usepackage{etoolbox}
\newcommand{\Test}[1]{%
    \ifstrempty{#1}%
        {%
            empty%
        }{%
            not empty%
        }%
}

如果 #1 为空,则此宏还可用于打印 #2;如果 #1 非空,则打印 #3。

\newcommand{\Test}[3]{%
    \ifstrempty{#1}%
    {%
        #2% If #1 is empty
    }{%
        #3% If #1 is not empty
    }%
}

答案4

您说一个参数的值有三种可能。

参数和⟨参数文本⟩宏定义的表示方法,在扩展所讨论的宏时,如何从标记流中收集并处理宏参数。

宏参数反过来是标记的组合。

“价值”一词有点含糊:

  1. 您的意思是,恰好有三种不同的标记组合可以收集作为宏观论据?

  2. 或者作为 TeX 进行扩展/评估-⟨数字⟩也扮演一个角色吗?

  3. 如果两个参数不是由相同的标记组合组成,而是由具有相同数量标记的不同标记组合组成,并且对于所有可能的标记,它们是否也具有相同的“值”-th 标记具有相同的\meaning,即类似于:

    \let\One=1
    \let\Two=2
    argument 1: 1\Two
    argument 2: \One2
    

如果它只是关于标记的不同组合,而不同标记的扩展/评估和含义相等不起作用,并且任何可能的组合都不包含花括号或井号等特殊标记(类别代码 1 或 2 或 6 的显式字符标记),则可以通过分隔参数来实现分叉,其中参数分隔符的部分由可能的标记组合形成。没有花括号和井号,因为这些类型的标记不能成为分隔参数分隔符的组成部分。

\documentclass{article}

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%% If e-TeX-extensions are available, you can do:
%\newcommand\UD@CheckWhetherNull[1]{%
%  \romannumeral0\if\relax\detokenize{#1}\relax
%    \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@firstoftwo
%  \else
%    \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@secondoftwo
%  \fi
%}%
%%-----------------------------------------------------------------------------
%% Check whether argument contains ! not nested in braces:
%%.............................................................................
\@ifdefinable\UD@gobbletoExclam{\long\def\UD@gobbletoExclam#1!{}}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoExclam#1!}%
}%
\newcommand\Test[3]{%
   \UD@CheckWhetherNoExclam{#1}{%
     \ForkParameterOne!#1!1!{Argument 1 est vide.}%
                      !!#1!{Argument 1 est \'egal à 1.}%
                      !!1!{Argument 1 n'est pas vide, n'est pas egal à 1, et est sans ``!''.}%
                      !!!!%
   }{Argument 1 n'est pas vide, n'est pas egal à 1, et est avec ``!''.} %
   \UD@CheckWhetherNoExclam{#2}{%
     \ForkParameterTwo!#2!v!h!{Argument 2 est vide.}%
                      !!#2!h!{Argument 2 est \'egal à v.}%
                      !!v!#2!{Argument 2 est \'egal à h.}%
                      !!v!h!{Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est sans ``!''.}%
                      !!!!%
   }{Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est avec ``!''.} %
   \UD@CheckWhetherNoExclam{#3}{%
     \ForkParameterThree!#3!{Argument 3 est vide.}%
                      !!{Argument 3 n'est pas vide et est sans ``!''.}%
                      !!!!%
   }{Argument 3 n'est pas vide et est avec ``!''.}%
}%
\@ifdefinable\ForkParameterOne{%
  \long\def\ForkParameterOne#1!!1!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterTwo{%
  \long\def\ForkParameterTwo#1!!v!h!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterThree{%
  \long\def\ForkParameterThree#1!!#2#3!!!!{#2}%
}%
\makeatother

\parindent=0ex
\parskip=\bigskipamount

\begin{document}
\verb|\Test{1}{v}{}| $\to$\\ \Test{1}{v}{}

\verb|\Test{1}{h}{}| $\to$\\ \Test{1}{h}{}

\verb|\Test{}{}{}| $\to$\\ \Test{}{}{}

\verb|\Test{X}{Y}{Z}| $\to$\\ \Test{X}{Y}{Z}

\verb|\Test{!}{!}{!}| $\to$\\ \Test{!}{!}{!}

\verb|\Test{1a}{vb}{}| $\to$\\ \Test{1a}{vb}{}
\end{document}

在此处输入图片描述

如果您需要将评估结果作为标记序列(例如,在扩展上下文中),则可以添加一些交换参数和\romannumeral0扩展:

\documentclass{article}

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%% If e-TeX-extensions are available, you can do:
%\newcommand\UD@CheckWhetherNull[1]{%
%  \romannumeral0\ifx\relax\detokenize{#1}\relax
%    \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@firstoftwo
%  \else
%    \@firstoftwo{\expandafter\expandafter\expandafter}{} \expandafter\@secondoftwo
%  \fi
%}%
%%-----------------------------------------------------------------------------
%% Exchanging two arguments:
%%.............................................................................
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Check whether argument contains ! not nested in braces:
%%.............................................................................
\@ifdefinable\UD@gobbletoExclam{\long\def\UD@gobbletoExclam#1!{}}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoExclam#1!}%
}%
%%-----------------------------------------------------------------------------
%% \Test. The result is delivered after two expansion-steps/after two "hits"
%%        with \expandafter.
%%.............................................................................
\newcommand\Test[3]{%
   \romannumeral0%
   \expandafter\UD@Exchange\expandafter{%
     \romannumeral0%
     \UD@CheckWhetherNoExclam{#3}{%
       \ForkParameterThree!#3!{ Argument 3 est vide.}%
                        !!{ Argument 3 n'est pas vide et est sans ``!''.}%
                        !!!!%
     }{ Argument 3 n'est pas vide et est avec ``!''.} %
   }{%
     \expandafter\UD@Exchange\expandafter{%
       \romannumeral0%
       \UD@CheckWhetherNoExclam{#2}{%
         \ForkParameterTwo!#2!v!h!{ Argument 2 est vide.}%
                          !!#2!h!{ Argument 2 est \'egal à v.}%
                          !!v!#2!{ Argument 2 est \'egal à h.}%
                          !!v!h!{ Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est sans ``!''.}%
                          !!!!%
       }{ Argument 2 n'est pas vide, ni est egal à v, ni est egal à h, et est avec ``!''.} %
     }{%
       \expandafter\UD@Exchange\expandafter{%
         \romannumeral0%
         \UD@CheckWhetherNoExclam{#1}{%
           \ForkParameterOne!#1!1!{ Argument 1 est vide.}%
                            !!#1!{ Argument 1 est \'egal à 1.}%
                            !!1!{ Argument 1 n'est pas vide, n'est pas egal à 1, et est sans ``!''.}%
                            !!!!%
         }{ Argument 1 n'est pas vide, n'est pas egal à 1, et est avec ``!''.} %
       }{ }%
     }%
   }%
}%
\@ifdefinable\ForkParameterOne{%
  \long\def\ForkParameterOne#1!!1!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterTwo{%
  \long\def\ForkParameterTwo#1!!v!h!#2#3!!!!{#2}%
}%
\@ifdefinable\ForkParameterThree{%
  \long\def\ForkParameterThree#1!!#2#3!!!!{#2}%
}%
\makeatother

\parindent=0ex
\parskip=0ex
\topsep=0ex
\partopsep=0ex

\begin{document}
% adjust gap between top-margin and 1st line of text
\hbox{}%
\kern-\headheight
\kern-\headsep
\kern-1in
\kern-\topmargin
\kern-\baselineskip
\kern-\topskip
\kern\ht\strutbox
\kern.5cm
\enlargethispage{.5cm}%
%--------------------------

\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{1}{v}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{1}{v}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%

\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null

\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{1}{h}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{1}{h}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%

\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null

\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{}{}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{}{}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%

\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null

\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{X}{Y}{Z}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{X}{Y}{Z}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%

\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null

\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{!}{!}{!}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{!}{!}{!}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%

\kern-\ht\strutbox\kern\dp\strutbox\hrulefill\null

\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{1a}{vb}{}%
}
\end{verbatim}
$\to$\\
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\temp
\expandafter\expandafter\expandafter{%
  \Test{1a}{vb}{}%
}%
{\tt\frenchspacing\sloppy\string\temp=\meaning\temp\par}%

\end{document}

在此处输入图片描述

相关内容