编辑

编辑

与本网站上的大多数问题不同,我的问题是我的代码编译时没有错误,但我不希望这样。

我希望能够检查是否\command已定义,如果已定义则执行某些操作,如果未定义则不执行任何操作。如果未定义则不想\command设置\relax。如果未定义则我不希望代码产生任何效果。

这是一个例子。在这种情况下,很容易解决这个问题,所以这只是为了说明目的。也就是说,这个特定案例本身并不是一个问题——它只是一个用来说明问题的简单例子。

\documentclass{article}
\makeatletter
  \@ifundefined{chapter}{}{\renewcommand\chapter[1]{turtles}}
\makeatother
\usepackage{kantlipsum}
\begin{document}
\chapter{a}
\kant[1-10]
\end{document}

正如我所提到的,在这种特殊情况下,有一个简单的解决方法:我可以检查是否\@chapter已定义,并使用其定义作为的代理\chapter

但是有没有办法检查是否\chapter已定义,而无需将其设置为\relax未定义或仅使用代理间接检查?

编辑

这是讨论中提到的第三个案例哪里\ifdefined...\fi会出现问题,但该\ifdef{}{}{}方法可以很好地替代\@ifundefined{}{}{}原始方法。由提供要求

\documentclass{article}
\makeatletter
% \usepackage{etoolbox}% for \ifdef method
% \ifdef{\chapter}{% Werner's comment on Alan Munn's answer - this method works well
\@ifundefined{chapter}{}{% original - works but \chapter no longer gives an error as it is set to \relax
% \ifdefined\chapter%ref.: Alan Munn's answer at https://tex.stackexchange.com/a/268467/ - unfortunately does not work here (at least, not with the knowledge I have to implement it)
  \renewcommand\chapter{%
          \if@openright
                  \cleardoublepage
          \else
                  \clearpage
          \fi
          \thispagestyle{plain}%
          \global\@topnum\z@
          \@afterindentfalse
          \secdef\@chapter\@schapter}%  end \renewcommand\chapter
  \def\@chapter[#1]#2{%
          \ifnum \c@secnumdepth >\m@ne
                  \if@mainmatter
                          \refstepcounter{chapter}%
                          \typeout{\@chapapp\space\thechapter.}%
                          \addcontentsline{toc}{chapter}%
                          {\protect\numberline{\thechapter}#1}%
                  \else
                          \addcontentsline{toc}{chapter}{#1}%
                  \fi
          \else
                  \addcontentsline{toc}{chapter}{#1}%
          \fi
          \chaptermark{#1}%
          \addtocontents{lof}{\protect\addvspace{10\p@}}%
          \addtocontents{lot}{\protect\addvspace{10\p@}}%
          \if@twocolumn
                  \@topnewpage[\@makechapterhead{#2}]%
          \else
                  \@makechapterhead{#2}%
                  \@afterheading
          \fi}% end definition of \@chapter
  \def\@makechapterhead#1{%
          \vspace*{50\p@}%
          {%
                  \parindent \z@ \raggedright \normalfont
                  \ifnum \c@secnumdepth >\m@ne
                          \if@mainmatter
                                  \fontsize{\@xivpt}{14}\mdseries\centering\scshape{\@chapapp\space \thechapter}%
                                  \par\nobreak
                                  \vskip 20\p@
                          \fi
                  \fi
                  \interlinepenalty\@M
                  \fontsize{\@xivpt}{18}\bldsc\centering #1\par\nobreak
                  \vskip 40\p@
          }%
  }%    end definition \@makechapterhead
  \def\@schapter#1{%
          \if@twocolumn
                  \@topnewpage[\@makeschapterhead{#1}]%
          \else
                  \@makeschapterhead{#1}%
                  \@afterheading
          \fi}% end definition \@schapter
  \def\@makeschapterhead#1{%
          \vspace*{50\p@}%
          {%
                  \parindent \z@ \raggedright
                  \normalfont
                  \interlinepenalty\@M
                  \fontsize{\@xivpt}{18}\bldsc\centering #1\par\nobreak
                  \vskip 40\p@
          }%
  }%    end definition \@makeschapterhead
}%      end of stuff to do only if \chapter is defined - \@ifundefined method
% }{}% \ifdef method
% \fi% \ifdefined method
\makeatother
\begin{document}
  \chapter{a}
\end{document}

答案1

最简单的方法是使用 e-TeX\ifdefined宏:

\documentclass{article}
\ifdefined\chapter\renewcommand\chapter[1]{turtles}\fi
\usepackage{kantlipsum}
\begin{document}
\chapter{a}
\kant[1-10]
\end{document}

如果其中有其他条件,则此方法将不起作用(因此是更大问题的根源),在这种情况下,etoolbox最好使用 Werner 的解决方案:

\documentclass{article}
\usepackage{etoolbox}
\makeatletter
  \ifdef{\chapter}{
    \renewcommand{\chapter}[1]{%
    \if@openright
        \cleardoublepage
     \else
        \clearpage
      \fi
    turtles}
}{}
\makeatother
\usepackage{kantlipsum}
\begin{document}
\chapter{a}
\kant[1-10]
\end{document}

答案2

当然,你会失去可扩展性,但这是“简单”的方法:

\documentclass
%{book}
{article}

\makeatletter
\begingroup
\@ifundefined{chapter}{\endgroup}{\endgroup\renewcommand\chapter[1]{turtles}}
\makeatother

\usepackage{kantlipsum}

\begin{document}

\chapter{a}
\kant[1-10]

\end{document}

如果命令已经出现在的范围内,则带有\ifdeffrom 的方法可能会给出错误的结果,因此它与 等同。etoolbox\@ifundefined\relax

可扩展测试应该以\ifdefined和为分支,在本例中,查看命令是否等同于\relax

\makeatletter
\newcommand{\x@ifundefined}[3]{%
   \ifcsname #1\endcsname
     %either defined or \relax
     \expandafter\@firstoftwo
   \else
     %undefined
     \expandafter\@secondoftwo
   \fi
   {\x@ifrelax{#1}{#2}{#3}}{#2}%
 }
\newcommand{\x@ifrelax}[3]{%
  \expandafter\ifx\csname #1\endcsname\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {#2}{#3}%
}
\makeatletter

测试表明我们没问题:

\makeatletter
\edef\foo{\x@ifundefined{bbcccddd}{undef}{def}}\show\foo
\edef\foo{\x@ifundefined{relax}{undef}{def}}\show\foo
\edef\foo{\x@ifundefined{mbox}{undef}{def}}\show\foo
\show\bbcccddd
\makeatother

将输出

> \foo=macro:
->undef.
l.26 ...fundefined{bbcccddd}{undef}{def}}\show\foo

? 
> \foo=macro:
->undef.
l.27 ...x@ifundefined{relax}{undef}{def}}\show\foo

? 
> \foo=macro:
->def.
l.28 ...\x@ifundefined{mbox}{undef}{def}}\show\foo

? 
> \bbcccddd=undefined.
l.29 \show\bbcccddd

相关内容