如何检查某个内容是否以 * 开头(或如何从 moodle 数据库构建自己的练习表)

如何检查某个内容是否以 * 开头(或如何从 moodle 数据库构建自己的练习表)

我想检查某些内容是否以星号 ( *)开头

我的尝试:

\def\testast#1{\ifx*#1\relax YES\else NO\fi}

但输出\testast{*Word}WordYES,而我期望的只是YES


我需要的实际情况如下:我正在尝试解析练习数据库,格式如下

    \begin{multi}
     Text
     \item answer 
     \item another answer
     \item* the correct answer
    \end{multi}

并找到正确答案。我使用getitems.sty。我的尝试是

    \newcommand\findcorrect[1]{%
      \ifx*#1 \relax\xdef\correct{\thecurrentitemnumber}%
      \fi%  
     }% 
    \NewEnviron{multi}[1][]{%
       \expandafter\gatheritems\expandafter{\BODY}
       \loopthroughitemswithcommand{\findcorrect}% 
    }%
    {}%

\gathereditems{n}但是,当对象找到正确答案时,我的宏就会在运行过程中打印。

问题归结于我在开始时发布的最初的例子。

答案1

使用\def\testast#1{\ifx*#1\relax YES\else NO\fi}命令
\testast{*Word}%
可得到:
\ifx**Word\relax YES\else NO\fi

\ifx将 的含义*与 的含义进行比较*。因此,if采用 -branch,而\else跳过 -branch,而if-branch 由 形成Word\relax YES\relax不会在 .pdf 文件中产生任何可见内容,因此在 .pdf 文件中您会看到WordYES



\makeatletter    
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@Exchange, \UD@stopromannumeral,
%%    \UD@CheckWhetherNull,  \UD@CheckWhetherLeadingTokens
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% 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]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%=============================================================================
%% Check whether argument's leading tokens form a specific 
%% token-sequence that does not contain explicit character tokens of 
%% category 1 or 2 or 6:
%%=============================================================================
%% \UD@CheckWhetherLeadingTokens{<argument which is to be checked>}%
%%                              {<a <token sequence> without explicit 
%%                                character tokens of category 1 or 2
%%                                or 6>}%
%%                              {<internal token-check-macro>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked> has
%%                                <token sequence> as leading tokens>}%
%%                              {<tokens to be delivered in case 
%%                                <argument which is to be checked>
%%                                does not have <token sequence> as
%%                                leading tokens>}%
\newcommand\UD@CheckWhetherLeadingTokens[3]{%
  \romannumeral\UD@CheckWhetherNull{#1}%
  {\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {%
    % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
    % and thus do not disturb when the test is carried out within \halign/\valign:
    \expandafter\UD@firstoftwo\expandafter{%
      \expandafter\expandafter\expandafter\UD@stopromannumeral
      \romannumeral
      \expandafter\UD@secondoftwo\string{\expandafter\UD@@CheckWhetherLeadingTokens#3{\relax}#1#2}{}}{}%
  }%
}%
\newcommand\UD@@CheckWhetherLeadingTokens[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\expandafter\expandafter\expandafter\UD@stopromannumeral
   \expandafter\expandafter\expandafter}%
  \expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token-sequence-gobble-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything 
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%
%% Defines <token-sequence-gobble-macro> to remove <token sequence> which in the
%% token-stream must definitely follow the token <token-sequence-gobble-macro>.
%%-----------------------------------------------------------------------------
\newcommand\UD@internaltokencheckdefiner[3]{%
  \@ifdefinable#1{\long\def#1##1#3{{##1}}}%
  \@ifdefinable#2{\def#2#3{}}%
}%
%%=============================================================================
%% Define infrastructure for checking for a leading *:
%%=============================================================================
\UD@internaltokencheckdefiner{\UD@SnapToStar}{\UD@GobbleStar}{*}%
%
% Now you can check for a leading * via
%
% \UD@CheckWhetherLeadingTokens{<argument to check>}{*}{\UD@SnapToStar}%
%                              {<tokens in case <argument to check> has a leading *>}%
%                              {<tokens in case <argument to check> does not have a leading *>}%
%
% \UD@GobbleStar must be trailed by * and removes that *.
%%=============================================================================
%% Define infrastructure for checking for a leading sequence *<space token>:
%%=============================================================================
\UD@internaltokencheckdefiner{\UD@SnapToStarSpace}{\UD@GobbleStarSpace}{* }%
%
% Now you can check for a leading sequence *<space token>  via
%
% \UD@CheckWhetherLeadingTokens{<argument to check>}{* }{\UD@SnapToStarSpace}%
%                              {<tokens in case <argument to check> has a leading *<space token> >}%
%                              {<tokens in case <argument to check> does not have a leading *<space token> >}%
%
% \UD@GobbleStarSpace must be trailed by a sequence *<space token>
% and removes that sequence *<space token>.
%%=============================================================================
%% Check if first token of macro-argument is an asterisk:
%%=============================================================================
%%
%% \testast{<argument to check>}%
%%         {<tokens in case <argument to check> has a leading *>}%
%%         {<tokens in case <argument to check> does not have a leading *>}%
%%
%%  (I suggest naming the command \CheckWhetherLeadingAsterisk instead of 
%    \testast.)
%%
\newcommand\testast[1]{%
  \UD@CheckWhetherLeadingTokens{#1}{*}{\UD@SnapToStar}%
}%
%------------------------------------------------------------------------------

\makeatother

\documentclass{article}

\usepackage{getitems}
%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
\usepackage{amsmath}
%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

\makeatletter
\NewEnviron{multi}[1][]{%
   \expandafter\gatheritems\expandafter{\BODY}%
   \loopthroughitemswithcommand{\findcorrect}% 
}{}%
\newcommand\findcorrect[1]{%
  \UD@CheckWhetherLeadingTokens{#1}{*}{\UD@SnapToStar}{%
    \expandafter\gdef\expandafter\NumberOfCorrectAnswer\expandafter{%
      \number\value{currentitemnumber}%
    }%
    \UD@CheckWhetherLeadingTokens{#1}{* }{\UD@SnapToStarSpace}{%
      \expandafter\gdef\expandafter\TextOfCorrectAnswer\expandafter{\UD@GobbleStarSpace#1}%
    }{%
      \expandafter\gdef\expandafter\TextOfCorrectAnswer\expandafter{\UD@GobbleStar#1}%
    }%
   }{}%
}% 
\makeatother

\begin{document}

\verb|\testast{*Word}{YES}{NO}|:  \testast{*Word}{YES}{NO}

\verb|\testast{Word}{YES}{NO}|:  \testast{Word}{YES}{NO}

\begin{multi}
 Text---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
 \item Answer---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
 \item Another answer---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
 \item* Correct---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\end{multi}

The number of the correct answer is: \NumberOfCorrectAnswer.

The text of the correct answer is: \TextOfCorrectAnswer.

\end{document}

在此处输入图片描述



如果你需要计算你的多环境并提取答案等,如你的评论

事实上我正要问 :) 正在计数,所以我需要提取问题的文本、可能的答案和正确的答案。在我的尝试中,计数器是numes,然后我使用\csname TEXT\roman{numes}文本\csname POSS\roman{numes}表示可能的答案数、\csname ANSWER\roman{n}ES\roman{numes}第 n 个可能的答案数和\csname CORRECT\roman{numes}正确选项数。然后我使用这样的宏来格式化考试,所以我需要使用然后说\expandafter\def\myneededmacro\cnsame TEXT\roman{numes}\endcsname

,那么您可以执行类似下面的操作,我使用它\UD@CsNameToCsToken来避免使用更长的\expandafter链来从控制序列名称生成控制序列标记:

\makeatletter    
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@Exchange, \UD@stopromannumeral,
%%    \UD@CsNameToCsToken, \UD@CheckWhetherNull, \UD@CheckWhetherLeadingTokens
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% Obtain control sequence token from name of control sequence name:
%%-----------------------------------------------------------------------------
%% \CsNameToCsToken<stuff not in braces>{NameOfCs}
%% ->  <stuff not in braces>\NameOfCs
%% (<stuff not in braces> may be empty.)
\@ifdefinable\UD@CsNameToCsToken{%
  \long\def\UD@CsNameToCsToken#1#{\romannumeral\UD@@CsNameToCsToken{#1}}%
}%
\newcommand\UD@@CsNameToCsToken[2]{%
  \expandafter\UD@Exchange\expandafter{\csname#2\endcsname}{\UD@stopromannumeral#1}%
}%
%%-----------------------------------------------------------------------------
%% 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]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's leading tokens form a specific 
%% token-sequence that does not contain explicit character tokens of 
%% category 1 or 2 or 6:
%%.............................................................................
%% \UD@CheckWhetherLeadingTokens{<argument which is to be checked>}%
%%                              {<a <token sequence> without explicit 
%%                                character tokens of category 1 or 2
%%                                or 6>}%
%%                              {<internal token-check-macro>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked> has
%%                                <token sequence> as leading tokens>}%
%%                              {<tokens to be delivered in case 
%%                                <argument which is to be checked>
%%                                does not have <token sequence> as
%%                                leading tokens>}%
\newcommand\UD@CheckWhetherLeadingTokens[3]{%
  \romannumeral\UD@CheckWhetherNull{#1}%
  {\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {%
    % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
    % and thus do not disturb when the test is carried out within \halign/\valign:
    \expandafter\UD@firstoftwo\expandafter{%
      \expandafter\expandafter\expandafter\UD@stopromannumeral
      \romannumeral
      \expandafter\UD@secondoftwo\string{\expandafter\UD@@CheckWhetherLeadingTokens#3{\relax}#1#2}{}}{}%
  }%
}%
\newcommand\UD@@CheckWhetherLeadingTokens[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\expandafter\expandafter\expandafter\UD@stopromannumeral
   \expandafter\expandafter\expandafter}%
  \expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token-sequence-gobble-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything 
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%
%% Defines <token-sequence-gobble-macro> to remove <token sequence> which in the
%% token-stream must definitely follow the token <token-sequence-gobble-macro>.
%%-----------------------------------------------------------------------------
\newcommand\UD@internaltokencheckdefiner[3]{%
  \@ifdefinable#1{\long\def#1##1#3{{##1}}}%
  \@ifdefinable#2{\def#2#3{}}%
}%
%%=============================================================================
%% END OF PARAPHERNALIA
%%=============================================================================
%%=============================================================================
%% CHECKING FOR LEADING ASTERISK OR LEADING ASTERISK TRAILED BY AN EXPLICIT
%% SPACE TOKEN
%%=============================================================================
%% Define infrastructure for checking for a leading *:
%%-----------------------------------------------------------------------------
\UD@internaltokencheckdefiner{\UD@SnapToStar}{\UD@GobbleStar}{*}%
%
% Now you can check for a leading * via
%
% \UD@CheckWhetherLeadingTokens{<argument to check>}{*}{\UD@SnapToStar}%
%                              {<tokens in case <argument to check> has a leading *>}%
%                              {<tokens in case <argument to check> does not have a leading *>}%
%
% \UD@GobbleStar must be trailed by * and removes that *.
%%-----------------------------------------------------------------------------
%% Define infrastructure for checking for a leading sequence *<space token>:
%%-----------------------------------------------------------------------------
\UD@internaltokencheckdefiner{\UD@SnapToStarSpace}{\UD@GobbleStarSpace}{* }%
%
% Now you can check for a leading sequence *<space token>  via
%
% \UD@CheckWhetherLeadingTokens{<argument to check>}{* }{\UD@SnapToStarSpace}%
%                              {<tokens in case <argument to check> has a leading *<space token> >}%
%                              {<tokens in case <argument to check> does not have a leading *<space token> >}%
%
% \UD@GobbleStarSpace must be trailed by a sequence *<space token>
% and removes that sequence *<space token>.
%%=============================================================================
%% END OF CHECKING FOR LEADING ASTERISK OR LEADING ASTERISK TRAILED BY AN 
%% EXPLICIT SPACE TOKEN
%%=============================================================================
\makeatother

\documentclass{article}

\usepackage{getitems}
%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
\usepackage{amsmath}
%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

\makeatletter
\newcounter{numes}%
\NewEnviron{multi}{%
   \stepcounter{numes}%
   % Instead of counting and defining \NameOfThisMultiInstance from the counter,
   % you can have the multi-environment process a mandatory argument where the
   % user is to pass a unique name for the current instance of the environment
   % and define  \NameOfThisMultiInstance  from that.
   \expandafter\gatheritems\expandafter{\BODY}%
   \UD@CsNameToCsToken\@ifdefinable{TEXT\roman{numes}}{%
     \UD@CsNameToCsToken
     \expandafter\expandafter\expandafter\expandafter
     \expandafter\expandafter\expandafter\gdef
     \expandafter\expandafter\expandafter\expandafter
     \expandafter\expandafter\expandafter{TEXT\roman{numes}}%
     \expandafter\expandafter\expandafter\expandafter
     \expandafter\expandafter\expandafter{%
       \gathereditem{0}%
     }%
   }%
   \UD@CsNameToCsToken\@ifdefinable{POSS\roman{numes}}{%
     \UD@CsNameToCsToken
     \expandafter\gdef\expandafter{POSS\roman{numes}}\expandafter{%
       \number\value{numgathereditems}%
     }%
   }%
   \loopthroughitemswithcommand{\extractanswers}% 
}{}%
\newcommand\extractanswers[1]{%
  \UD@CheckWhetherLeadingTokens{#1}{*}{\UD@SnapToStar}{%
    \UD@CsNameToCsToken\@ifdefinable{CORRECTNUM\roman{numes}}{%
      \UD@CsNameToCsToken
      \expandafter\gdef\expandafter{CORRECTNUM\roman{numes}}\expandafter{%
        \number\value{currentitemnumber}%
      }%
    }%
    \UD@CsNameToCsToken\@ifdefinable{ANSWER\roman{currentitemnumber}ES\roman{numes}}{%
      \UD@CheckWhetherLeadingTokens{#1}{* }{\UD@SnapToStarSpace}{%
        \UD@Exchange{\expandafter{\UD@GobbleStarSpace#1}}%
      }{%
        \UD@Exchange{\expandafter{\UD@GobbleStar#1}}%
      }%
      {%
        \UD@CsNameToCsToken
        \expandafter\gdef\expandafter
        {ANSWER\roman{currentitemnumber}ES\roman{numes}}%
      }%
    }%
    \UD@CsNameToCsToken\@ifdefinable{CORRECTTEXT\roman{numes}}{%
       \UD@CsNameToCsToken\UD@CsNameToCsToken
       \global\let{CORRECTTEXT\roman{numes}}={ANSWER\roman{currentitemnumber}ES\roman{numes}}%
    }%
  }{%
    \UD@CsNameToCsToken\@ifdefinable{ANSWER\roman{currentitemnumber}ES\roman{numes}}{%
       \UD@CsNameToCsToken\gdef{ANSWER\roman{currentitemnumber}ES\roman{numes}}{#1}%
    }%
  }%
}% 
\makeatother

\begin{document}

\begin{multi}
Header---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item First answer/incorect---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item Second answer/incorect---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item* Third answer-correct---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item Fourth answer/incorect---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\end{multi}

\verb|\TEXTi| yields: \TEXTi.

\verb|\POSSi| yields: \POSSi.

\verb|\CORRECTNUMi| yields: \CORRECTNUMi.

\verb|\CORRECTTEXTi| yields: \CORRECTTEXTi

\verb|\ANSWERiESi| yields: \ANSWERiESi.

\verb|\ANSWERiiESi| yields: \ANSWERiiESi.

\verb|\ANSWERiiiESi| yields: \ANSWERiiiESi.

\verb|\ANSWERivESi| yields: \ANSWERivESi.

\end{document}

在此处输入图片描述

答案2

您可以考虑使用参考值用于放置标签,以便在处理环境之前就可以引用事物:

在这个变体中,multi-environment 有一个强制参数,其中对于该环境的每个实例,用户必须为该实例提供一个唯一的名称。

宏、、、 用于检索所需信息。
\TEXT{⟨name of multi instance⟩}
\POSS{⟨name of multi instance⟩}
\CORRECTNUM{⟨name of multi instance⟩}
\CORRECTTEXT{⟨name of multi instance⟩}
\ANSWER{⟨name of multi instance⟩}{⟨number of answert⟩}

如果您这样做,就像任何交叉引用机制一样,您至少需要两次乳胶运行,直到所有内容匹配。

\makeatletter
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@Exchange, \UD@PassFirstToSecond,
%%    \UD@stopromannumeral, \UD@CheckWhetherNull, \UD@CheckWhetherLeadingTokens
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% 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]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's leading tokens form a specific 
%% token-sequence that does not contain explicit character tokens of 
%% category 1 or 2 or 6:
%%.............................................................................
%% \UD@CheckWhetherLeadingTokens{<argument which is to be checked>}%
%%                              {<a <token sequence> without explicit 
%%                                character tokens of category 1 or 2
%%                                or 6>}%
%%                              {<internal token-check-macro>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked> has
%%                                <token sequence> as leading tokens>}%
%%                              {<tokens to be delivered in case 
%%                                <argument which is to be checked>
%%                                does not have <token sequence> as
%%                                leading tokens>}%
\newcommand\UD@CheckWhetherLeadingTokens[3]{%
  \romannumeral\UD@CheckWhetherNull{#1}%
  {\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {%
    % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
    % and thus do not disturb when the test is carried out within \halign/\valign:
    \expandafter\UD@firstoftwo\expandafter{%
      \expandafter\expandafter\expandafter\UD@stopromannumeral
      \romannumeral
      \expandafter\UD@secondoftwo\string{\expandafter\UD@@CheckWhetherLeadingTokens#3{\relax}#1#2}{}}{}%
  }%
}%
\newcommand\UD@@CheckWhetherLeadingTokens[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\expandafter\expandafter\expandafter\UD@stopromannumeral
   \expandafter\expandafter\expandafter}%
  \expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token-sequence-gobble-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything 
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%
%% Defines <token-sequence-gobble-macro> to remove <token sequence> which in the
%% token-stream must definitely follow the token <token-sequence-gobble-macro>.
%%-----------------------------------------------------------------------------
\newcommand\UD@internaltokencheckdefiner[3]{%
  \@ifdefinable#1{\long\def#1##1#3{{##1}}}%
  \@ifdefinable#2{\def#2#3{}}%
}%
%%=============================================================================
%% END OF PARAPHERNALIA
%%=============================================================================
%%=============================================================================
%% CHECKING FOR LEADING ASTERISK OR LEADING ASTERISK TRAILED BY AN EXPLICIT
%% SPACE TOKEN
%%=============================================================================
%% Define infrastructure for checking for a leading *:
%%-----------------------------------------------------------------------------
\UD@internaltokencheckdefiner{\UD@SnapToStar}{\UD@GobbleStar}{*}%
%
% Now you can check for a leading * via
%
% \UD@CheckWhetherLeadingTokens{<argument to check>}{*}{\UD@SnapToStar}%
%                              {<tokens in case <argument to check> has a leading *>}%
%                              {<tokens in case <argument to check> does not have a leading *>}%
%
% \UD@GobbleStar must be trailed by * and removes that *.
%%-----------------------------------------------------------------------------
%% Define infrastructure for checking for a leading sequence *<space token>:
%%-----------------------------------------------------------------------------
\UD@internaltokencheckdefiner{\UD@SnapToStarSpace}{\UD@GobbleStarSpace}{* }%
%
% Now you can check for a leading sequence *<space token>  via
%
% \UD@CheckWhetherLeadingTokens{<argument to check>}{* }{\UD@SnapToStarSpace}%
%                              {<tokens in case <argument to check> has a leading *<space token> >}%
%                              {<tokens in case <argument to check> does not have a leading *<space token> >}%
%
% \UD@GobbleStarSpace must be trailed by a sequence *<space token>
% and removes that sequence *<space token>.
%%=============================================================================
%% END OF CHECKING FOR LEADING ASTERISK OR LEADING ASTERISK TRAILED BY AN 
%% EXPLICIT SPACE TOKEN
%%=============================================================================
\makeatother

\documentclass{article}

\usepackage{getitems}
\usepackage{amsmath}
\makeatletter
\usepackage{zref}%
\zref@newprop{Multi}{}%
\newcommand\TEXT[1]{\zref@extract{MULTI_TEXT_{#1}}{Multi}}%
\newcommand\POSS[1]{\zref@extract{MULTI_POSS_{#1}}{Multi}}%
\newcommand\CORRECTNUM[1]{\zref@extract{MULTI_CORRECTNUM_{#1}}{Multi}}%
\newcommand\CORRECTTEXT[1]{\zref@extract{MULTI_CORRECTTEXT_{#1}}{Multi}}%
\newcommand\ANSWER[2]{\zref@extract{MULTI_ANSWER_{#1}{#2}}{Multi}}%
\newcommand\ThisMultiName{}%
\NewEnviron{multi}[1]{%
   \def\ThisMultiName{#1}%
   \expandafter\gatheritems\expandafter{\BODY}%
   \expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter\UD@PassFirstToSecond
   \expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter{\gathereditem{0}}%
                                       {\zref@setcurrent{Multi}}%
   \zref@labelbyprops{MULTI_TEXT_{\ThisMultiName}}{Multi}%
   \expandafter\UD@PassFirstToSecond
   \expandafter{\number\value{numgathereditems}}%
               {\zref@setcurrent{Multi}}%
   \zref@labelbyprops{MULTI_POSS_{\ThisMultiName}}{Multi}%
   \loopthroughitemswithcommand{\extractanswers}% 
}{}%
\newcommand\extractanswers[1]{%
  \UD@CheckWhetherLeadingTokens{#1}{*}{\UD@SnapToStar}{%
    \expandafter\UD@PassFirstToSecond
    \expandafter{\number\value{currentitemnumber}}%
                {\zref@setcurrent{Multi}}%
    \zref@labelbyprops{MULTI_CORRECTNUM_{\ThisMultiName}}{Multi}%
    \expandafter\UD@PassFirstToSecond
    \expandafter{%
                  \romannumeral 
                  \UD@CheckWhetherLeadingTokens{#1}{* }{\UD@SnapToStarSpace}%
                  {\expandafter\UD@stopromannumeral\UD@GobbleStarSpace}%
                  {\expandafter\UD@stopromannumeral\UD@GobbleStar}#1%
                }%
                {\zref@setcurrent{Multi}}%
    \zref@labelbyprops{MULTI_ANSWER_{\ThisMultiName}{\arabic{currentitemnumber}}}{Multi}%
    \zref@labelbyprops{MULTI_CORRECTTEXT_{\ThisMultiName}}{Multi}%
  }{%
    \zref@setcurrent{Multi}{#1}%
    \zref@labelbyprops{MULTI_ANSWER_{\ThisMultiName}{\arabic{currentitemnumber}}}{Multi}%
  }%
}%
\makeatother

\begin{document}

\verb|\TEXT{NameOfThisMulti}| yields: \TEXT{NameOfThisMulti}.

\verb|\POSS{NameOfThisMulti}| yields: \POSS{NameOfThisMulti}.

\verb|\CORRECTNUM{NameOfThisMulti}| yields: \CORRECTNUM{NameOfThisMulti}.

\verb|\CORRECTTEXT{NameOfThisMulti}| yields: \CORRECTTEXT{NameOfThisMulti}.

\verb|\ANSWER{NameOfThisMulti}{1}| yields: \ANSWER{NameOfThisMulti}{1}.

\verb|\ANSWER{NameOfThisMulti}{2}| yields: \ANSWER{NameOfThisMulti}{2}.

\verb|\ANSWER{NameOfThisMulti}{3}| yields: \ANSWER{NameOfThisMulti}{3}.

\verb|\ANSWER{NameOfThisMulti}{4}| yields: \ANSWER{NameOfThisMulti}{4}.

\begin{multi}{NameOfThisMulti}%
Header---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item First answer/incorect---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item Second answer/incorect---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item* Third answer-correct---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\item Fourth answer/incorect---$\begin{pmatrix} a&b\\c&d\end{pmatrix}$
\end{multi}

\end{document}

在此处输入图片描述

相关内容