缺少插入的 \endcsname。\放松

缺少插入的 \endcsname。\放松

我正在尝试使用 /csname 和 /endcsname 读取一组预定义数据。但是,一直出现“missing /endcsname inserted”错误。以下是简化的 LaTex 代码。

\documentclass[11pt, oneside]{article}
\usepackage{geometry}
\geometry{letterpaper}

\def\datahello@zero@string{Hello}
\def\datahello@zero@symbol{, }
\def\datahello@one@string{world}
\def\datahello@one@symbol{!}
\def\datagreeting@zero@string{Nice}
\def\datagreeting@zero@symbol{ }
\def\datagreeting@one@string{to}
\def\datagreeting@one@symbol{ }
\def\datagreeting@two@string{meet}
\def\datagreeting@two@symbol{ }
\def\datagreeting@three@string{you}
\def\datagreeting@three@symbol{.}

\newcommand\digittoliteral[1]{%
    \ifcase#1\relax%
        zero%
        \or one%
        \or two%
        \or three%
        \or four%
        \or five%
        \or six%
        \or seven%
        \or eight%
        \or nine%
        \else #1%
    \fi%
}

\newcommand\literaldataname{}
\def\getdata#1#2#3{%
%   data#1@\digittoliteral{#2}@#3%  % Correctly gives datahello@zero@string
%   \csname #1@\digittoliteral{#2}\endcsname%   % First attempt fails because macro call within csname is illegal?
    \edef\literaldataname{data#1@\digittoliteral{#2}@#3}%   % Expects \literaldataname = dataalpha@zero
    \literaldataname%   % Correctly gives data@zero
    \csname \literaldataname\endcsname% % Second attempt fails?
}

\begin{document}
\getdata{hello}{0}{string}\getdata{hello}{0}{symbol}\getdata{hello}{1}{string}\getdata{hello}{1}{symbol}
\newline
\getdata{greeting}{0}{string}\getdata{greeting}{0}{symbol}\getdata{greeting}{1}{string}\getdata{greeting}{1}{symbol}\getdata{greeting}{2}{string}\getdata{greeting}{2}{symbol}\getdata{greeting}{3}{string}\getdata{greeting}{3}{symbol}
\end{document}

我一直收到以下错误。

Missing \endcsname inserted.
<to be read again>
                   \relax
l.42 alpha: \getdata{hello}{0}{string}
                                      \getdata{hello}{0}{symbol}

我认为我需要在第一次尝试中使用 \expandafter(无论如何)。但是,我很奇怪为什么第二次尝试不起作用,而我认为 \edef 会扩展所有内容?

答案1

\relax从 的定义中删除\digittoliteral

\documentclass{article}

\makeatletter
\def\datahello@zero@string{Hello}
\def\datahello@zero@symbol{, }
\def\datahello@one@string{world}
\def\datahello@one@symbol{!}
\def\datagreeting@zero@string{Nice}
\def\datagreeting@zero@symbol{ }
\def\datagreeting@one@string{to}
\def\datagreeting@one@symbol{ }
\def\datagreeting@two@string{meet}
\def\datagreeting@two@symbol{ }
\def\datagreeting@three@string{you}
\def\datagreeting@three@symbol{.}
\makeatother

\newcommand\digittoliteral[1]{%
    \ifcase#1
        zero%
        \or one%
        \or two%
        \or three%
        \or four%
        \or five%
        \or six%
        \or seven%
        \or eight%
        \or nine%
        \else #1%
    \fi
}

\newcommand\literaldataname{}
\def\getdata#1#2#3{\csname data#1@\digittoliteral{#2}@#3\endcsname}

\begin{document}

\getdata{hello}{0}{string}\getdata{hello}{0}{symbol}%
\getdata{hello}{1}{string}\getdata{hello}{1}{symbol}

\getdata{greeting}{0}{string}\getdata{greeting}{0}{symbol}%
\getdata{greeting}{1}{string}\getdata{greeting}{1}{symbol}%
\getdata{greeting}{2}{string}\getdata{greeting}{2}{symbol}%
\getdata{greeting}{3}{string}\getdata{greeting}{3}{symbol}

\end{document}

在此处输入图片描述

如果你担心行尾没有保护,别担心。你可以使用

\ifcase\numexpr#1\relax

相反,如果您不打算只将明确的数字传递给\getdata

一种expl3实现,具有用于存储数据的稍微更简单的语法。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\newdata}{mmm}
 {% #1 = name for collection, #2 = subname, #3 = data
  \data_new:nnn { #1 } { #2 } { #3 }
 }
\NewExpandableDocumentCommand{\getdata}{mmm}
 {% #1 = name of collection, #2 = index, #3 = key
  \prop_item:cn {g_data_#1_#3_prop} { #2 }
 }

\seq_new:N \l__data_temp_seq
\cs_generate_variant:Nn \prop_gput:Nnn { cx }

\cs_new_protected:Nn \data_new:nnn
 {
  \prop_new:c {g_data_#1_#2_prop}
  \seq_set_from_clist:Nn \l__data_temp_seq { #3 }
  \seq_indexed_map_inline:Nn \l__data_temp_seq
   {
    \prop_gput:cxn {g_data_#1_#2_prop} { \int_eval:n { ##1 - 1 } } { ##2 }
   }
 }
\ExplSyntaxOff

\newdata{hello}{string}{Hello,world}
\newdata{hello}{symbol}{{, },!}

\newdata{greeting}{string}{Nice,to,meet,you}
\newdata{greeting}{symbol}{{ },{ },{ },{.}}

\begin{document}

\getdata{hello}{0}{string}\getdata{hello}{0}{symbol}%
\getdata{hello}{1}{string}\getdata{hello}{1}{symbol}

\getdata{greeting}{0}{string}\getdata{greeting}{0}{symbol}%
\getdata{greeting}{1}{string}\getdata{greeting}{1}{symbol}%
\getdata{greeting}{2}{string}\getdata{greeting}{2}{symbol}%
\getdata{greeting}{3}{string}\getdata{greeting}{3}{symbol}

\end{document}

相关内容