使用 `\@ifnextchar` 来提前查找 `.`

使用 `\@ifnextchar` 来提前查找 `.`

我试图编写一个命令,检查调用后的下一个字符是否是点.),但似乎无法弄清楚。

我对 LaTeX 还不太熟悉,我编写了一个命令来对“世纪”的书写进行风格化。该命令.默认在末尾添加字符。问题是,如果我在句末使用它,则会得到两个点(..)。我尝试提前查找下一个字符以查看它是否为点,以便有条件地决定是否在末尾添加一个点。我尝试使用 marco \@ifnextchar,但似乎无法弄明白(尽管搜索了 TeX StackExchange 和文档)。我做错了什么?

使用最少的工作示例进行更新

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage{lmodern}
\usepackage{rotating}

\newcommand{\scl}[1]{%
    % #1 : the century in question
    #1%
    \ifthenelse{\equal{#1}{I}}{\up{er}}{\up{ème}}%
    ~s%
    \@ifnextchar.{}{.}% this is the line that causes a problem: checks if next char is `.`
}

\begin{document}
    This is where I use the command \scl{XIX}. Ideally, the command 
    should not have added a `.` since it is followed by a dot.
\end{document}

输出:

我刚刚发现,如果不使用rotating(在我执行此命令之前已加载),我会收到以下错误:Undefined control sequence. This is where I use the command \scl{XIX}。使用时rotating,这是输出:

输出

供参考,我在 TeXstudio 上使用 XeLaTeX。

感谢您的帮助 !

答案1

你需要@一封信:

在此处输入图片描述

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
% no: (ignored with xetex) \usepackage[utf8x]{inputenc}
% no: does real harm with xetex (breaks hyphenation) \usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage{lmodern}
\usepackage{rotating}

\makeatletter
\newcommand{\scl}[1]{%
    % #1 : the century in question
    #1%
    \ifthenelse{\equal{#1}{I}}{\up{er}}{\up{ème}}%
    ~s%
    \@ifnextchar.{}{. }% this is the line that causes a problem: checks if next char is `.`
}

\makeatother

\begin{document}
    This is where I use the command \scl{XIX}. Ideally, the command 
    should not have added a `.` since it is followed by a dot.

    This is where I use the command \scl{XIX} ideally, the command 
    should  have added a `.` since it is not followed by a dot.
\end{document}

答案2

您缺少\makeatletter允许\@ifnextchar正确解释的权利。

正如其他人所评论的那样,永远不要使用utf8x(任何引擎)并且不要加载或fontenc使用lmodernUnicode 引擎(XeLaTeX 或 LuaLaTeX)。

您的命令缺乏稳健性,例如,在章节标题或说明中不起作用。使用

\DeclareRobustCommand{\scl}[1]{...}

反而。

一个更加强大的实现expl3

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage{fontspec}

\ExplSyntaxOn

\NewDocumentCommand{\scl}{m}
 {% #1 : the century in question
  #1
  \str_if_eq:nnTF { I } { #1 }{\up{er}}{\up{ème}}
  \nobreakspace s
  \peek_charcode:NF . { . }
}
\ExplSyntaxOff

\begin{document}

This is where I use the command \scl{XIX}. Ideally, the command 
should not have added a `.' since it is followed by a period.

\end{document}

在此处输入图片描述

不过,我认为输入标准数字比输入罗马数字更容易。

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage{fontspec}

\ExplSyntaxOn

\NewDocumentCommand{\scl}{m}
 {% #1 : the century in question in standard numeric form
  \int_to_Roman:n { #1 }
  \int_compare:nTF { #1 == 1 }{\up{er}}{\up{ème}}
  \nobreakspace s
  \peek_charcode:NF . { . }
}
\ExplSyntaxOff

\begin{document}

This is where I use the command \scl{19}. Ideally, the command 
should not have added a `.' since it is followed by a period.

\end{document}

输出是一样的。

甚至可以同时拥有两种类型的输入(尽管我并不推荐这样做)。

\documentclass[a4paper,12pt,twoside]{book}
\usepackage[english, french]{babel}
\usepackage{fontspec}

\ExplSyntaxOn

\NewDocumentCommand{\scl}{m}
 {
  \regex_match:nnTF { \A [0-9]* \Z } { #1 }
   {% the input is numeric
    \int_to_Roman:n { #1 }
    \int_compare:nTF { #1 == 1 }{\up{er}}{\up{ème}}
   }
   {% assume the input is a Roman numeral
    #1
    \str_if_eq:nnTF { I } { #1 }{\up{er}}{\up{ème}}
   }
  \nobreakspace s
  \peek_charcode:NF . { . }
}
\ExplSyntaxOff

\begin{document}

This is where I use the command \scl{19}. Ideally, the command 
should not have added a `.' since it is followed by a period.

This is where I use the command \scl{XIX}. Ideally, the command 
should not have added a `.' since it is followed by a period.

\end{document}

生成了相同文本的两个副本。

相关内容