宏 \ifx \else - 性别输出交替(请帮忙)

宏 \ifx \else - 性别输出交替(请帮忙)

我尝试编写一些代码,获取我的动物患者的性别(已绝育的雄性、已绝育的雌性、未绝育的雄性、未绝育的雌性),并将其应用于使用正确形式的他/她、他/她、他/她的,以自动填充整个文档。

目前,我编写的代码无论性别输入如何都会在男性和女性形式之间交替输出,我不太明白为什么。如能提供任何帮助/故障排除,我将不胜感激。

\documentclass[]{article}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{verbatim}
\usepackage{lmodern}
\usepackage{xspace}
\usepackage{float}
\usepackage{tabularx}
\makeatletter 
\makeatother 

\newif\ifxspace\xspacetrue
\makeatletter
\newif\ifsex@he\sex@hefalse

% macro to get first character of a token
\def\sex@getfirst#1{\sex@fstx#1\empty\empty}
\def\sex@fstx#1#2\empty{%
 \edef\sex@fst{#1}}

\ProcessOptions
% toggle for changing the gender

%macros for comparison
\def\sex@balls{MI} %male - intact, with balls
\def\sex@neut{MC} %male - castrated, no balls
\def\sex@ovs{FI} %female - intact, ovaries
\def\sex@spay{FS} %female - spayed, no ovaries

% command to set gender (takes Male/M Female/F etc. or lowercase version of each)
% expands argument first to allow it to be a macro
\newcommand\setgender[1]{%
\edef\next{\noexpand\sex@setgender{#1}}\next}
\newcommand\sex@setgender[1]{%
\sex@getfirst{#1}
\ifx\sex@fst\sex@balls \global\sex@hefalse 
    \else
    \ifx\sex@fst\sex@neut \global\sex@hefalse
        \else
        \ifx\sex@fst\sex@ovs \global\sex@hetrue
            \else
            \ifx\sex@fst\sex@spay \global\sex@hetrue
                \else
                \global\sex@hetrue 
                %\PackageWarning{he-she}{Invalid value for gender. Using Masculine}
                \fi
            \fi
        \fi
    \fi
}

%SEX - he/she, his/hers, him/her (lowercase and capital)

%Sex toggle - he/she (lower case)
\newcommand*{\heshe}{%
  \leavevmode
  \ifsex@he
    he%
    \global\sex@hefalse%
  \else
    she%
    \global\sex@hetrue%
  \fi
  \ifxspace\xspace\fi
}

%Sex toggle - He/She (capitalized)
\newcommand*{\Heshe}{%
  \leavevmode
  \ifsex@he
    He%
    \global\sex@hefalse%
  \else
    She%
    \global\sex@hetrue%
  \fi
  \ifxspace\xspace\fi
}

%Sex toggle - him/her (lowercase)
\newcommand*{\himher}{%
  \leavevmode
  \ifsex@he
    him%
  %\global\sex@hefalse%
  \else
    her%
    \global\sex@hetrue%
  \fi
  \ifxspace\xspace\fi
}

%Sex toggle - Him/Her (capital)
\newcommand*{\Himher}{%
  \leavevmode
  \ifsex@he
    Him%
    \global\sex@hefalse%
  \else
    Her%
    \global\sex@hetrue%
  \fi
  \ifxspace\xspace\fi
}

%Sex toggle - his/her (lowercase)
\newcommand*{\hisher}{%
  \leavevmode
  \ifsex@he
    his%
    \global\sex@hefalse%
  \else
    her%
    \global\sex@hetrue%
  \fi
  \ifxspace\xspace\fi
}

%Sex toggle - His/Her (capitalized)
\newcommand*{\Hisher}{%
  \leavevmode
  \ifsex@he
    His%
    \global\sex@hefalse%
  \else
    Her%
    \global\sex@hetrue%
  \fi
  \ifxspace\xspace\fi
}


\begin{document}
\begin{tabularx}{\textwidth} { 
  | >{\raggedright\arraybackslash}X 
  | >{\raggedright\arraybackslash}X 
  | >{\raggedright\arraybackslash}X 
  | >{\raggedright\arraybackslash}X | }
 \hline
{\bf Patient name:}  &  ***    & {\bf Sex:}  & \sex@balls \\ %
\hline
\end{tabularx} \\

\heshe \Heshe \himher \Himher \hisher \Hisher

\end{document}

答案1

您的问题不太清楚,但我的猜测是您不希望交替出现他/她的行为(这是您显示的所有代码所做的),并且希望命令在每种情况下都产生指定的性别,如下所示

在此处输入图片描述

\documentclass[]{article}
\usepackage{xspace}

\makeatletter

\newif\ifxspace\xspacetrue

\newif\ifsex@he\sex@hefalse


% #1=MI,MC,FI,FS
\def\setgender#1{%
  \if F\@firstoftwo#1\sex@hefalse\else\sex@hetrue\fi}

%%????\ProcessOptions





%Sex toggle - he/she (lower case)
\newcommand*{\heshe}{%
  \ifsex@he\else s\fi
  he%
  \ifxspace\xspace\fi
}

%Sex toggle - He/She (capitalized)
\newcommand*{\Heshe}{%
  \ifsex@he H\else Sh\fi
  e%
  \ifxspace\xspace\fi
}

%Sex toggle - him/her (lowercase)
\newcommand*{\himher}{%
  h%
  \ifsex@he im\else er\fi
  \ifxspace\xspace\fi
}

%Sex toggle - Him/Her (capital)
\newcommand*{\Himher}{%
  H%
  \ifsex@he im\else er\fi
  \ifxspace\xspace\fi
}

%Sex toggle - his/her (lowercase)
\newcommand*{\hisher}{%
  h%
  \ifsex@he is\else er\fi
  \ifxspace\xspace\fi
}

%Sex toggle - His/Her (capitalized)
\newcommand*{\Hisher}{%
  H%
  \ifsex@he is\else er\fi
  \ifxspace\xspace\fi
}

\makeatother

\begin{document}

\setgender{MI} MI: \heshe \Heshe \himher \Himher \hisher \Hisher

\setgender{MC} MC: \heshe \Heshe \himher \Himher \hisher \Hisher

\setgender{FI} FI: \heshe \Heshe \himher \Himher \hisher \Hisher

\setgender{FC} FC: \heshe \Heshe \himher \Himher \hisher \Hisher

\end{document}

答案2

\setgender无论如何,您的问题代码中实现的宏都会导致设置\global\sex@hetrue

\setgender\edef对参数进行一些扩展欺骗,然后调用\sex@setgender

\sex@setgender依次通过从参数的第一个字母\sex@getfirst定义一个宏。 的定义文本由一个字母组成。\sex@fst\sex@fst

然后进行一系列对宏\ifx的比较,宏的定义文本由几个字母组成。\sex@fst

因此,对于每一个\ifx比较,所比较宏的含义总是不同的。

因此,每次\ifx比较都会产生走\else路线的结果,最终会出现

\global\sex@hetrue 
%\PackageWarning{he-she}{Invalid value for gender. Using Masculine}


我建议不要使用\if/\ifx比较,而是使用分隔参数来分叉性别:

\documentclass{article}

\usepackage{xspace}

\makeatletter

\newif\ifxspace\xspacetrue
\newif\ifsex@he\sex@hefalse

\@ifdefinable\gobbletoexclam{\long\def\gobbletoexclam#1!{}}%
\newcommand\setgender[1]{%
  \ifcat$\detokenize\expandafter{\gobbletoexclam#1!}$%
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {%
    \setgenderfork
    !#1!MC!FI!FS!{\global\sex@hetrue}%
    !MI!#1!FI!FS!{\global\sex@hetrue}%
    !MI!MC!#1!FS!{\global\sex@hefalse}%
    !MI!MC!FI!#1!{\global\sex@hefalse}%
    !MI!MC!FI!FS!{\setgendererrordefault}!!!!%
  }{\setgendererrordefault}%
}%
\newcommand\setgendererrordefault{%
   \PackageError{he-she}{Invalid value for gender. Using Masculine}{Only values MI/MC/FI/FS are allowed!}%
   \global\sex@hetrue
}%
\@ifdefinable\setgenderfork{%
  \long\def\setgenderfork#1!MI!MC!FI!FS!#2#3!!!!{#2}%
}%

%Sex toggle - he/she (lower case)
\newcommand*{\heshe}{\ifsex@he\else s\fi he\ifxspace\xspace\fi}%
%Sex toggle - He/She (capitalized)
\newcommand*{\Heshe}{\ifsex@he H\else Sh\fi e\ifxspace\xspace\fi}%
%Sex toggle - him/her (lowercase)
\newcommand*{\himher}{h\ifsex@he im\else er\fi\ifxspace\xspace\fi}%
%Sex toggle - Him/Her (capital)
\newcommand*{\Himher}{H\ifsex@he im\else er\fi\ifxspace\xspace\fi}%
%Sex toggle - his/her (lowercase)
\newcommand*{\hisher}{h\ifsex@he is\else er\fi\ifxspace\xspace\fi}%
%Sex toggle - His/Her (capitalized)
\newcommand*{\Hisher}{H\ifsex@he is\else er\fi\ifxspace\xspace\fi}

\makeatother

\begin{document}

\setgender{MI} MI: \heshe \Heshe \himher \Himher \hisher \Hisher

\setgender{MC} MC: \heshe \Heshe \himher \Himher \hisher \Hisher

\setgender{FI} FI: \heshe \Heshe \himher \Himher \hisher \Hisher

\setgender{FS} FS: \heshe \Heshe \himher \Himher \hisher \Hisher

% Raising errors - Behavior in some cases differing from David Carlisle's code!

\setgender{FFS}

\setgender{MMI}

\setgender{}

\setgender{ }

\setgender{\fi}

\setgender{!MMI}

\end{document}

然而,这个变体并没有扩展的论点\setgender

即,此变体不允许您从宏中设置性别。

IE,

\def\foobar{FI}%
\setgender{\foobar}

不起作用。

触发扩展取决于你:

\def\foobar{FI}%
\expandafter\setgender\expandafter{\foobar}

确实有效。

我倾向于尽可能避免扩展/执行用户输入。用户输入不可预测,因此应被视为任意代码。扩展/执行任意代码可能会导致各种麻烦。

例如,如果一个邪恶的人

\def\foobar{\foobar}
\setgender{\foobar\foobar}

使用 David Carlisle 的代码,那么编译器将会默默地陷入非终止循环。

(您可以按 <CTRL>+Z 来使 LaTeX 停止。)

相关内容