\expandafter 和计数器运行不顺畅

\expandafter 和计数器运行不顺畅

我的 google-fu 终于让我失望了...我正在尝试编写一个包,它允许你\addauthor{name, email}多次说,并正确格式化标题页。以下是我的麻烦的一个简单例子:

% FILE: sd.sty
\ProvidesPackage{sd}
\newcounter{authors}
\newcommand{\@authors}{\@empty}
\newcommand{\@authorsnoemail}{\@empty}
\def\addauthor#1{\@addauthor#1\@nil}
\def\@addauthor#1,#2\@nil{%
  \expandafter\def\expandafter\@authorsnoemail\expandafter{%
    \@authorsnoemail%
    \ifnum\value{authors}>0, \fi%
    #1}
  \expandafter\def\expandafter\@authors\expandafter{\@authors%
    \ifnum\value{authors}=0 \else ; \fi%
    #1 - #2}
  \stepcounter{authors}}
\newcommand{\ane}{\@authorsnoemail}
\newcommand{\auth}{\@authors}

然后我尝试

% FILE: main.tex
\documentclass{article}
\usepackage{sd}

\addauthor{1, 1@1}
\addauthor{2, 2@2}
\addauthor{3, 3@3}

\begin{document}
\begin{tabular}{ll}
Expected: & 1, 2, 3 \\
Got: &  \ane\\
Expected: & 1 - 1@1; 2 - 2@2; 3 - 3@3 \\
Got: & \auth \\
\end{tabular}
\end{document}

输出是

Expected: 1, 2, 3
Got:      , 1, 2, 3
Expected: 1 - 1@1; 2 - 2@2; 3 - 3@3
Got:      ; 1 - 1@1; 2 - 2@2; 3 - 3@3

我的问题是“我怎样才能正确地进行计数器比较,以便分隔符仅插入第二作者及以上的位置?”

(我包含了这两个列表,因为出于某种原因,删除一个可以使其正常工作...我怀疑我对 s 做错了什么\expandafter

答案1

在此处输入图片描述

先处理初始情况可能更容易。我还添加了一个额外的内容#3以删除逗号后面的任何空格。

% FILE: sd.sty
\ProvidesPackage{sd}
\newcounter{authors}
\let\@authors\@empty
\let\@authorsnoemail\@empty
\def\addauthor#1{\@addauthor#1\@empty\@nil}
\def\@addauthor#1,#2#3\@nil{%
  \ifx\@authors\@empty
     \def\@authorsnoemail{#1}%
     \def\@authors{#1 - #2#3}%
  \else
  \expandafter\def\expandafter\@authorsnoemail\expandafter{%
    \@authorsnoemail, #1}%
  \expandafter\def\expandafter\@authors\expandafter{%
    \@authors; #1 - #2#3}%
   \fi
  \stepcounter{authors}}
\newcommand{\ane}{\@authorsnoemail}
\newcommand{\auth}{\@authors}

答案2

你没有扩展条件,它放在里面\@authors 照原样:如果你\makeatletter\show\@authors\makeatother按照这些\addauthor行做,你会得到

> \@authors=macro:
->\@empty \ifnum \value {authors}=0 \else ; \fi 1 -  1@1\ifnum \value {authors}
=0 \else ; \fi 2 -  2@2\ifnum \value {authors}=0 \else ; \fi 3 -  3@3.

这显然不是你想要的。

这是一个解决方法;为了比 David 更现代,我以 LaTeX3 形式呈现它:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\addauthor}{ >{ \SplitArgument { 1 } { , } } m }
 {
  \sd_addauthor:nn #1
 }

\NewDocumentCommand{\betteraddauthor}{ m m }
 {
  \sd_addauthor:nn { #1 } { #2 }
 }

\NewDocumentCommand{\ane}{ }
 {
  \seq_use:Nnnn \g_sd_authors_noemail_seq { ,~ } { ,~ } { ,~ }
 }
\NewDocumentCommand{\auth}{ }
 {
  \seq_use:Nnnn \g_sd_authors_seq { ;~ } { ;~ } { ;~ }
 }

\cs_new_protected:Npn \sd_addauthor:nn #1 #2
 {
  \seq_gput_right:Nn \g_sd_authors_seq { #1 ~ - ~ #2 }
  \seq_gput_right:Nn \g_sd_authors_noemail_seq { #1 }
 }
\seq_new:N \g_sd_authors_seq
\seq_new:N \g_sd_authors_noemail_seq

\ExplSyntaxOff


\addauthor{1, 1@1}
\addauthor{2, 2@2}
\betteraddauthor{3}{3@3}

\begin{document}
\begin{tabular}{ll}
Expected: & 1, 2, 3 \\
Got: &  \ane\\
Expected: & 1 - 1@1; 2 - 2@2; 3 - 3@3 \\
Got: & \auth \\
\end{tabular}
\end{document}

输出如下:

在此处输入图片描述

我不认为语法

\addauthor{A. Name, [email protected]}

非常好,我更喜欢

\addauthor{A. Name}{[email protected]}

所以我为第二种语法提供了 的定义\betteraddauthor。请注意,使用的“内部”宏是相同的。

答案3

以下只是使用了较少的字符,并使用了插入的空格,但没有将其删除。这只适用于您建议的输出,它需要空格。

在此处输入图片描述

\documentclass{article}
\makeatletter
\newcounter{authors}
\newcommand{\@authors}{}
\newcommand{\@authorsnoemail}{}
\def\addauthor#1{\@addauthor#1\@nil}
\def\@addauthor#1,#2\@nil{%
  \protected@edef\@authorsnoemail{\@authorsnoemail%
    \ifnum\value{authors}>0, \fi%
    #1}%
  \protected@edef\@authors{\@authors%
    \ifnum\value{authors}>0; \fi%
    #1 -#2}%
  \stepcounter{authors}}
\newcommand{\ane}{\@authorsnoemail}
\newcommand{\auth}{\@authors}
\makeatother
\addauthor{1, 1@1}
\addauthor{2, 2@2}
\addauthor{3, 3@3}

\begin{document}
\begin{tabular}{ll}
Expected: & 1, 2, 3 \\
Got: &  \ane\\
Expected: & 1 - 1@1; 2 - 2@2; 3 - 3@3 \\
Got: & \auth \\
\end{tabular}
\end{document}

相关内容