Probleme bei einer alten Prüfungsaufgabe
-
Hallo,
ich habe gerade folgende Aufgabe vor mir liegen:
**Schreiben Sie eine Funktion grossSchrift, die in einem als String gegebenen Titel (titel) alle Buchstaben in Großbuchstaben umwandelt.
Beispiel: Herr der Ringe --- HERR DER RINGE
Für das Ergebnis beschafft die Funktion dynamisch Speicher von der Größe des Eingabestrings. Einen Pointer auf diesen Ergebnisstring gibt die Funktion zurück.**
Ich wollte erst mal total einfach beginnen und mit einem String arbeiten der nur kleine Buchstaben enthält und keine Leerzeichen oder Sonderzeichen.
Die Abfrage bzw. ausgrenzung der Sonder- und Großbuchstaben wollte ich danach machen...Allerdings komme ich überhaupt nicht weit und bin total am verzweifeln...
So sieht mein momentaler Code aus:
#include <stdio.h> #include <string.h> #include <stdlib.h> char* grosseSchrift(char *c); int main (void){ char *s = "kleingeschrieben"; char *newS; newS = grosseSchrift(s); printf("*s = %s \n\n", s); printf("*newS = %s \n\n", newS); return 0; } char* grosseSchrift(char *c) { int i = 0; char *s= (char*)malloc(strlen(c) * sizeof(*c)); while (*c != '\0') { *s = *c - 0x20; s++; c++; } return s; }
Bei der Ausgabe von newS kommen leider nur irgendwelche Zeichen raus die nichts mit dem String zu tun haben...
Ich bin mir auch gar nicht sicher ob ich mit dieser Methode:
char *s= (char*)malloc(strlen(c) * sizeof(*c));
auch wirklich die richtige Speichergröße mir reserviere...Durch rumprobieren habe ich herrausgefunden, dass wenn ich beim return (s-16) schreibe, er mir dann KLEINGESCHRIEBEN ausgebibt aber dann hängt er noch einige Zeichen hinten dran...
Mir kommt das alles total Spanisch vor und bin mehr als nur verwirrt und weiß nicht mehr wo Hinten und Vorne ist...
Ich komm absolut nicht mehr weiter...
Ich möchte keine Lösungen oder so, ich möchte nur Tipps und meinungen oder Hinweise auf Fehler oder Denkfehler... ):
Hoffe Jemand kann helfen... Danke!
-
Erstens: bei malloc() hast du zu wenig Speicher angefordert - Stichwort: Null-Terminator.
Zweitens: Diesen Null-Terminator solltest du am Ende der Funktion auch setzen, sonst liest printf() weiter, bis es zufällig ein 0x00-Byte im Speicher findet.
Drittens: In der Kopierschleife verschiebst du den Zeiger auf den Zielstring, da solltest du dir den ursprünglich von malloc() gelieferten Zeiger nochmal irgendwo aufheben, damit du ihn zurückgeben kannst.
Viertens: Schau dir mal die Funktiontoupper()
an.
Fünftens: irgendwer sollte den angeforderten Speicher auch wieder freigeben.
-
Vielen Dank für die ganzen Tipps!
Ich habe den Code etwas angepasst:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> char* grosseSchrift(char *c); int main (void){ char *s = "Herr Der Ringe\0"; char *newS; newS = grosseSchrift(s); printf("*s = %s \n\n", s); printf("*newS = %s \n\n", newS); return 0; } char* grosseSchrift(char *c) { int i = 0; char *s= (char*)malloc(strlen(c) * sizeof(*c)); char *tmp = s; while (*c != '\0') { *tmp = toupper(*c); tmp++; c++; } *tmp = '\0'; return s; }
Allerdings bin ich mir jetzt wegen dem free() nicht sicher,
also ich weiß jetzt nicht wo ich das genau setzen soll...Es in der Funktion zu setzen würde doch keinen Sinn machen oder?
Ich würde ja somit meinen String den ich gerade dort geschrieben habe wieder "löschen" also frei geben...Also würde sich einfach in der main nach dem printf ein free(newS) setzen...
Macht das Sinn?
-
vandread schrieb:
Es in der Funktion zu setzen würde doch keinen Sinn machen oder?
Ich würde ja somit meinen String den ich gerade dort geschrieben habe wieder "löschen" also frei geben...Gut erkannt
Also würde sich einfach in der main nach dem printf ein free(newS) setzen...
Macht das Sinn?Ja, genau dort gehört das free() hin - nachdem du den zurückgegebenen String nicht mehr benötigst, räumst du ihn wieder auf.
-
Du forderst immer noch zuwenig Speicher an.
Der Leerstring "" besteht aus einem Zeichen ('\0') hat aber die Länge 0
-
@CStoll
danke! (:@DirkB
also muss ich noch ein byte dazu holen?!
also:
char *s= (char*)malloc(strlen(c) * sizeof(*c) + 1);
-
Wenn du schon mit
sizeof(*c)
arbeitest, bin ich auch pingelig:char *s= (char*)malloc( (strlen(c) + 1 ) * sizeof(*c));
Bei deiner Formel gehst du davon aus, dass ein *c ein Byte groß ist. Und dann kannst du auch auf den Ausdruck verzichten.
-
Alles klar tut mir Leid (:
Hier also der fertige Code:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> char* grosseSchrift(char *c); int main (void){ char *s = "Herr Der Ringe\0"; char *newS; newS = grosseSchrift(s); printf("*s = %s \n\n", s); printf("*newS = %s \n\n", newS); free(newS); return 0; } char* grosseSchrift(char *c) { int i = 0; char *s= (char*)malloc((strlen(c) + 1) * sizeof(*c)); char *tmp = s; while (*c != '\0') { *tmp = toupper(*c); tmp++; c++; } *tmp = '\0'; return s; }
-
Prima!
Noch ein paar Anmerkungen:
Beichar *s = "Herr Der Ringe\0";
brauchstdu das \0 am Ende nicht.
Das wird bei Stringliteralen (Text zwischen ") automatisch vom Compiler eingefügt.Und du kannst den Warnungen vom Compiler noch nachgehen.
Z.B.Variable i deklariert aber nie benutzt.
-
Ups das i stammt noch aus einigen Versuchen, das muss natürlich weg...
Gilt das mit \0 eigentlich auch bei Arrays?
Also bei einem Pointer bin ich mir sicher das es automatisch gesetzt wird,
aber wird es beispielsweise bei:
char s[] = "Das ist ein Text";
auch gesetzt?
-
ja
-
Das gilt für "Stringliterale".
Stringliterale sind Texte zwischen Anführungszeichen.
In deinem Beispiel eben gerade ist das"Das ist ein Text"
ein Stringliteral.