Wie kann ich eine Zeichenfolge in C in Kleinbuchstaben schreiben?

108

Wie kann ich eine gemischte Zeichenfolge in eine Kleinbuchstabenzeichenfolge in C konvertieren?

Tony Stark
quelle
2
Beschäftigen Sie sich nur mit ASCII mit Buchstaben az?
Mark Byers
1
ASCII. Wie würde ich das berücksichtigen? würde das folgende Beispiel noch funktionieren? Was passiert, wenn mein Zeichen ein '#' ist und tolower () darauf aufgerufen wird?
Tony Stark
1
Das wird funktionieren. Ich habe mehr darüber nachgedacht, ob Ihre Zeichenfolge Dinge wie é oder Ü enthält.
Mark Byers
1
Warum nicht einfach "strlwr" verwenden? strlwr((char*)str);Es geht einfach durch den String und konvertiert ihn selbst.
Larry
@ Larry Es ist nicht Standard.
Mitte

Antworten:

152

Es befindet sich in der Standardbibliothek und ist der einfachste Weg, eine solche Funktion zu implementieren. Also ja, durchlaufen Sie einfach die Zeichenfolge und konvertieren Sie jedes Zeichen in Kleinbuchstaben.

Etwas Triviales wie dieses:

#include <ctype.h>

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

oder wenn Sie einen Liner bevorzugen, können Sie diesen von JF Sebastian verwenden:

for ( ; *p; ++p) *p = tolower(*p);
Earlz
quelle
35
for ( ; *p; ++p) *p = tolower(*p);scheint idiomatischer.
JFS
14
@JF los geht's. Kommt darauf an, ob der Code beängstigend oder schön aussehen soll :) (sehr gut lesbarer
Einzeiler
Dies gibt mir einen Segfault, wenn str ein ist char *, aber nicht, wenn str ein char-Array ist. Hast du eine Erklärung dafür?
Elektrischer Kaffee
1
Ich glaube, der eine Liner wird dazu führen, dass Sie Ihren Zeiger auf die Zeichenfolge verlieren.
Ace.C
2
Ich glaube, dass ein Liner unzählige Auswirkungen haben wird.
NOP da CALL
7

Das Konvertieren in Kleinbuchstaben entspricht dem Anstiegsbit 0x60, wenn Sie sich auf ASCII beschränken:

for(char *p = pstr; *p; ++p)
    *p = *p > 0x40 && *p < 0x5b ? *p | 0x60 : *p;
Oleg Razgulyaev
quelle
5
Um es etwas lesbarer zu machen, könnten Sie tunfor(char *p = pstr;*p;++p) *p=*p>='A'&&*p<='Z'?*p|0x60:*p;
Grant Peters
7
Diese Version ist tatsächlich langsamer als die von glibc tolower(). 55,2 vs. 44,15 auf meiner Maschine.
JFS
das kann ich mir nicht vorstellen: tolower () befasst sich mit chars; nur wenn es Makro ist
Oleg Razgulyaev
1
@oraz: tolower () hat eine int (*)(int)Signatur. Hier ist der Code für Leistungsmessungen gist.github.com/370497
jfs
@JF: Ich verstehe, sie haben Tabelle verwendet, aber ich kann optimieren: für (; * p; ++ p) wenn (* p> 'Z') {weiter;} sonst wenn (* p <'A') {weiter;} sonst {* p = * p | 0x60;}
Oleg Razgulyaev
1

Beschäftigen Sie sich nur mit ASCII-Zeichenfolgen und haben keine Probleme mit dem Gebietsschema? Dann ja, das wäre ein guter Weg, es zu tun.

Mark Byers
quelle
Was passiert, wenn tolower () auf einem nicht-ascii az char aufgerufen wird? mögen '!' oder '#'. Ich habe es auf '#' getestet und es schien in Ordnung zu funktionieren. Gilt dies im Allgemeinen für alle ASCII-Zeichen, die keine Buchstaben az sind?
Tony Stark
1
@hatorade: Lässt tolower()das Argument unverändert, wenn es nicht im Bereich 'A' .. 'Z' liegt.
JFS
1
! und # sind beide ASCII-Zeichen. Mark bezog sich auf andere Codierungen wie UTF8, bei denen man nicht davon ausgehen kann, dass es ein Byte pro Zeichen gibt (wie bei dieser Lösung)
hdgarrood
1

Wenn Sie Unicode-Unterstützung in Kleinbuchstaben benötigen, lesen Sie diese Frage: Light C Unicode Library

Eduardo
quelle
1

Wenn wir so schlampig wie möglich sein wollen tolower(), tun Sie Folgendes:

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

Aber es explodiert irgendwie, wenn Sie ihm einige Symbole / Ziffern geben, und im Allgemeinen ist es böse. Gute Interviewfrage.

Ken S.
quelle
6
Ja, dies wird eine Vielzahl von Symbolen falten / spindeln / verstümmeln (in ASCII wird jedes Symbol, Steuerzeichen oder jede Zahl mit Bit 5 Clear zum gleichen Zeichencode mit gesetztem Bit 5 usw.), also wirklich, ernsthaft, nicht benutze es.
Ken S
Dieser Beitrag wird auf Meta diskutiert .
Patrick Hofman
0

Schleifen des Zeigers, um eine bessere Leistung zu erzielen:

#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;
}
cscan
quelle