![如何从宏参数中删除前导和尾随空格?](https://linux22.com/image/259436/%E5%A6%82%E4%BD%95%E4%BB%8E%E5%AE%8F%E5%8F%82%E6%95%B0%E4%B8%AD%E5%88%A0%E9%99%A4%E5%89%8D%E5%AF%BC%E5%92%8C%E5%B0%BE%E9%9A%8F%E7%A9%BA%E6%A0%BC%EF%BC%9F.png)
考虑这个最小的工作示例:
\documentclass[a4paper]{amsart}
\usepackage{tikz}
\tikzset{graph/.style = {every node/.style = { draw,
shape = circle,
fill = black,
minimum size = 0.8mm,
inner sep = 0mm,
label distance = 0.8mm
}}}
\newcommand{\circumferencenode}[4][]{\node (#1#2) at (#4: #3) [label = #4: $#2$] {};}
\newlength{\gr} % graph radius
\setlength{\gr}{15mm}
\begin{document}
\begin{tikzpicture}[graph]
\circumferencenode{0}{\gr}{ 90}
\circumferencenode{1}{\gr}{ 30}
\circumferencenode{2}{\gr}{330}
\circumferencenode{3}{\gr}{270}
\circumferencenode{4}{\gr}{210}
\circumferencenode{5}{\gr}{150}
\draw (0) -- (1) -- (2) -- (3) -- (4) -- (5) -- (0);
\end{tikzpicture}
\vspace*{10mm}
\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr}{ 90}
\circumferencenode{ 3}{\gr}{ 0}
\circumferencenode{ 4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
\end{document}
输出结果如下:
如您所见,第二个示例看起来很奇怪。节点的放置出了问题。我本想问为什么会发生这种情况,但一些实验表明,如果将第二张图片更改为以下内容:
\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr}{90}
\circumferencenode{3}{\gr}{0}
\circumferencenode{4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
或者甚至是这样的:
\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr} {90}
\circumferencenode {3}{\gr} {0}
\circumferencenode {4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
那么问题就消失了,第二张图表就如人们预期的那样出现了。
因此问题显然是宏参数中的前导空格。我可以去掉它们,这样就没问题了。但是,我很高兴按照\circumferencenode
我原来的方式安排对宏的调用,这样数字和括号组就可以垂直对齐。因此,更好的解决方案是找出如何从宏参数中删除前导和尾随空格。
- 为何原来的例子不能正常工作?
- 如何从我定义的宏的参数中删除前导和尾随空格?
答案1
使用内核宏修剪空格可能很困难;这时 LaTeX3 可以提供帮助:
\documentclass[a4paper]{amsart}
\usepackage{tikz,xparse}
\tikzset{graph/.style = {every node/.style = { draw,
shape = circle,
fill = black,
minimum size = 0.8mm,
inner sep = 0mm,
label distance = 0.8mm
}}}
%%% We need a "classical" definition, because of the colons in the replacement text
\newcommand{\circumferencenodeinner}[4]{\node (#1#2) at (#4: #3) [label = #4: $#2$] {};}
%%% Now we go with LaTeX3
\ExplSyntaxOn
\NewDocumentCommand{\circumferencenode}{ O{} m m m }
{
\hammerite_circumference_node:nxnx
{ #1 }
{ \tl_trim_spaces:n { #2 } }
{ #3 }
{ \tl_trim_spaces:n { #4 } }
}
\cs_set_eq:NN \hammerite_circumference_node:nnnn \circumferencenodeinner
\cs_generate_variant:Nn \hammerite_circumference_node:nnnn { nxnx }
\ExplSyntaxOff
\newlength{\gr} % graph radius
\setlength{\gr}{15mm}
\begin{document}
\noindent\begin{minipage}{.4\textwidth}
%%% Just to give an example we use the old definition
\newcommand{\circumferencenodeold}[4][]{\node (#1#2) at (#4: #3) [label = #4: $#2$] {};}
\textbf{Old}
\begin{tikzpicture}[graph]
\circumferencenodeold{0}{\gr}{ 90}
\circumferencenodeold{1}{\gr}{ 30}
\circumferencenodeold{2}{\gr}{330}
\circumferencenodeold{3}{\gr}{270}
\circumferencenodeold{4}{\gr}{210}
\circumferencenodeold{5}{\gr}{150}
\draw (0) -- (1) -- (2) -- (3) -- (4) -- (5) -- (0);
\end{tikzpicture}
\vspace*{10mm}
\begin{tikzpicture}[graph]
\circumferencenodeold{02}{\gr}{ 90}
\circumferencenodeold{ 3}{\gr}{ 0}
\circumferencenodeold{ 4}{\gr}{270}
\circumferencenodeold{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
\end{minipage}\vrule\qquad
\noindent\begin{minipage}{.4\textwidth}
\textbf{New}
\begin{tikzpicture}[graph]
\circumferencenode{0}{\gr}{ 90}
\circumferencenode{1}{\gr}{ 30}
\circumferencenode{2}{\gr}{330}
\circumferencenode{3}{\gr}{270}
\circumferencenode{4}{\gr}{210}
\circumferencenode{5}{\gr}{150}
\draw (0) -- (1) -- (2) -- (3) -- (4) -- (5) -- (0);
\end{tikzpicture}
\vspace*{10mm}
\begin{tikzpicture}[graph]
\circumferencenode{02}{\gr}{ 90}
\circumferencenode{ 3}{\gr}{ 0}
\circumferencenode{ 4}{\gr}{270}
\circumferencenode{15}{\gr}{180}
\draw (02) -- (3) -- (4) -- (15) -- (02);
\end{tikzpicture}
\end{minipage}
\end{document}
由于替换文本中有冒号,因此该命令\circumferencenodeinner
以标准方式定义;请注意不指定了可选参数;它只是一个辅助宏,将转换为\let
具有 LaTeX3 名称的宏,以便nxnx
可以创建带后缀的变体;这x
意味着相应的参数已完全展开。实际上,当我们最终调用它时,参数#2
和#4
被传递给\tl_trim_spaces:n
它,它的工作正是修剪前导和尾随空格,然后按原样传递其余部分。
答案2
正如 Peter Grill 所说,命令定义的节点名称\circumferencenode
与绘制图形时使用的节点名称之间存在冲突。那么第一个问题的答案是,您正在定义节点" 3"
(注意前导空格)并使用(3)
没有前导空格的节点。
这是应与提供的定义一起使用的绘制命令:
\draw (02) -- ({ 3}) -- ({ 4}) -- (15) -- (02);
我不知道第二个问题的简单答案:(。