确定#1 的第一个非空格字符是否是字母?

确定#1 的第一个非空格字符是否是字母?

假设我有一个带有\title命令的类文件,我想检查标题是否以字母开头,而不是以数学或数字或符号开头。我该怎么做?

这是我的 MnWE,的语法\@iffirstnotletter当然可以进行合理的修改。如果它也能识别重音字符,那就更好了,但这不是必需的。

\documentclass{article}

\makeatletter
\newcommand\@iffirstnotletter[3]{#2} % <-- should be modified

\renewcommand\title[1]{\@iffirstnotletter{#1}{%
    \GenericWarning{}{Please start the title with a letter!}%
  }{}%
  \def\@title{#1}%
}%
\makeatother

\title{Ahoj}

\begin{document}

\maketitle

\end{document}

编辑:

我的第一个想法是这样的:

\def\ONETWO#1#2\ENDONETWO{#1} % strips the 1st token of
                             % whatever is between `\ONETWO...\ENDONETWO`
\def\@iffirstnotletter#1#2#3{%
  % checks the \catcode of the 1st token of #1 
  \expandafter\ifnum\expandafter\the\expandafter\catcode
    \expandafter`\csname\ONETWO#1\ENDONETWO\endcsname=11\relax
  #3\else#2
\fi}

但它有一个疯狂的行为,例如,当第一件事是\(作为数学模式的开始时:然后它给出! Missing \endcsname inserted.

答案1

用 进行长检查\futurelet;这涵盖了 UTF-8 多字节字符,但如果参数中的第一个项是多字节字符,它无论如何都会给出“好”,因为“UTF-8 字母”的概念没有明确定义。另一方面,在“\'{U}jezd”等情况下,这将失败。可以添加可接受的控制序列列表来应对这种情况。

\documentclass{article}
\usepackage[utf8]{inputenc}

\makeatletter
\newcommand\ifletter[1]{%
  \futurelet\letter@token\checknextletter#1\relax\@nil
}
\def\checknextletter{%
  \ifcat\noexpand\letter@token a%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\@gobbleto@nil{good}}%
  {\checknextutfii}%
}

\def\checknextutfii{%
  \expandafter\ifx\expandafter\UTFviii@two@octets\letter@token
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\@gobbleto@nil{good}}%
  {\checknextutfiii}%
}

\def\checknextutfiii{%
  \expandafter\ifx\expandafter\UTFviii@three@octets\letter@token
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\@gobbleto@nil{good}}%
  {\checknextutfiv}%
}

\def\checknextutfiv{%
  \expandafter\ifx\expandafter\UTFviii@four@octets\letter@token
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\@gobbleto@nil{good}}%
  {\GenericWarning{}{Please start the title with a letter}%
   \@gobbleto@nil{bad}}%
}

\long\def\@gobbleto@nil#1#2\@nil{#1}

\makeatother

\begin{document}

\verb*'foo': \ifletter{foo} = good

\verb*' foo': \ifletter{ foo} = bad

\verb*'f12': \ifletter{f12} = good

\verb*'1oo': \ifletter{1oo} = bad

\verb*'$math$': \ifletter{$math$} = bad

\verb*'\(math\)': \ifletter{\(math\)} = bad

\verb*'äoo': \ifletter{äoo} = good

\verb*'\relax': \ifletter{\relax} = bad

\verb*'': \ifletter{} = bad

\end{document}

在此处输入图片描述

答案2

这是我的尝试似乎涵盖基础知识:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}% I don't want to define \ifdefmacro

\makeatletter
\newcommand\ifletter[1]{%
  \ifcat#1a\@empty
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\newcommand\iffirstletter[1]{\@iffirstletter#1\@empty\q@stop}
\def\@iffirstletter#1#2\q@stop{%
  \ifdefmacro{#1}  % to prevent error messages from accented letters, they're false
    {\@secondoftwo}% starts with macro...
    {\ifletter{#1}}%
}
\makeatother

\begin{document}

!\iffirstletter{foo}{true}{false}! = true

!\iffirstletter{ foo}{true}{false}! = true

!\iffirstletter{f12}{true}{false}! = true

!\iffirstletter{1oo}{true}{false}! = false

!\iffirstletter{$math$}{true}{false}! = false

!\iffirstletter{\(math\)}{true}{false}! = false

!\iffirstletter{äoo}{true}{false}! = false % this may be misleading

!\iffirstletter{\relax}{true}{false}! = false

!\iffirstletter{}{true}{false}! = false

\end{document}

相关内容