循环,与条件中的宏值进行比较,如果为真则与多个宏进行比较

循环,与条件中的宏值进行比较,如果为真则与多个宏进行比较

我似乎陷入了困境,现在正在通过反复试验来寻找正确的方法来做到这一点。

以下是一个总体思路:

% I DECLARE NEW MACROS WITH NAMES AS DEFFINITION. AND ASIGN LETTERS TO PEOPLE SINCE NUMBERS ARE FORBIDEN IN MACRO'S NAMES.
\newcommand{\AuthorNameA}{John}
\newcommand{\AuthorSurnameA}{Doe}
\newcommand{\AuthorNameB}{Jane}
\newcommand{\AuthorSurnameB}{Doe}
\newcommand{\AuthorNumber}{3}

% DECLARE NEW COUNTER
\newcounter{loopTitleCoverAuthor}

% START WITH LOOP
\forloop{loopTitleCoverAuthor}{1}{

   %COMPARE COUNTER WITH DEFINITION OF MACRO SET PREVIOUSLY
   \value{loopTitleCoverAuthor} < \value{bfThesisAuthorNumber}
}{
% IF CONDITION IS TRUE CHECK IF MACRO WITH PARTICULLAR ENDING IS DEFINED AND IF IT IS, PRINT NAME AND SURNAME
\ifdefined\expandafter\AuthorName\Alph{loopTitleCoverAuthor}
   \expandafter\AuthorName\Alph{loopTitleCoverAuthor} \textsc{\expandafter\AuthorSurname\Alph{loopTitleCoverAuthor}}\\
\fi
}

a) 不出所料,这不起作用。我遇到的第一个问题是将计数器与宏值进行比较。因此,为了继续并查看可能还有哪些错误,我将条件部分更改为:

\value{loopTitleCoverAuthor} < 3 %\value{bfThesisAuthorNumber}

b) 然后我在检查时遇到了问题\ifdefined,所以我也将其注释掉,并且总是调用姓名和姓氏宏。

c) 最后,我遇到了一个问题\expandafter(我认为)。我现在得到了输出,但不是它应该有的样子。它省略了\AuthorName和,\AuthorSurname并且只打印了\Alph计数器步骤。

我希望看到:

John Doe
Jane Doe

我得到:

AA
BB

因此,我的问题是:

  1. \forloop在(a)的条件中可以使用宏的值吗?

  2. 我应该如何重新格式化\ifdefined以正确检查每个循环中是否定义了宏(\AuthorNameA在第一个循环中,\AuthorNameB在第二个循环中...)(b)? 我也尝试了\csname,多个 \expandafter,\expandafterbefore \ifdefined,... 这里没有描述:https://www.tug.org/TUGboat/tb09-1/tb20bechtolsheim.pdf似乎有效(或者更可能的是,我做了一些明显错误的事情,但看不到它)。

  3. 我应该改变什么才能\AuthorNameA扩大(c)?

  4. 有没有更好的方法来做到这一点?在一个文件中声明“控件和变量”,然后\input在该文件中循环使用这些宏的值来显示和控制输出?

答案1

这个测试\value{A} < \value{B}对我有用。

我已经使用了\@ifundefined{csname}{true}{false}其中csname没有转义字符的要测试的命令名称\

这里最重要的是用 构建各种命令名称\csname foo\Alph{...}\endcsname

\documentclass{article}


\usepackage{forloop}

\newcommand{\AuthorNameA}{John}
\newcommand{\AuthorSurnameA}{Doe}
\newcommand{\AuthorNameB}{Jane}
\newcommand{\AuthorSurnameB}{Doe}
\newcommand{\AuthorNumber}{5}

% DECLARE NEW COUNTER
\newcounter{loopTitleCoverAuthor}

\newcounter{bfThesisAuthorNumber}
\setcounter{bfThesisAuthorNumber}{\AuthorNumber}


\begin{document}
% START WITH LOOP
\makeatletter 
\forloop{loopTitleCoverAuthor}{1}{%
  % COMPARE COUNTER WITH DEFINITION OF MACRO SET PREVIOUSLY
  \value{loopTitleCoverAuthor} < \value{bfThesisAuthorNumber} % End condition
}{
  \@ifundefined{AuthorName\Alph{loopTitleCoverAuthor}}{%
    Booooooooooooo: Author \Alph{loopTitleCoverAuthor} is not defined!

  }{
    Hooray:  Author \Alph{loopTitleCoverAuthor} exists and is \csname AuthorName\Alph{loopTitleCoverAuthor}\endcsname 

    \csname AuthorName\Alph{loopTitleCoverAuthor}\endcsname\ \textsc{\csname AuthorSurname\Alph{loopTitleCoverAuthor}\endcsname}

  }
}
\makeatother    
\end{document}

在此处输入图片描述

答案2

您的代码存在一些问题。

  1. 代码

    \ifdefined\expandafter\AuthorName\Alph{loopTitleCoverAuthor}
    

    测试是否\expandafter定义。

  2. 然而代码

    \expandafter\ifdefined\expandafter\AuthorName\Alph{loopTitleCoverAuthor}
    

    也不会有什么好处,因为当loopTitleCoverAuthor值为 1 时,你会得到

    \ifdefined\AuthorName A
    

    而不是如您所希望的那样出现单个标记。

  3. 同样地,当你这样做时

     \expandafter\AuthorName\Alph{loopTitleCoverAuthor}
    

    在真实部分,你得到代币,而不是\AuthorNameA

你能怎麼做?

诀窍是使用\ifcsname\csname。你第一的想要生成一个标记,其名称AuthorName由计数器的字母值组成:

\ifcsname AuthorName\Alph{loopTitleCoverAuthor}\endcsname
  \expandafter\AuthorName\Alph{loopTitleCoverAuthor}
  \textsc{\csname AuthorSurname\Alph{loopTitleCoverAuthor}\endcsname}\\
\fi

不需要\expandafter,因为\ifcsname和会进行完全扩展,直到找到\csname匹配为止。\endcsname

答案3

尽管已经有了很好的答案,但我还是贡献了我用于当前不断增长的 Liederbuch 包的版本:

\def\TesT#1{
\expandafter\def\csname test\Alph{#1}\endcsname{}
}

\newcounter{wseva}
\setcounter{wseva}{4}

\TesT{wseva}

\def\doesItExist#1{
\expandafter\ifx\csname test\Alph{#1}\endcsname\relax
no
\else
yes
\fi
}

\begin{document}

\doesItExist{wseva}

\end{document}

如果的内容\csname不存在,则返回\relax。比较\ifx\theExpandedCsname\relax返回 true。否则返回 false,并且\else将运行该部分。

相关内容