Wie funktioniert tolower?
-
Kann mir jemand erklären wie die Funktion 'tolower' aus "ctype.h" funktioniert?
In einer Internetbeschreibung hab ich folgendes gefunden:Wandelt Groß- in Kleinbuchstaben um.
tolower ist eine Funktion, die das als Integerwert übergebene Zeichen ch (ein Wert im Bereich von EOF bis 255) in einen Kleinbuchstaben umwandelt.Rückgabewert:
Liefert bei großen Buchstaben den umgewandelten Wert von ch zurück, ansonsten wird das Zeichen unverändert zurückgeliefert.So hier wär mal n kleiner Codeschnippsel:
#include <iostream> #include <string> #include <ctype.h> using namespace std; int main() { #include <iostream> #include <string> #include <ctype.h> using namespace std; int main() { string array[2]; array[0]="H"; array[1]="W"; int temp1; int temp2; temp1=tolower(array[0][0]); temp2=tolower(array[0][1]); return 0; } }
Ich möchte jetzt "H" und "W" in "h" und "w" uwandeln!
So, also muss ich jetzt an tolower den ASCII-CODE von "H" und "W" übergeben.
(So wie ich das gemacht habe, übergeb ich an tolower einen Buchstaben und keinen Integer Wert, wundert mich das das trotzdem geht?)
So nun stehen in temp1 und in temp2 die ASCII Werte drin, wie mach ich aus denen jetzt wieder einen Buchstaben..?
Kann mir das mal nochmal jemand genauer erläutern? Mach ich das zu umständlich? (also is jetzt halt nur n primitives Übungs Beispiel)
Und warum geht z.B. das hier: "tolower(array[0][0]);" da übergebe ich doch nen Buchstaben, und keine "int"???
Dankeschön schon mal im Voraus.
-
// machs doch nciht so kompliziert. Du darfst nicht std::string mit char* verwechseln // hier mal ein beispiel: char* text = "HALLO"; for(int i = 0; i < strlen(text); i++) text[i] = tolower(text[i]); cout << text << endl; // gibt "hallo" aus
int und char sind kompatibel. char ist sozusagen auch ein int, nur mit kleinerem bereich. Und die zahlen werden eben nciht als zahl sondern als zeichen interpretiert.
Man kann auch mit asci rechnen:cout << '9' - '0' << endl; // 9
-
innerhalb deines Programmes gibt es sowas wie Buchstaben garnicht. ein char ist nichtsweiter als eine zahl, die einen maximalwert von 255 hat. Erst, wenn du eine Ausgabe machst, wird der Buchstabenwert über eine zeichentabelle und einen Font zu einem Zeichen in der console.
-
Ah danke, is ja gar nicht so schwierig.
Nur was mir grad aufgefallen ist, warum steht da "char *text"?
Warum ist das als char Zeiger deklariert? Okay, mir ist auch aufgefallen, das man in "char text" nur einen Buchstaben speichern kann, und in "char *text" mehrere Buchstaben. Aber warum? Und seit wann kann man Werte direkt in Zeiger (*text) schreiben? Oder hat das gar nix mehr mit nem Zeiger zu tun? Aber schaut doch so aus.
Sry, für die blöden Fragen, aber ich hab bis jetzt fast immer nur mit "std::string" gearbeitet, und sowas "spezielles" is mir bis jetzt no net begegnet.
Dankeschön schon mal im Voraus.
-
int tolower(int ch) { return ch|32; }
-
Die string Klasse baut auf C-Strings (char*) auf, und bildet somit nur eine komfortable Schnittstelle, bei der sich der Benutzer nicht mehr um die riskante Speicherverwaltung (und mehr) kümmern muss. Ein char* ist nichts anderes als ein Zeiger, der auf die erste Speicheradresse einer beliebigen Zeichenkette zeigt. Inkrementiert man jedoch den Zeiger (also erhöht die Speicheradresse um 1) zeigt er auf das zweite Zeichen der Zeichenkette usw.. Das Ende des Strings (Zeichenkette) wird mit einer '\0' markiert.
char *text = "Das ist ein Beispieltext"; // Der Inhalt jeder darauffolgenden Speicheradresse, // auf die der Zeiger zeigt wird solange ausgegeben, // bis eine 0 auftritt, die das Ende markiert. std::cout<<text<<std::endl; // Das ganze kann man jetzt auch manuell machen: std::cout<<*text; ++text; // Adresse, auf die der Zeiger zeigt, wird um eins erhöht. std::cout<<*text; // usw.
Weiterführendes: http://www.pronix.de/pronix-745.html
Und ein Buch wäre eine Anschaffung wert, da dies absolute Grundlagen sind.MfG mikey.
-
Brutus schrieb:
int tolower(int ch) { return ch|32; }
int tolower(int ch) { if (ch >= 'A' && ch <= 'Z') return ch|32; return ch; }
-
Brutus schrieb:
int tolower(int ch) { return ch|32; }
nö
tolower dürfte in den meisten Standard-Libraries glaube ich komplexer implementiert sein und auf die Locales zurück greifen.
-
Hallo zusammen,
wie aber verwendet man tolower oder toupper möglichst unkompliziert auf einer ganzen Zeichenkette? Bis jetzt verwende ich immer folgende Variante. Beispiel:
#include <iostream> #include <string> #include <algorithm> #include <ctype.h> using namespace std; int f_tolower(int x) { return tolower(x); } int main() { string s = "KeIN langWEILIGER StAnDarDSPRUCH!"; transform(s.begin(), s.end(), s.begin(), &f_tolower); /* transform(s.begin(), s.end(), s.begin(), &tolower) * funktioniert leider nicht */ cout << s << endl; }
Geht das auch noch einfacher? Gibt es eine derartige Funktion oder gar ein Funktionsobjekt?
Grüße Martin
-
Was genau funktioniert denn an transform(...,tolower); nicht?
-
CStoll schrieb:
Was genau funktioniert denn an transform(...,tolower); nicht?
Ich nehme an (und luck_tux' Nickname bestätigt mich irgendwo dabei), dass er unter Linux arbeitet. Hier sind tolower und toupper irgendwelche Makros o.ä.. Jedenfalls nichts was der g++ in diversen Versionen (ich glaube bis hin zur aktuellen) als Funktionspointer erkennen würde.
Ich habs unter Linux bisher auch immer wie oben machen müssen. (Allerdings war mein my_tolower immer inline
)
-
lucky_tux schrieb:
Hallo zusammen,
wie aber verwendet man tolower oder toupper möglichst unkompliziert auf einer ganzen Zeichenkette? Bis jetzt verwende ich immer folgende Variante. Beispiel:
#include <iostream> #include <string> #include <algorithm> #include <ctype.h> using namespace std; int f_tolower(int x) { return tolower(x); } int main() { string s = "KeIN langWEILIGER StAnDarDSPRUCH!"; transform(s.begin(), s.end(), s.begin(), &f_tolower); /* transform(s.begin(), s.end(), s.begin(), &tolower) * funktioniert leider nicht */ cout << s << endl; }
Geht das auch noch einfacher? Gibt es eine derartige Funktion oder gar ein Funktionsobjekt?
Grüße Martin
Also eigentlich finde ich das schon ziemlich optimal: Sagt Genau und minimal das aus, was man tut: "Transformiere aus einem string (von begin bis end) in einen anderen mit tolower" .....
Kürzer und sprechender geht's IMO nicht - höchstens, indem man sich auf komplette strings bezieht, könnte man noch einen Parameter loswerden.Unschön finde ich aber auch, dass tolower eine int-Signatur hat ... Besseres fällt mir da im Augenblick auch nicht ein (wundert mich, dass man einen anderen Namen verwenden muss und kein normaler Overload funktikoniert, weiß aber auch nicht, warum).
Gruß,
Simon2.
-
Schreibe ich
transform(s.begin(), s.end(), s.begin(), &tolower);
so lässt sich das Beispiel nicht kompilieren:
# g++ main.cpp
main.cpp:10: error: no matching function for call to 'transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'Ich gehe davon aus, dass Präprozessordirektiven verwendet wurden. Leider habe ich momentan nicht die Möglichkeit das nachzuprüfen. Vlt. wagt ja jemand einen Blick in ctype? ...
Grüße Martin
--
Anmerkung: Da waren Andere schneller... Hab mir wohl ein wenig Zeit beim Tippen gelassen
-
Jetzt brat mir n Storch und die Beine recht knusprig...
Kann das Problem (welches ich definitiv auch schon hatte in genau dieser Form) gerade weder mit nem 3.2er noch mit nem 4.1er g++ nachstellen.
-
Hi,
also ich habe keine Probleme, das nachzustellen (g++ (GCC) 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)).
In der ctype finde ich:
int __cdecl tolower(int);Im Standard steht
ISO/IEC 14882: 2003 (Secon Edition); Kap. 22.1.3.2.2 schrieb:
template <class charT> charT tolower(charT c, const locale& loc);
Returns:use_facet<ctype<charT> >(loc).tolower(c)
.Gruß,
Simon2.
-
Hallo,
$ g++-2.95 --version
2.95.4$ g++-2.95 main.cpp
$ g++-4.1 --version
g++-4.1 (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.$ g++-4.1 main.cpp
main.cpp: In function 'int main()':
main.cpp:10: error: no matching function for call to 'transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'Mit einem alten Compiler und einer älteren libstdc++ funktioniert alles wunderbar. Meinermeinung nach sollte man jedoch nicht darauf vertrauen, dass die "richtige" Version verwendet wird, sondern möglichst kompatiblen Code schreiben, auch wenn dieser ein wenig komplexer und/oder einen größeren Umfang besitzt.
Grüße Martin
-
LordJaxom schrieb:
CStoll schrieb:
Was genau funktioniert denn an transform(...,tolower); nicht?
Ich nehme an (und luck_tux' Nickname bestätigt mich irgendwo dabei), dass er unter Linux arbeitet. Hier sind tolower und toupper irgendwelche Makros o.ä.. Jedenfalls nichts was der g++ in diversen Versionen (ich glaube bis hin zur aktuellen) als Funktionspointer erkennen würde.
Ich habs unter Linux bisher auch immer wie oben machen müssen. (Allerdings war mein my_tolower immer inline
)
Ich denke ihr beobachtet hier ein anderes Problem: tolower ist, in abhängigkeit der inkludiereten Header, ein überladener Name, was einen Aufruf von transform(..., &tolower) ungültig macht. Ein Cast schafft abhilfe: transform(..., static_cast<int(*)(int)>(tolower)). Korrekt ist das Ergebnis aber nicht, zumindest, wenn char != unsigned char ist. Wie ich hier schon ca. 1 Millionen mal geschrieben habe, muss man bei char != unsigned char die Zeichen erst nach unsigned char casten, bevor man sie an tolower übergibt.
Sinnvoll wäre also:
inline int myTolower(int c) { return std::tolower(static_cast<unsigned char>(c)); } ... transform(..., myTolower);
-
Äh ich hätt da noch eine Frage zum Thema, wie kann ich die Buchstabenlänge in einem string rausbekommen? Gibts da irgend eine Funktion? Also ich kenne "strlen", aber das geht ja nur bei char oder?
Ähm und was ist der Unterschied zwischen "ctype.h" und "cctype"?
Dankeschön schon mal im Voraus.
-
Stromberg schrieb:
Äh ich hätt da noch eine Frage zum Thema, wie kann ich die Buchstabenlänge in einem string rausbekommen? Gibts da irgend eine Funktion? Also ich kenne "strlen", aber das geht ja nur bei char oder?
Da gibt's sogar zwei - size() und length().
Ähm und was ist der Unterschied zwischen "ctype.h" und "cctype"?
Dankeschön schon mal im Voraus.<ctype.h> gehört zu C, <cctype> ist die C++ Entsprechung dazu (und definiert alle Funktionen im Namensraum 'std::').
-
CStoll schrieb:
Stromberg schrieb:
Äh ich hätt da noch eine Frage zum Thema, wie kann ich die Buchstabenlänge in einem string rausbekommen? Gibts da irgend eine Funktion? Also ich kenne "strlen", aber das geht ja nur bei char oder?
Da gibt's sogar zwei - size() und length().
hat das einen grund?
sind die wirklich identisch?