Zuweisung schlägt fehl
-
Hallo,
ich habe noch nicht viel in C programmiert, und mich quälen immer wieder komische Fehler. Zum Beispiel funktioniert der folgende Code bei mir nicht:
#include <stdio.h> int main(int argc, char *argv[]) { char *asd = "aaa"; while (*asd != '\0') { *asd = toupper(*asd); asd++; } printf("%s", asd); system("pause"); return 0; }
Wenn ich das Programm kompiliere und starte stürzt es immer ab. Ich hab mich mal herangetastet und herausgefunden, dass es an dieser Zeile liegt:
*asd = toupper(*asd);
Egal was ich *asd zuweise, es stürzt immer ab!
Ich hoffe ihr könnt mir helfen.Mit freundlichen Grüßen,
NetSlayer
-
char *asd = "aaa";
du schreibst etwas in einen unallokolisierten speicherbereich, sprich einen nicht initialisierten pointer. das is immer eine schlechte idee, da ein zeiger, ohne ihm expliziet einen speicherbereich zuzuordnen, immer auf eine muellige speicheradresse zeigt, wo du nix reinschreiben sollst/darfst/kannst/whatever, und wenn du dann es doch zu endet das oft in nem segfault oder in unabsehbaren auswirkungen
-
*asd = toupper(*asd);
die zeile wollte ich noch dazunehmen, ich meinte also
char *asd = "aaa";
*asd = toupper(*asd);
-
denn char *ptr = "test"; ist legal
sorry fuer diesen 3fach post, ich muss mich mal registrieren damit ich posts editieren kann
-
Ah, danke.
Ich habe mir jetzt mit malloc geholfen.
Der folgende Code sieht etwas merkwürdig aus, läuft aber und macht was er soll
#include <stdio.h> int main(int argc, char *argv[]) { char *asd = malloc(100); char *runner; *asd = 'A'; *(asd + 1) = 'a'; *(asd + 2) = '\0'; runner = asd; while (*runner != '\0') { *runner = toupper(*runner); runner++; } printf("%s", asd); system("pause"); return 0; }
-
#include <stdio.h> #define LEN 100 int main(int argc, char *argv[]) { char *asd = (char *)malloc(LEN); char *runner; strcpy(asd, "Aa"); runner = asd; while (*runner != '\0') { *runner = toupper(*runner); runner++; } printf("%s\n\n", asd); return 0; }
so waere es etwas netter
1. keine werte hardcodieren, sondern makros nehmen
2. dein kopiervorgang was etwas komischda eignen sich libfunktionen doch manchmal
3. vor malloc am besten immer einen cast machen
4. nicht unbedingt systemabhaenginge commands nehmen, das system("pause") laeuft auf meinem gnu/linux system nichtzudem, welchen sinn hatte es? an der stelle bitte sleep benutzen
5. am ende \n benutzen, da die shell sonst kein newline macht und der prompt nach dem output des programms kommt
-
2. dein kopiervorgang was etwas komisch
da eignen sich libfunktionen doch manchmal
Ja, kam mir auch gerade *g*
3. vor malloc am besten immer einen cast machen
...hat der Compiler auch die ganze Zeit erzählt
4. nicht unbedingt systemabhaenginge commands nehmen, das system("pause") laeuft auf meinem gnu/linux system nicht
zudem, welchen sinn hatte es? an der stelle bitte sleep benutzen
Bin gerade unter Windows, und benutz Dev-C++. Und wenn ich da kein Sysmte("pause") hinsetz' ist das Konsolenfenster gleich wieder weg. Aber sleep ist ne gute Idee.
5. am ende \n benutzen, da die shell sonst kein newline macht und der prompt nach dem output des programms kommt
Jo, werd ich machen (ich weiß schon wie das aussieht, unter linux passiert mir das nämlich genauso *g*)
Alles in allem, danke für die Tips
-
daq schrieb:
3. vor malloc am besten immer einen cast machen
Das ist kein guter Ratschlag! Man sollte Casts vermeiden, wenn sie nicht nötig sind. Und man sollte gut darüber nachdenken, wie man sie verwendet, wenn man sie verwendet.
4. nicht unbedingt systemabhaenginge commands nehmen, das system("pause") laeuft auf meinem gnu/linux system nicht
zudem, welchen sinn hatte es? an der stelle bitte sleep benutzen
system() ist generell schlecht für solche Sachen. system() sollte man wirklich nur dann hernehmen, wenn man andere Programme aufruft und nicht dazu missbrauchen Befehlszeilenkommandos auszuführen, die durch einfache Funktionen (auch wenn diese meist systemspezifisch sind; was die Kommandos allerdings auch sind) viel schöner zu lösen sind.
daq schrieb:
char *asd = "aaa";
du schreibst etwas in einen unallokolisierten speicherbereich, sprich einen nicht initialisierten pointer.
Das stimmt so nicht ganz bei der Definition. Das Problem bei der Sache ist, dass asd auf einen Speicherbereich zeigt, der nur ReadOnly ist. Wenn man dann natürlich versucht darauf zu schreiben, dann mag das das Betriebssystem nicht so gern ;).
-
NetSlayer schrieb:
Bin gerade unter Windows, und benutz Dev-C++. Und wenn ich da kein Sysmte("pause") hinsetz' ist das Konsolenfenster gleich wieder weg. Aber sleep ist ne gute Idee.
Du könntest das Programm ja auch ganz normal von der Konsole starten, wie man eigentlich jedes Konsolenprogramm startet ;). Und was ist eigntlich so schwer daran, selber am Ende des Programms die Eingabe einer Taste vom Benutzer zu verlangen??
-
AJ schrieb:
Und was ist eigntlich so schwer daran, selber am Ende des Programms die Eingabe einer Taste vom Benutzer zu verlangen??
Also jetz' hack doch nicht so auf mir rum. Vielleicht kannst du mal in meinen ersten Post gucken: Ich programmiere noch nicht lange C. Ich hab doch gesagt ich hab's jetzt mit sleep() gelöst, dann brauch ich nicht einmal 'ne Taste drücken.
Ach ja, ich starte das Programm nicht von der Konsole, weil ich auch einfach F9 drücken kann. Außerdem kann die Windows-Shell gar nichts; ich benutze die eigentlich nicht gern.
-
Sleep ist am Ende eines Programmes selten hilfreich, da der Benutzer vielleicht doch selbst entscheiden möchte, wann er das Ergebnis fertig gelesen hat.
getchar ... es wird auf ENTER gewartet
getch() ... nich ANSI aber wartet auf beliebige taste
scanf("%c") ... würde ich nur zur not verwenden, oder
fgetc(stdin)UND: es besteht ein "geringer" unterschied zwischen der compilerumgebung, und dem aufruf durch das OS.
man KÖNNTE auch ohne malloc speicher reservieren LASSEN:
char variable[]="Ich bin ein String*gg*";
das funkt doch auch oder?
QUESTION @AJ: warum sind casts schlecht?
mfG :xmas1: (c)h :xmas1:
-
NetSlayer schrieb:
AJ schrieb:
Und was ist eigntlich so schwer daran, selber am Ende des Programms die Eingabe einer Taste vom Benutzer zu verlangen??
Also jetz' hack doch nicht so auf mir rum. Vielleicht kannst du mal in meinen ersten Post gucken: Ich programmiere noch nicht lange C. Ich hab doch gesagt ich hab's jetzt mit sleep() gelöst, dann brauch ich nicht einmal 'ne Taste drücken.
Ach ja, ich starte das Programm nicht von der Konsole, weil ich auch einfach F9 drücken kann. Außerdem kann die Windows-Shell gar nichts; ich benutze die eigentlich nicht gern.Richtig du programmierst noch nicht lange C und genau deswegen versuche ich dir so früh wie nur möglich die Flausen aus dem Kopf zu bringen. Außerdem verstehe ich nicht, dass so viele Anfänger mit dem system("PAUSE") daherkommen (ich muss das meistens in der Woche mind. 5 mal im Forum sehen, dass einer am Schluss den Schmarrn hinmacht). Ich frag mich wie die Leute darauf kommen das herzunehmen, schließlich ist eines der ersten Sachen, die man lernt, ein Zeichen von der Tastatur mit scanf() o. ä. einzulesen.
Klar ist es einfacher auf F9 (wohl der Shortcut in deiner IDE zum Ausführen) zu drücken, um das Programm gleich auszuführen, aber Konsolenprogramme sind nun mal für die Konsole gedacht (das sagt ja der Name schon), d. h. man sollte sie auch dort testen!
Ich hab absolut nichts dagegen, dass du am Ende deines Programms einen Tastendruck zum Beenden verlangst, aber BITTE nicht mit system().
Wenn du weitere Fortschritte in C machst, dann denk bitte auch daran, nicht immer gleich system() und einen Konsolenbefehl zu verwenden. Informier dich erstmal drüber, ob es alternative Funktionen dazu gibt (das ist eigentlich immer der Fall).
-
chille07 schrieb:
man KÖNNTE auch ohne malloc speicher reservieren LASSEN:
char variable[]="Ich bin ein String*gg*";
das funkt doch auch oder?
Das Problem ist, dass du hier nur lesend zugreifen darfst. Deshlab ist const für Literale richtiger
const char variable[]="Ich bin ein String*gg*";
Dann hätte NetSlayer von vorn herein schon einige Fehler weniger gehabt.
-
groovemaster schrieb:
chille07 schrieb:
man KÖNNTE auch ohne malloc speicher reservieren LASSEN:
char variable[]="Ich bin ein String*gg*";
das funkt doch auch oder?
Das Problem ist, dass du hier nur lesend zugreifen darfst. Deshlab ist const für Literale richtiger
In diesem Fall besteht nicht nur lesender Zugriff. Da hier erstellte Array wird in der Größe reserviert, dass es für den String + Stringendezeichen braucht und der String wird dann an den reservierten Speicher kopiert. Aufpassen muss man nur, dass man nicht über den Speicher des Arrays hinausschreibt (Bufferoverflow).
-
Ich dachte eigentlich, dass das nur bei solchen Sachen gemacht wird
char variable[100] = "Ich bin ein String*gg*";
Hmm, muss ich mir doch nochmal genau anschaun, was der Standard dazu sagt.
-
groovemaster schrieb:
Ich dachte eigentlich, dass das nur bei solchen Sachen gemacht wird
char variable[100] = "Ich bin ein String*gg*";
Hmm, muss ich mir doch nochmal genau anschaun, was der Standard dazu sagt.
char foo[]="hallo";
ist ein Array, dass eine handvoll chars beinhaltetchar* foo="hallo";
ist ein zeiger auf einen konstanten Speicherbereich (denn "hallo"[1]='x' ist ja aus verstädnlichen Gründen auch nicht erlaubt).die feinen unterschiede zwischen array und zeiger
-
groovemaster schrieb:
Ich dachte eigentlich, dass das nur bei solchen Sachen gemacht wird
char variable[100] = "Ich bin ein String*gg*";
Hmm, muss ich mir doch nochmal genau anschaun, was der Standard dazu sagt.
In diesem Fall wird ein Array für 100 chars angelegt und der String danach in den reservierten Speicher kopiert. Wenn du die 100 weglässt, dann wird hald einfach nur so viel Speicher reserviert, wie für den String gebraucht wird. Ganz einfach ;).
-
Scheint tatsächlich so zu sein, dass nur bei der Zeiger Schreibweise das Literal direkt referenziert wird und somit read-only ist. Man lernt halt nie aus.