[VC++ 6] tolower() für komplettes char-Array

ManicMarble

Erfahrenes Mitglied
Hallo,
das Thema ist wahrscheinlich banal und 1000 mal gefragt, habe auch einiges dazu gefunden, aber das will alles mal wieder nicht wie ich will.

Ich versuche ein komplettes char-Array in Kleinbuchstaben umzuwandeln. Der schönste Einzeiler, den ich hierzu gefunden habe ist dieser:
PHP:
char* test = "HALLO hallo Hallo";
for(char* tmp = test; *tmp; tmp++) *tmp = (unsigned char) tolower((unsigned char) *tmp);
cout << test << endl << endl;
Leider funktioniert das bei mir nicht (ich teste das in einem einfachen VC++-Konsolen-Projekt). Der Compiler meldet keinen Fehler, aber das Programm stürzt bei der Ausführung ab.

Alternativ habe ich mir dann das hier ausgedacht:
PHP:
for(int i = 0; test[i] != '\0'; i++) test[i] = tolower(test[i]);
Das selbe Ergebnis.

Es liegt wohl nicht am tolower(), ich kriege den Absturz auch mit
PHP:
for(int i = 0; test[i] != '\0'; i++) test[i] = 'A';
Und am Casting (unsigned char) liegt's auch nicht, Absturz mit und ohne Casting.

Vorläufig mache ich das jetzt so:
PHP:
char* test = "HALLO hallo Hallo";	
char* test2 = _strlwr(_strdup(test));
cout << test2 << endl << endl;
Das geht zwar, ich find's aber recht unelegant, weil ich damit ja den String kopiere (in der End-Anwendung will ich das auf recht lange Strings anwenden).

Weiß jemand Rat?

Martin
 
Nachtrag:
Habe das Problem eingegrenzt. Es muss an der Zuweisung liegen.
PHP:
char* test = "HALLO hallo Hallo";
// Alle diese Zeilen führen zu einem Absturz:
test[3] = tolower(test[0]);
test[3] = 'A';
test[3] = 65;
test[3] = (unsigned char) 65;
(Wobei ich den 2. Buchstaben ([3]) nur als Beispiel genommen habe. Absturz bei egal welchem Zeichen ([0] bis [16]).

Aber solche Zuweisungen müssten doch gehen, oder? Habe ähnliches schon in zig Anleitungen gelesen. Hab' ich da was verpasst...?
 
Hy!

Wenn ich das noch recht in Erinnerung habe, ist ein char* den du mit
Code:
char  *test = "HALLO";
anlegst const, du darfst ihn also nicht ändern. Legst du den char* jedoch mit
Code:
char test[18] = "HALLO....";
an, so funktioniert auch dein Einzeiler.

mfg
uhu01
 
Hallo uhu01,
vielen Dank für die Antwort.

Mein Problem damit ist, dass ich das char-Array ja "in echt" nicht einfach vorher per
char* x = "Hallo";
festlege (dann könnt' ich ja gleich alles klein schreiben), sondern dass ich einer Funktion (besser: Methode eine Klasse) den char* übergebe. Daher weiß ich natürlich nicht, wie lang der enthaltene String ist.

Ich möchte mich auch nicht so leicht geschlagen geben. Dass char* immer const ist, wäre mir neu (so wie vieles in Sachen C/C++). In vielen Büchern und Tutorials (so auch hier) steht sowas:
char* t1 = "Das ist ein völlig veränderbarer String";
const char* t2 = "Inhalt ist nicht veränderbar, wohl aber der Pointer";
Erzählen die alle Mist? Oder fehlt mir da einfach der intellektuelle Zugang?

Weiter ratlos,
Martin
 
Mit
Code:
char* szString
bekommst du einen Pointer auf einen String.
szString ist also eine Adresse und kein Array bei dem du auf jedes einzelne Element zugreifen kannst.

Wenn du auf die einzelnen Elemente zugreifen willst, musst du den Pointer hochzählen.
Beispiel:

Code:
char* pszString = "HEUT ist EIN toller TAG";
char* pszRemember = szString;
pszString++ = 'e';
printf("%s",pszRemember);  // Ausgabe muesste sein: HeUT ist EIN toller TAG

Hoffe das stimmt so ...
 
Zuletzt bearbeitet:
Hallo Konsumierer,
auch Dir Danke für die Antwort.
Dass char* ein Pointer ist, ist mir schon klar. Um ganz korrekt zu sein ist es ja kein Pointer auf einen String, sondern ein Pointer auf das erste Element eines Arrays aus Zeichencodes. Schon klar dass der Pointer hochgezählt werden muss und dabei ein Zeichen nach dem anderen durchgeht bis er auf das Null-Byte stößt.
Genau das macht aber doch der von mir gepostete Code
PHP:
char* test = "HALLO hallo Hallo"; 
for(char* tmp = test; *tmp; tmp++) *tmp = (unsigned char) tolower((unsigned char) *tmp);
test ist ein Pointer auf 'H'. tmp ist am Anfang der Schleife ebenfalls ein Pointer auf 'H'. tmp++ zählt den Pointer hoch, beim 2. Schleifenbdurchlauf pointet tmp auf 'A'. Das Ganze läuft so lange, bis tmp auf '\0' zeigt.

Soweit ich das sehe ist die Schleife korrekt. Wie bereits erwähnt passiert der Fehler bei der Zuweisung.

Martin
 
Versuchs mal damit:

Code:
char* test = "HALLO hallo Hallo"; 
for(char* tmp = test; *tmp; tmp++) 
{
  tmp = (unsigned char) tolower((unsigned char) tmp); 
}
 
Ich kann mir nicht vorstellen, dass das geht. Der einzige Unterschied ist doch, dass jetzt das Ergebnis von tolower() der Adresse des Zeichens zugewiesen wird anstatt dem Zeichen selbst (*tmp ist doch die dereferenzierte Adresse).

Egal, ich probier's und melde mich, wenn's tatsächlich gehen sollte...
 
Code:
char* test = "HALLO hallo Hallo";

Aua, aua! test ist hier ein Pointer auf ein Stringliteral und kein tatsächliches Array. Es ist keine gute Idee, darauf schreibend zuzugreifen. Wenn du einen Buffer zum Reinschreiben brauchst, mach dir den lieber so:
Code:
char test[]  = "HALLO hallo Hallo";
Das alloziert tatsächlich Speicher, den du auch überschreiben kannst. Noch besser wäre es allerdings, gleich std::string oder std::vector<char> zu verwenden.
 
Ja klar ist das ein Pointer auf ein Stringliteral, sach ich doch.

Und wie gesagt: Nur in diesem Test-Programm "mache" ich mir diesen char*. In Wirklichkeit habe ich da wo ich das brauche genau das: Einen Pointer auf ein Stringliteral. Das ist sozusagen "gegeben", da kann ich nicht im Testprogramm einfach die Testbedingungen ändern ;).

So. Und das will ich in Kleinbuchstaben umwandeln und wenn's geht ohne alle Zeichen in einen neuen Puffer kopieren zu müssen und wenn irgend möglich ohne Funktionsaufruf.

Martin
 
Zurück