可能只是另一个 gdef 扩展问题

可能只是另一个 gdef 扩展问题

延续邮政,我尝试使以下(简化的)代码正常工作。

  • \timedelta 使用 2 个参数。
  • 使用 \gdef 作为第一个参数是可以的。
  • 使用 \gdef 作为第二个参数是 Nok。

我无法摆脱例外

21:段落在 \timedelta@i 完成之前结束。[]

\documentclass{article}

\makeatletter
\newcommand{\timedelta}[2]{\romannumeral0\timedelta@i#1:#2:}%
\def\timedelta@i #1:#2:#3:#4:%
   {\expandafter\timedelta@ii\the\numexpr#3*60+#4-#1*60-#2.}%
\def\timedelta@ii#1{\expandafter\timedelta@iii\the\numexpr
                    \if-#11440\fi #1}%
\def\timedelta@iii#1.{\expandafter\timedelta@iv\the\numexpr
                    (#1 + 30)/60 -1.#1.}%
\def\timedelta@iv #1.#2.{\expandafter\timedelta@v\the\numexpr
                    100+#2-60*#1\expandafter.\the\numexpr100+#1.}
\def\timedelta@v 1#1.1#2.{ #2:#1}
\makeatother

\begin{document}


\gdef\routeStart{01:27}
\expandafter\timedelta\expandafter{\routeStart}{01:27}% ok

\gdef\routeStop{01:27}
\expandafter\timedelta{16:03}\expandafter{\routeStop}% nok -> Paragraph ended before \timedelta@i was complete.

\end{document}

我对第一个答案的编辑

如何“扩展”这两个论点?谢谢!

\timedelta{\routeStart}{\routeStop}

答案1

这可能会有所帮助:

\documentclass{article}

\makeatletter
\newcommand{\timedelta}[2]{\romannumeral0\timedelta@i#1:#2:}%
\def\timedelta@i #1:#2:#3:#4:%
   {\expandafter\timedelta@ii\the\numexpr#3*60+#4-#1*60-#2.}%
\def\timedelta@ii#1{\expandafter\timedelta@iii\the\numexpr
                    \if-#11440\fi #1}%
\def\timedelta@iii#1.{\expandafter\timedelta@iv\the\numexpr
                    (#1 + 30)/60 -1.#1.}%
\def\timedelta@iv #1.#2.{\expandafter\timedelta@v\the\numexpr
                    100+#2-60*#1\expandafter.\the\numexpr100+#1.}
\def\timedelta@v 1#1.1#2.{ #2:#1}
\makeatother

\newcommand\timeatled[2]{\timedelta{#2}{#1}}

\newcommand\timedeltaON[2]{\expandafter\timedelta\expandafter{#1}{#2}}
\newcommand\timedeltaNO[2]{\expandafter\timeatled\expandafter{#2}{#1}}
\newcommand\timedeltaOO[2]{\expandafter\timedeltaNO\expandafter{#1}{#2}}

\newcommand\timedeltaXN[2]
    {\expandafter\timedelta\expandafter{\romannumeral-`0#1}{#2}}
\newcommand\timedeltaNX[2]
    {\expandafter\timeatled\expandafter{\romannumeral-`0#2}{#1}}
\newcommand\timedeltaXX[2]
    {\expandafter\timedeltaNX\expandafter{\romannumeral-`0#1}{#2}}


\begin{document}


\gdef\routeStart{01:27}
\timedeltaON{\routeStart}{01:27}% ok

\timedeltaOO{\routeStart}{01:27}% ok

\timedeltaXX{\routeStart}{01:27}% ok

\gdef\routeStop{01:27}

\timedeltaNO{16:03}{\routeStop}% ok

\timedeltaOO{16:03}{\routeStop}% ok

\timedeltaXX{16:03}{\routeStop}% ok

\end{document}

在此处输入图片描述

LaTeX3 具有“生成变体”通用功能,可以一劳永逸地解决这些问题......

请注意,它\timedeltaXX可以与自身嵌套(即作为其自身的第一个或第二个参数)。

答案2

您误用了\expandafter。扩展宏的第二个参数的一种方法是,定义第二个宏,其中包含宏及其第一个参数,然后\expandafter在执行第二个宏之前使用 s 扩展参数:

\documentclass{article}

\makeatletter
\newcommand{\timedelta}[2]{\romannumeral0\timedelta@i#1:#2:}%
\def\timedelta@i #1:#2:#3:#4:%
   {\expandafter\timedelta@ii\the\numexpr#3*60+#4-#1*60-#2.}%
\def\timedelta@ii#1{\expandafter\timedelta@iii\the\numexpr
                    \if-#11440\fi #1}%
\def\timedelta@iii#1.{\expandafter\timedelta@iv\the\numexpr
                    (#1 + 30)/60 -1.#1.}%
\def\timedelta@iv #1.#2.{\expandafter\timedelta@v\the\numexpr
                    100+#2-60*#1\expandafter.\the\numexpr100+#1.}
\def\timedelta@v 1#1.1#2.{ #2:#1}
\makeatother

\begin{document}


\gdef\routeStart{01:27}
\expandafter\timedelta\expandafter{\routeStart}{01:27}% ok

\gdef\routeStop{01:27}
\def\tempmacro{\timedelta{16:03}}%
\expandafter\tempmacro\expandafter{\routeStop}%
%\expandafter\timedelta{16:03}\expandafter{\routeStop}% nok -> Paragraph ended before \timedelta@i was complete.

\end{document}

\expandafter的作用是(描述不准确)在第一个标记之前扩展第二个标记(如果它可以扩展)。在您的示例中,第一个参数的每个字符都是一个标记,因此正确的方法是使用 跳过每个字符\expandafter,因此在这种情况下正确的使用方法\expandafter是:

\expandafter\timedelta\expandafter{\expandafter1\expandafter6\expandafter:\expandafter0\expandafter3\expandafter}\expandafter{\routeStop}%

这真的很麻烦...

相关内容