Comment puis-je minuscule une chaîne en C?


108

Comment puis-je convertir une chaîne de casse mixte en chaîne en minuscules en C?


2
Avez-vous uniquement affaire à l'ASCII avec les lettres az?
Mark Byers

1
ascii. comment pourrais-je en tenir compte? l'exemple ci-dessous fonctionnerait-il toujours? que se passe-t-il si mon caractère est un '#' et que tolower () est appelé dessus?
Tony Stark

1
Ça marchera. Je me demandais plus si votre chaîne contenait des choses comme é ou Ü.
Mark Byers

1
Pourquoi ne pas simplement utiliser "strlwr"? strlwr((char*)str);Il passe simplement par la chaîne et le convertit lui-même.
Larry

1
@Larry Ce n'est pas standard.
mi

Réponses:


153

C'est dans la bibliothèque standard, et c'est le moyen le plus simple que je puisse voir pour implémenter une telle fonction. Alors oui, faites une boucle sur la chaîne et convertissez chaque caractère en minuscules.

Quelque chose de trivial comme ça:

#include <ctype.h>

for(int i = 0; str[i]; i++){
  str[i] = tolower(str[i]);
}

ou si vous préférez une doublure, vous pouvez utiliser celle-ci de JF Sebastian:

for ( ; *p; ++p) *p = tolower(*p);

35
for ( ; *p; ++p) *p = tolower(*p);semble plus idiomatique.
jfs

14
@JF, voilà. Cela dépend s'ils veulent que le code soit effrayant ou agréable :) (une doublure très lisible, mais cela semble effrayant)
Earlz

cela me donne un segfault si str est un char *, mais pas si str est un tableau de caractères. Vous avez une explication à cela?
Café électrique du

1
Je crois que la seule ligne vous fera perdre votre pointeur sur la chaîne.
Ace.C

2
Je crois qu'un seul paquebot aura des ramifications incalculables.
NOP da CALL

7

convertir en minuscules équivaut à augmenter le bit 0x60 si vous vous limitez à ASCII:

for(char *p = pstr; *p; ++p)
    *p = *p > 0x40 && *p < 0x5b ? *p | 0x60 : *p;

6
Pour le rendre un peu plus lisible, vous pouvez le fairefor(char *p = pstr;*p;++p) *p=*p>='A'&&*p<='Z'?*p|0x60:*p;
Grant Peters

7
Cette version est en fait plus lente que celle de la glibc tolower(). 55,2 contre 44,15 sur ma machine.
jfs

je ne peux pas imaginer que: tolower () traite des caractères; seulement si c'est macro
Oleg Razgulyaev

1
@oraz: tolower () a une int (*)(int)signature. Voici le code utilisé pour les mesures de performance gist.github.com/370497
jfs

@JF: je vois, ils ont utilisé la table, mais je peux optimiser: for (; * p; ++ p) if (* p> 'Z') {continue;} else if (* p <'A') {continue;} else {* p = * p | 0x60;}
Oleg Razgulyaev

1

Êtes-vous uniquement confronté à des chaînes ASCII et n'avez-vous aucun problème de paramètres régionaux? Alors oui, ce serait une bonne façon de le faire.


que se passe-t-il si tolower () est appelé sur un caractère az non ascii? comme '!' ou '#'. Je l'ai testé sur «#» et cela a semblé fonctionner correctement. est-ce généralement vrai pour tous les caractères ascii qui ne sont pas des lettres az?
Tony Stark

1
@hatorade: tolower()laisse l'argument inchangé s'il n'est pas dans la plage 'A' .. 'Z'.
jfs

1
! et # sont tous deux des caractères ascii. Mark faisait référence à d'autres encodages comme UTF8, où vous ne pouvez pas supposer qu'il y a un octet par caractère (comme le fait cette solution)
hdgarrood


1

Si nous allons être aussi bâclés à utiliser tolower(), faites ceci:

char blah[] = "blah blah Blah BLAH blAH\0"; int i=0; while(blah[i]|=' ', blah[++i]) {}

Mais bon, ça explose un peu si vous lui donnez des symboles / chiffres, et en général c'est mal. Bonne question d'entretien, cependant.


6
Oui, cela pliera / broche / mutilera une variété de symboles (en ASCII, tout symbole, caractère de contrôle ou chiffre avec le bit 5 clair deviendra le même code de caractère avec le bit 5 défini, etc.) donc vraiment, sérieusement, ne le faites pas utilise le.
Ken S

Ce message est discuté sur meta .
Patrick Hofman

0

Boucler le pointeur pour obtenir de meilleures performances:

#include <ctype.h>

char* toLower(char* s) {
  for(char *p=s; *p; p++) *p=tolower(*p);
  return s;
}
char* toUpper(char* s) {
  for(char *p=s; *p; p++) *p=toupper(*p);
  return s;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.