Skip to content

J'essaye d'avoir... [email protected] et lowercase fonctionnent sur la comparaison des chaînes de caractères.

Le tutoriel ou le code que vous trouverez dans cet article est la solution la plus simple et la plus valable que nous ayons trouvée à votre doute ou à votre dilemme.

Solution :

Un expl3 solution. Ici, j'utilise le fait que tl_map_function:nN va "manger" des espaces, et faire un pliage correct de la casse plutôt qu'une mise en minuscule (voir les docs Unicode pour les raisons pour lesquelles c'est important) :

documentclass{article}
usepackage{expl3,xparse}
ExplSyntaxOn
NewExpandableDocumentCommand compareStrings { m m +m +m }
  {
    str_if_eq:eeTF % str_if_eq_x:nnTF in older code
      { tl_map_function:fN { str_foldcase:n {#1} } use:n }
      { tl_map_function:fN { str_foldcase:n {#2} } use:n }
      {#3} {#4}
  }
cs_generate_variant:Nn tl_map_function:nN { f }
ExplSyntaxOff

begin{document}
compareStrings{test}{tesT}{1}{2}
end{document}

Vous devez appliquer une minuscule aux chaînes de caractères avant de les comparer, donc il faut que ce soit en dehors de toute valeur de edef Ici, j'ai utilisé pdfstrcmp pour éviter d'avoir à définir des macros temporaires supplémentaires, cette primitive est également disponible dans d'autres moteurs que pdftex, sous forme de strcmp.

Cela trouve tous les éléments, sauf le dernier, comme étant égaux

enter image description here

documentclass{article}

%%% Support command %%%
makeatletter
newcommandcompareStrings[2]{%
edeftempA{lowercase{noexpandifnum0=noexpandpdfstrcmp
    {noexpand[email protected]#1 noexpand@empty}%
    {noexpand[email protected]#2 noexpand@empty}%
}relax}%
tempA
    expandafter@firstoftwo
  else
    expandafter@secondoftwo
  fi}

makeatother
%%%%% End support commands %%%%

begin{document}

defzz{T e sT}
0: compareStrings{tesT}{tesT}{1}{2}

1: compareStrings{test}{tesT}{1}{2}

2: compareStrings{zz}{tesT}{1}{2}

3: compareStrings{testj}{tesT}{1}{2}

end{document}

Soyez conscient que lowercase n'est pas extensible et ne déclenche pas l'expansion de son argument.

Ainsi, vous devez vous assurer que les tokens qui se développent en caractères dont les cas doivent être modifiés sont déjà complètement développés lorsque lowercase ou uppercase entre en action. (Idem pour uppercase.)

Sachez que [email protected] ne déclenche pas l'expansion de son argument.

Ainsi, vous devez vous assurer que les jetons qui se développent vers des caractères où les espaces doivent être supprimés sont déjà complètement développés lorsque [email protected] entre en action.

documentclass{article}
usepackage{ifthenx}

makeatletter
DeclareRobustCommandcompareStrings[2]{%
  % Make sure each instance of [email protected] gets its argument 
  % expanded - do this by edef-fing while via noexpand preventing 
  % expansion both of [email protected] and of @empty. The latter is a
  % sentinel-token for [email protected] and therefore must be let in place
  % untouched also:
  [email protected]tempA{%
    {noexpand[email protected]#1 noexpand@empty}%
    {noexpand[email protected]#2 noexpand@empty}%
  }%
  % Now that the arguments for the [email protected] are expanded,
  % via another [email protected] have carried out the [email protected]:
  [email protected]tempA{%
    % lowercase is not expandable, thus does not get expanded
    % /does not get carried out at "e-def-fing-time". 
    % Expansion of anything else but tempA is prevented via 
    % noexpand. Within tempA anything but the [email protected]
    % instances is already expanded due to the previous [email protected]
    % Thus the only effect of this [email protected] is carrying
    % out [email protected] on arguments that were expanded by 
    % the previous [email protected]
    lowercase{noexpandifthenelse{noexpandequaltempA}}%
  }%
  % Now in tempA the arguments are expanded and space tokens
  % are removed. Thus tempA expands to a call to lowercase
  % where the arguments are expanded and thus you don't have
  % control-sequence-tokens any more (whereon lowercase would have
  % no effect) but character-tokens (whereon lowwercase does have
  % an effect).
  tempA{@firstoftwo}{@secondoftwo}%
}
makeatother

parindent=0ex
parskip=baselineskip

begin{document}

verb|compareStrings{test}{tesT}{equal}{different}| yields:
compareStrings{test}{tesT}{equal}{different}

verb|compareStrings{test}{t e sT}{equal}{different}| yields:
compareStrings{test}{t e sT}{equal}{different}

verb|compareStrings{test}{t E   sT}{equal}{different}| yields:
compareStrings{test}{t e sT}{equal}{different}

verb|compareStrings{test}{tset}{equal}{different}| yields:
compareStrings{test}{tset}{equal}{different}

deftest{test}%
deftset{TsEt}%
verb|deftest{test}|\    
verb|deftset{TsEt}|

verb|compareStrings{test}{te s T}{equal}{different}| yields:
compareStrings{test}{te s T}{equal}{different}

verb|compareStrings{test}{tSeT}{equal}{different}| yields:
compareStrings{test}{tSeT}{equal}{different}

verb|compareStrings{tset}{te s T}{equal}{different}| yields:
compareStrings{tset}{te s T}{equal}{different}

verb|compareStrings{tset}{tSeT}{equal}{different}| yields:
compareStrings{tset}{tSeT}{equal}{different}

verb|compareStrings{tset}{test}{equal}{different}| yields:
compareStrings{tset}{test}{equal}{different}

verb|compareStrings{test}{tset}{equal}{different}| yields:
compareStrings{test}{tset}{equal}{different}

Be aware that verb|uppercase| and verb|lowercase| are not expandable, thus:

verb|compareStrings{uppercase{test}}{TEST}{equal}{different}| yields:
compareStrings{uppercase{test}}{TEST}{equal}{different}

verb|compareStrings{uppercase{test}}{test}{equal}{different}| yields:
compareStrings{uppercase{test}}{test}{equal}{different}

verb|compareStrings{lowercase{TEST}}{test}{equal}{different}| yields:
compareStrings{lowercase{TEST}}{test}{equal}{different}

verb|compareStrings{lowercase{test}}{test}{equal}{different}| yields:
compareStrings{lowercase{test}}{test}{equal}{different}

end{document}

enter image description here


Dans le cas où la suppression des jetons d'espace doit être appliquée dans des situations où l'argument lui-même peut contenir des accolades, je peux proposer une routine expansible. [email protected] pour supprimer récursivement tous les jetons d'espace explicites d'une séquence de jetons, même lorsque l'argument contient des accolades, sans avoir besoin de jetons sentinelles qui peuvent ne pas apparaître dans l'argument.

Comme effet secondaire, la routine remplace les paires de tokens de caractères explicites correspondants de la catégorie code 1/2 par des accolades correspondantes.

Habituellement, les accolades sont les seuls caractères avec le code de catégorie 1/2, donc habituellement cela ne devrait pas être un problème. Habituellement.

(Si quelqu'un connaît une méthode qui peut être utilisée dans des contextes d'expansion sur de vieux moteurs 8bit sans extensions e-TeX ou odfTeX, et où les caractères explicites correspondants de la catégorie 1/2 resteront intacts, je serai heureux de l'apprendre ;-)) )

documentclass{article}
usepackage{ifthenx}

makeatletter
%% Code for expandable recursive space-remove-routine:
%%
%%=============================================================================
%% Paraphernalia:
%%    [email protected], [email protected],
%%    [email protected], [email protected], [email protected]
%%    [email protected], [email protected],
%%    [email protected], [email protected]
%%=============================================================================
newcommand[email protected][2]{#1}%
newcommand[email protected][2]{#2}%
newcommand[email protected][2]{#2{#1}}%
newcommand[email protected][2]{#2#1}%
newcommand[email protected]{}[email protected]{def[email protected]}{} {}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% [email protected]{}%
%%                     {}%
%%                     {}%
%%
%% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
%% 
newcommand[email protected][1]{%
  romannumeral0expandafter[email protected]string{expandafter
  [email protected]expandafter{expandafter{string#1}expandafter
  [email protected]string}expandafter[email protected]expandafter{expandafter
  [email protected]string}expandafterexpandafter[email protected]{ }{}%
  [email protected]}{expandafterexpandafter[email protected]{ }{}[email protected]}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% [email protected]{}%
%%                      {}%
%%                      {}%
newcommand[email protected][1]{%
  romannumeral0expandafter[email protected]expandafter{expandafter{%
  string#1.}expandafter[email protected]expandafter{expandafter
  [email protected]string}expandafterexpandafter[email protected]{ }{}%
  [email protected]}{expandafterexpandafter[email protected]{ }{}[email protected]}%
}%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% [email protected]{}%
%%                             {'s 1st token is a
%%                               space-token>}%
%%                             {'s 1st token is not
%%                               a space-token>}%
newcommand[email protected][1]{%
  romannumeral0[email protected]{#1}%
  {expandafterexpandafter[email protected]{ }{}[email protected]}%
  {expandafter[email protected]string{[email protected]#1 }{}}%
}%
newcommand[email protected]{}%
longdef[email protected]#1 {%
  expandafter[email protected]expandafter{[email protected]#1{}}%
  {[email protected]{[email protected]}}{[email protected]{[email protected]}}%
  {[email protected]{ }{expandafterexpandafterexpandafterexpandafter
   expandafterexpandafterexpandafter}expandafterexpandafter
   expandafter}expandafter[email protected]expandafter{string}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%
%%   [email protected]{ABCDE} yields {A}
%%
%%   [email protected]{{AB}CDE} yields {AB}
%%
%% Be aware that (La)TeX does discard preceding space tokens when
%% gathering an undelimited argument. Thus:
%%
%%   [email protected]{  ABCDE} also yields {A}
%%
%%   [email protected]{  {AB}CDE} also yields {AB}
%%
%% This routine only works when the argument of [email protected]
%% is not empty/when the argument of [email protected] does have a
%% first inner undelimited argument. Thus use this routine only in 
%% situations where non-emptiness of [email protected]'s argument is
%% ensured.
%%.............................................................................
newcommand[email protected]@SelDOm{}%
longdef[email protected]@SelDOm#1#2[email protected]{{#1}}%
newcommand[email protected][1]{%
  romannumeral0%
  [email protected]{#1[email protected]}%
}%
newcommand[email protected][1]{%
  expandafter[email protected]expandafter{[email protected]{}#1}%
  { #1}%
  {expandafter[email protected]expandafter{[email protected]@SelDOm#1}}%
}%
%%=============================================================================
%%  [email protected]{}
%%
%%  after two expansion-steps delivers 
%%  
%%  (!!! [email protected] does also replace all pairs of matching 
%%       explicit character tokens of catcode 1/2 by matching braces!!!)
%%-----------------------------------------------------------------------------
newcommand[email protected]removeallspace[1]{%
  romannumeral0[email protected]{#1}{}%
}%
newcommand[email protected][2]{%
  [email protected]{#1}{ #2}{%
    [email protected]{#1}{%
       expandafter[email protected]
       expandafter{[email protected]#1}{#2}%
    }{%
      [email protected]{#1}{%
        expandafterexpandafterexpandafter[email protected]
        expandafterexpandafterexpandafter{%
        expandafter[email protected]expandafter{%
            romannumeral0expandafter[email protected]
            romannumeral0[email protected]{#1[email protected]}{}%
        }{#2}}%
        {expandafter[email protected]expandafter{[email protected]{}#1}}%
      }{%
       expandafter[email protected]
       romannumeral0[email protected]{#1[email protected]}{#1}{#2}%
      }%
    }%
  }%
}%
newcommand[email protected][3]{%
    expandafter[email protected]
    expandafter{[email protected]{}#2}{#3#1}%
}%

%% End of code for expandable recursive space-remove-routine.
makeatother

makeatletter
DeclareRobustCommandcompareStrings[2]{%
  % Make sure each instance of [email protected] gets its argument 
  % expanded - do this by edef-fing while via noexpand preventing 
  % expansion of [email protected]:
  [email protected]tempA{%
    {noexpand[email protected]{#1}}%
    {noexpand[email protected]{#2}}%
  }%
  % Now that the arguments for the [email protected] are expanded,
  % via another [email protected] have carried out the [email protected]:
  [email protected]tempA{%
    % lowercase is not expandable, thus does not get expanded
    % /does not get carried out at "e-def-fing-time". 
    % Expansion of anything else but tempA is prevented via 
    % noexpand. Within tempA anything but the [email protected]
    % instances is already expanded due to the previous [email protected]
    % Thus the only effect of this [email protected] is carrying
    % out [email protected] on arguments that were expanded by 
    % the previous [email protected]
    lowercase{noexpandifthenelse{noexpandequaltempA}}%
  }%
  % Now in tempA the arguments are expanded and space tokens
  % are removed. Thus tempA expands to a call to lowercase
  % where the arguments are expanded and thus you don't have
  % control-sequence-tokens any more (whereon lowercase would have
  % no effect) but character-tokens (whereon lowwercase does have
  % an effect).
  tempA{[email protected]}{[email protected]}%
}
makeatother

parindent=0ex
parskip=baselineskip

begin{document}

verb|compareStrings{te{s}t}{te { S } T}{equal}{different}| yields:
compareStrings{te{s}t}{te { S } T}{equal}{different}

verb|compareStrings{test}{t E   sT}{equal}{different}| yields:
compareStrings{test}{t E   sT}{equal}{different}

verb|compareStrings{t{es}t}{t{se}t}{equal}{different}| yields:
compareStrings{t{es}t}{t{se}t}{equal}{different}

deftest{te{ s} t}%
deftset{Ts{ E }t}%
verb|deftest{te{ s} t}|\    
verb|deftset{Ts{ E }t}|

verb|compareStrings{test}{te {s} T}{equal}{different}| yields:
compareStrings{test}{te {s} T}{equal}{different}

verb|compareStrings{test}{{tS}eT}{equal}{different}| yields:
compareStrings{test}{{tS}eT}{equal}{different}

verb|compareStrings{tset}{t{e} s T}{equal}{different}| yields:
compareStrings{tset}{t{e} s T}{equal}{different}

verb|compareStrings{tset}{tS{e}T}{equal}{different}| yields:
compareStrings{tset}{tS{e}T}{equal}{different}

verb|compareStrings{tset}{test}{equal}{different}| yields:
compareStrings{tset}{test}{equal}{different}

verb|compareStrings{test}{tset}{equal}{different}| yields:
compareStrings{test}{tset}{equal}{different}

Be aware that braces are taken into account, thus:

verb|compareStrings{t{es}t}{test}{equal}{different}| yields:
compareStrings{t{es}t}{test}{equal}{different}

Be aware that verb|uppercase| and verb|lowercase| are not expandable, thus:

verb|compareStrings{uppercase{test}}{TEST}{equal}{different}| yields:
compareStrings{uppercase{test}}{TEST}{equal}{different}

verb|compareStrings{uppercase{test}}{test}{equal}{different}| yields:
compareStrings{uppercase{test}}{test}{equal}{different}

verb|compareStrings{lowercase{TEST}}{test}{equal}{different}| yields:
compareStrings{lowercase{TEST}}{test}{equal}{different}

verb|compareStrings{lowercase{test}}{test}{equal}{different}| yields:
compareStrings{lowercase{test}}{test}{equal}{different}

end{document}

enter image description here

Nous vous montrons des avis et des notes



Utilisez notre moteur de recherche

Ricerca
Generic filters

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.