我不明白为什么这段代码没有产生我在输出中描述的内容。
\documentclass{article}
\newcommand{\defaultvalue}{\textit{initialvalue}} %indentation pour les (sous)-questions non-numérotées
\newcommand{\mycounter}{\defaultvalue}
\newcommand{\inmain}{1}
\newcommand{\question}[2][\defaultvalue]{ %Question
\textbf{Question #1 :} #2
\ifx\inmain1 \renewcommand{\mycounter}{#1} \fi
}
\begin{document}
mycounter has value \mycounter \\
\question[1.a)]{
\textit{inmain} has value \inmain, therefore I would expect \textit{mycounter} to take value \textit{1.a)} after this.\\
}
However, \textit{mycounter} still has value \mycounter
\end{document}
这段代码被缩小了,以便只暴露我面临的问题。但是,为了预测替代建议,这里是它的底部,以防万一它有用。我正在尝试重写一个非常灵活的手动计数系统,以满足这里不相关的需求。我有一个\question
命令和一个\subquestion
调用的命令\question
(这在我想重新设计某些东西时很有用)。这些命令有可选参数,可以启用手动编号,我希望子问题可以选择性地携带主问题的编号。因为\subquestion
调用\question
,我需要一个控制序列\question
来确保在\subquestion
调用时计数器不会改变\question
。但它不起作用。
答案1
你有:
\ifx\inmain1 \renewcommand{\mycounter}{#1} \fi
不\ifx
触发token的扩展。\ifx
仅比较token的含义。
\show\inmain
收益\inmain
具有以下含义:
> \inmain=\long macro:
->1.
\show1
收益1
具有以下含义:
> the character 1.
含义是不是平等的...
顺便说一句:在将数字字符标记1
为类别代码 12(其他)的显式字符标记后,(La)TeX 的读取装置处于状态 M(行中间)。因此,后面的空格字符1
被标记为显式空格标记。(类别代码 10(空格)和字符代码 32 的显式字符标记。32 是 (La)TeX 内部字符编码方案中空格字符的代码点编号,在传统 TeX 引擎中为 ASCII,在基于 XeTeX 或 LuaTeX 的 TeX 引擎中为 UTF-8。)
如果条件为真,则后面的显式空格标记1
将作为“真”分支的第一个标记传递。在水平模式/非受限水平模式下,它会产生水平粘连,这可能是不受欢迎的。
这同样适用于右花括号后面/之前的空格字符,\fi
只是生成的显式空格标记将作为“真”分支的最后一个标记传递。
因此,真正的分支由一个显式空间标记、一个\renewcommand
赋值和另一个显式空间标记组成。在水平模式/非受限水平模式下,两个显式空间标记都会产生水平粘合。
如果你想比较两个数字/两个 TeX-⟨数字⟩-我建议使用的数量\ifnum
:
\documentclass{article}
\newcommand{\defaultvalue}{\textit{initialvalue}} %indentation pour les (sous)-questions non-numérotées
\newcommand{\mycounter}{\defaultvalue}
\newcommand{\inmain}{1}
\newcommand{\question}[2][\defaultvalue]{%
\textbf{Question #1 :} #2%
\ifnum\inmain=1 %
\renewcommand{\mycounter}{#1}%
\fi
}
\begin{document}
mycounter has value \mycounter\\
\question[1.a)]{%
\textit{inmain} has value \inmain, therefore I
expect \textit{mycounter} to take value
\textit{1.a)} after this.\\
}%
And voil\`a: \textit{mycounter} has value \mycounter.
\end{document}
使用\ifnum\inmain=1 %
两个 TeX-⟨数字⟩-数量进行比较。当收集 TeX 的第一个标记时-⟨数字⟩-数量,以及收集更多 TeX 标记时-⟨数字⟩-数量最终会变成来自集合 {1,2,3,4,5,6,7,8,9,0} 的字符标记序列,扩展不会被抑制。因此,\inmain
当 LaTeX 开始收集\ifnum
的第一个 TeX-⟨数字⟩-数量。这将产生显式 catcode-12(other)-character-token 1
,它将被用作集合 {1,2,3,4,5,6,7,8,9,0} 中字符标记序列的第一个元素。然后=
找到 (explicit character-token of catcode 12(other)),这将终止收集属于该序列的更多数字的过程。不会=
被丢弃。然后 LaTeX 开始收集 的\ifnum
第二个 TeX-⟨数字⟩-数量。因此,后面的空格字符1
也被标记为显式空格标记。但字符标记再次1
被视为元素/属于集合 {1,2,3,4,5,6,7,8,9,0} 中的字符标记序列的第一个元素。因此,空格标记被视为终止收集属于该序列的更多数字的过程的事物。与
其他终止搜索更多 TeX- 数字的标记不同,⟨数字⟩-由集合 {1,2,3,4,5,6,7,8,9,0} 中的字符标记序列形成的数量,例如,=
终止数字序列的显式空格标记将被默默丢弃/从标记流中删除。
\if
关于原语和\ifcat
工作原理的评论:
\if
比较字符标记的字符代码。\if
在进行比较之前,会触发可扩展标记的扩展。非隐式字符标记的不可扩展控制序列将被视为具有相同的字符代码,该字符代码与字符标记可能具有的所有字符代码不同。
\ifcat
比较字符标记的类别代码。\ifcat
在进行比较之前,会触发可扩展标记的扩展。非隐式字符标记的不可扩展控制序列将被视为具有相同的类别代码,该类别代码与字符标记可能具有的所有类别代码不同。
答案2
你的代码很奇怪,我没有太多时间详细解释。\ifx\inmain1
如果你以前这样做过,那么结果会是真的\let\ifmain1
,但事实并非如此(可能也不可取)。\ifx
不会扩展后面的内容。你可以使用它\ifnum
进行整数比较;\ifnum
在查找 〈number〉 时扩展宏(参见 TeX 语法)。
由于您要打印 的值\inmain
,因此我将首先在此处使用此技巧。请注意代码中的虚假空格,但请注意,\ifnum\inmain=1
下面后面的空格是故意的并且很有用:根据 TeX 语法,它终止 〈number〉1
。它不会出现在输出中。这是很好的做法,但您需要了解原因。
\documentclass{article}
\newcommand{\defaultvalue}{\textit{initialvalue}}
\newcommand{\mycounter}{\defaultvalue}
\newcommand{\inmain}{1}
\newcommand{\question}[2][\defaultvalue]{% Question
\textbf{Question #1 :}~#2%
\ifnum\inmain=1 \renewcommand{\mycounter}{#1}\fi
}
\begin{document}
mycounter has value \mycounter \\
\question[1.a)]{%
\textit{inmain} has value \inmain, therefore I would expect
\textit{mycounter} to take value \textit{1.a)} after this.\\
}
Indeed, \textit{mycounter} has value \mycounter.
\end{document}
更惯用的方法可能是用来\newif\ifinmain
声明\inmaintrue
或\inmainfalse
设置标志,并且\ifinmain ... \else ...\fi
使用它(可选\else
)。此外,你滥用了术语“计数器”(我的意思是,你的\mycounter
宏不是 LaTeX 计数器),并且行
\newcommand{\mycounter}{\defaultvalue}
可能不会做你想要的(它将控制序列标记存储\defaultvalue
为宏的替换文本\mycounter
;\mycounter
是不是此时展开)。如果你定义\defaultvalue
为数字,你可能想要这样的东西:
\newcommand{\defaultvalue}{3}
\edef\mycounter{\defaultvalue}
如果您确实想要在的替换文本中格式化命令\defaultvalue
,则可以使用:
\makeatletter
\newcommand{\defaultvalue}{\textit{3}}
\protected@edef\mycounter{\defaultvalue}
\makeatother
整理最后的建议得出:
\documentclass{article}
\makeatletter
\newcommand{\defaultvalue}{\textit{3}}
\protected@edef\mycounter{\defaultvalue}
\newif\ifinmain
\inmaintrue
\newcommand{\question}[2][\defaultvalue]{% Question
\textbf{Question #1 :}~#2%
\ifinmain\renewcommand{\mycounter}{#1}\fi
}
\makeatother
\begin{document}
mycounter has value \mycounter \\
\question[1.a)]{%
\texttt{\textbackslash ifinmain} is \texttt{\textbackslash iftrue}, therefore
\textit{mycounter} will take value \textit{1.a)} after this.\\
}
Indeed, \textit{mycounter} has value \mycounter.
\end{document}
但我再说一遍,这一切看起来有点奇怪。也许有更好的方法可以满足您的需要,也许是使用enumitem
。我担心这是一个 XY 问题。