如何在另一个命令(csname)中获取命令(csname)的内容

如何在另一个命令(csname)中获取命令(csname)的内容

我正在尝试按照学校的论文标准创建一个课程,当我尝试实现首字母缩略词列表时遇到了问题,因为这个列表应该按字母顺序排序,而我发现的包与我实现的课程不兼容。所以我决定使用数组进行自己的实现。

我可以创建数组(其中数组的每个元素都使用\foo#1作为中的新索引),但要对该数组进行排序,我需要在数组的特定位置插入一个元素。#1\csname foo#1 \endcsname

我现在的代码示例是:

\documentclass[]{report}

\newcounter{countArrayTest}
\setcounter{countArrayTest}{0}

\newcommand{\appendElement}[1]{%
    \expandafter\newcommand\csname arraytest\the\value{countArrayTest} \endcsname{#1}
    \stepcounter{countArrayTest}
}

\newcommand{\getIndexElement}[1]{
    \csname arraytest#1 \endcsname
}

\newcommand{\testInsert}{%
    \expandafter\renewcommand\csname arraytest1 \endcsname{\getIndexElement{0}}
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}
}

\newcounter{CountTempAux}

\newcommand{\showAll}{%
    \setcounter{CountTempAux}{0}
    \loop\ifnum\value{CountTempAux}<\value{countArrayTest}
        \csname arraytest\the\value{CountTempAux} \endcsname
        \stepcounter{CountTempAux}
    \repeat
}

\begin{document}


\appendElement{Element1}
\appendElement{Element2}


\testInsert

\showAll

\end{document}

问题是,我期望答案是“Test1 Element1”,但我得到的是“Test1 Test1”。

有什么建议可以解决这个问题吗?

答案1

我同意艾伦·芒恩评论说,如果你向我们展示你尝试使用的缩写包所遇到的问题,可能会更容易一些(acronymglossaries?)。

对于你现在的问题:你遇到的问题在于

\newcommand{\testInsert}{%
    \expandafter\renewcommand\csname arraytest1 \endcsname{\getIndexElement{0}}
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}
}

\arraytest1不是定义为\arraytest0但为\getIndexElement{0}。稍后当你在里面调用它时\showall \arraytest0已经被重新定义为Test1

为了存储\arraytest0你需要扩展的内容\getIndexEntry{0}

\newcommand{\testInsert}{%
    \expandafter\edef\csname arraytest1 \endcsname{\getIndexElement{0}}%
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}%
}

现在

\appendElement{Element1}\appendElement{Element2}
\testInsert
\showAll

会给

测试1 元素1

\arraytest0但如果包含不可扩展的内容,这将不起作用:

\appendElement{\textbf{Element1}}\appendElement{Element2}
\testInsert
\showAll

在这种情况下你可以使用\protected@edef

\makeatletter
\newcommand{\testInsert}{%
    \expandafter\protected@edef\csname arraytest1 \endcsname{\getIndexElement{0}}%
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}%
}
\makeatother
\appendElement{\textbf{Element1}}\appendElement{Element2}
\testInsert
\showAll

测试1元素1

您还可以使用etoolbox\csletcs(*):

\usepackage{etoolbox}
\newcommand{\testInsert}{%
    \csletcs{arraytest1}{arraytest0}%
    \expandafter\renewcommand\csname arraytest0\endcsname{Test1}%
}

(*) 您当前的定义showall在元素之间产生了很多空格。为了避免这种情况,您应该注释掉所有不以命令结尾的行:

\newcommand{\showAll}{%
    \setcounter{CountTempAux}{0}%
    \loop\ifnum\value{CountTempAux}<\value{countArrayTest}%
        \csname arraytest\the\value{CountTempAux} \endcsname
        \stepcounter{CountTempAux}%
    \repeat
}

这同样适用于您定义的其他所有命令。例如

\newcommand{\appendElement}[1]{%
    \expandafter\newcommand\csname arraytest\the\value{countArrayTest} \endcsname{#1}
    \stepcounter{countArrayTest}
}

定义\arraytest0(包括 ! 后面的空格,0除非您更改它,否则\csletcs我的代码将无法工作)并在调用时产生两个额外的空格。更好的是:

\newcommand{\appendElement}[1]{%
    \expandafter\newcommand\csname arraytest\the\value{countArrayTest}\endcsname{#1}%
    \stepcounter{countArrayTest}%
}

你可能想要使用\@namedefetoolbox无论如何\csdef

\newcommand{\appendElement}[1]{%
    \@namedef{arraytest\the\value{countArrayTest}}{#1}%
    \stepcounter{countArrayTest}%
}

答案2

如果您愿意投入这么多工作,那么这个tocloft套餐也许是值得尝试的。tocloft这是关于该软件包的快速入门文章。它会将一个文件放入编译目录中,您可以通过该sort(1)文件或另一个实用程序作为构建过程的一部分来运行它。

相关内容