我正在尝试使用 /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}