C C-Anfänger: Mehr als einen Buchstaben in char abspeichern

kingd0x

Lt. Junior Grade
Registriert
Apr. 2015
Beiträge
258
Hallo, ich versuche momentan etwas C zu lernen und habe folgende Situation.
Ich möchte eine Frage stellen:
printf("Ja oder Nein?" \n);
und auf diese Frage soll dann die Antwort Ja/Nein folgen.
In einem normalen char kann man nur einen Buchstaben speichern, dass habe ich schonmal herausgefunden :D
Also muss ich einen Char String anlegen.
Die Frage ist nun, wie sieht das "richtig" aus? In den eckigen Klammern muss man doch angeben, wie lang der String werden soll oder? Also bin ich davon ausgegangen, dass man bei Ja/Nein eine 4 eintragen muss, da Nein 4 Zeichen hat?

char antwort[4];
printf("Ja oder Nein?" \n);
scanf("%s", antwort);
printf("%s", antwort);

-> funktioniert ohne Probleme, aber wenn ich in den eckigen Klammern eine 3,2,1 oder 0 eingebe funktioniert das ganze immer noch.
Warum? N E I N hat 4 Zeichen, aber es werden doch bspw. nur 2 zeichen gespeichert wenn man eine 2 einträgt?
Könnte mir bitte jemand auf anfänger Niveau erläutern, wofür die Zahl in der Klammer steht und ob diese Methode für mein Vorgehen überhaupt geeignet ist?^^

Gruß
 
Was du machst, ist ein Char ARRAY anlegen.
Da Strings mit einer "null" -> "\0" terminiert werden müssen, brauchst du immer ein Zeichen mehr.

Bsp "Nein":

char c[5]; // Legt ein Char Array mit einer Größe von 5 an. (Index 0-4)
c[0] = 'N';
c[1] = 'e';
c[2] = 'i';
c[3] = n'';
c[4] = '\0';

Weitere Infos:
http://www.c-howto.de/tutorial/strings-zeichenketten/nullterminiert/
 
  • Gefällt mir
Reaktionen: kingd0x
Danke für den Link.
Also kann ich,
wenn char antwort[5]; deklariert ist,
hinterher durch bspw. antwort[2] = ' \0' ein "Ne" ausgeben.

Bsp.:
char antwort[5];
printf("Ja oder Nein?" \n);
scanf("%s", antwort);
antwort[2] = ' \0'
printf("%s", antwort);

-> ausgegeben wird "Ne"

Aber wofür steht dann die 1 im unteren Beispiel?
char antwort[1];
printf("Ja oder Nein?" \n);
scanf("%s", antwort);
antwort[4] = ' \0'
printf("%s", antwort);

-> Gibt trotzdem Nein aus
Ich dachte die 1 gibt vor, wie viele Zeichen gespeichert werden können..
Blicke nicht mehr durch :(
 
Jeder String (in C Char-Array) wird, wie schon gesagt mit einem '\0' abgeschlossen. Das '\0' kannst du dir als Markierung für des Ende des Wortes bzw. des Satzes vorstellen. '\0' ist dabei einfach nur ein Alias für 0. Du könntest also genauso c[4] = 0; schreiben.
 
  • Gefällt mir
Reaktionen: kingd0x
scanf ist die deklarierte länge von antwort[x] vollkommen egal. Statt ja oder nein kann man auch einen ganzen satz eintippen und dein string oder gar dein Programm wird überschrieben.
Nutze bitte nicht scanf, führt nur zu Pufferüberläufen und Sicherheitslücken usw
 
Okay, scanf speichert wirklich alles ab, grade ausprobiert.
Mit fgets() macht die Zahl in der eckigen Klammer wieder Sinn für mich.
Ich danke euch :)
 
char antwort[1];
Erlaubt es dir EIN zeichen zu speichern!!!
scanf ist es egal wie groß antwort ist, deshalb gibt es einen Speicherüberlauf. Den Du aber nicht merkst. Erst wenn du das machst:
char antwort1[1];
char antwort2[1];

Würde in antwort2 jetzt der zweite buchstabe von antwort1 stehen.
 
  • Gefällt mir
Reaktionen: kingd0x
Wusste nicht, dass scanf einfach alles überschreiben kann.
Jetzt macht die Zahl wieder Sinn :D
 
C ist einfach doof! Du kannst auch antwort[0]='A'; und antwort[1]='B'; schreiben. Dem compiler ist es egal, das antwort nur ein Zeichen groß ist. Es müsste aber zumindest ein warning kommen.
 
  • Gefällt mir
Reaktionen: kingd0x
Ich weiß nicht ob du dich schon mit Pointern auseinander gesetzt hast.
char antwort[4];
ist im Prinzip das gleiche wie
char* antwort = malloc(4 * sizeof(char));

scanf schreibt also einfach ab der Speicheradresse von antwort[0] in den Speicher. Wie viel du die davon reserviert hast, ist ihm erstmal egal.
C erlaubt dem Programmierer ziemlich viel, dadurch kann man allerdings auch leicht Fehler verursachen. Gerade beim Speichermanagement.
 
  • Gefällt mir
Reaktionen: kingd0x
Bin durch die ganze Problematik mit dem Speicher und scanf auch schon auf malloc gestoßen.
Aber auch mit malloc wäre es dem scanf doch egal wie viele Zeichen man eintippt oder?
 
wenn du Visual C nutzt, dann kannst du auch scanf_s verwenden. Das ist die "sichere" version davon.
 
  • Gefällt mir
Reaktionen: kingd0x
In der Schule muss ich leider Code::Blocks nutzen und aus dem Grund versuche auch Privat alles mit Code::Blocks zu erlernen, damit ich hinterher keine Probleme kriege :)
 
Furiad schrieb:
Bin durch die ganze Problematik mit dem Speicher und scanf auch schon auf malloc gestoßen.
Aber auch mit malloc wäre es dem scanf doch egal wie viele Zeichen man eintippt oder?
Ja genau, ich wollte nur zeigen, warum man überhaupt weiter als die größe des Arrays schreiben kann.
 
  • Gefällt mir
Reaktionen: kingd0x
Ebrithil schrieb:
Ich weiß nicht ob du dich schon mit Pointern auseinander gesetzt hast.
char antwort[4];
ist im Prinzip das gleiche wie
char* antwort = malloc(4 * sizeof(char));
Uhm, da würde ich vorsichtiger sein. Sowohl für das Typsystem von C als auch die Speicherverwaltung sind das sehr unterschiedliche Dinge.
Für Funktionen die einen C-String nutzen ist es egal, da diese den Wert einfach als C-Pointer nutzen. Und da liegt auch das "Problem": Bei einem Pointer kennt man nur den Anfang der Array, nicht die Größe. Bei einem C-String wurde einfach festgelegt, dass das Ende durch einen Null-Char (\0) markiert ist. Sonst müsste man immer die Länge als Zahl mitgeben.
Hier sind die unterschiedlichen Bedeutungen genauer erklärt: https://en.cppreference.com/w/c/language/array
Falls das als Anfänger verwirrt, schau das Beispiel an:
C:
int a[3] = {1,2,3};
int* p = a;
printf("%zu\n", sizeof a); // prints size of array
printf("%zu\n", sizeof p); // prints size of a pointer
Es gibt im Typsystem von C quasi verschiedene Arten auf den Speicher in einer Array zu schauen.
Sobald man mit einem char* auf die Array guckt, hat der Compiler keine Ahnung wie groß der Bereich dahinter ist, da der Typ "Pointer" diese Info nicht enthält. Der char-Pointer weiß nur wie groß 1 char ist. Wie gesagt, C ist einfach doof! :D
(Wichtig ist auch, dass die Array mit fester Größe auf dem Stack existiert, und nicht mit free() gelöscht werden darf ;))
ldasta schrieb:
wenn du Visual C nutzt, dann kannst du auch scanf_s verwenden. Das ist die "sichere" version davon.
Das sollte in jedem Compiler gehen der C11 unterstützt. Der Sinn bei der _s Version ist, dass man die mögliche Größe der Eingaben festlegt, und damit einen Overflow verhindert.
 
  • Gefällt mir
Reaktionen: kingd0x
Ebrithil schrieb:
Ich weiß nicht ob du dich schon mit Pointern auseinander gesetzt hast.
char antwort[4];
ist im Prinzip das gleiche wie
char* antwort = malloc(4 * sizeof(char));

Ist es nicht... char antwort[4]; allocated auf dem Stack, malloc auf dem Heap, das ist ein großer Unterschied.

Ist das eine Uni-Aufgabe? Falls nicht, was spricht dagegen statt C direkt C++ für dein Projekt zu benutzen? Dann stände std::string zur Verfügung. Oder eine andere Sprache, rust zum Beispiel.
 
  • Gefällt mir
Reaktionen: kingd0x
GregoryH schrieb:
Ist es nicht... char antwort[4]; allocated auf dem Stack, malloc auf dem Heap, das ist ein großer Unterschied.

Ist das eine Uni-Aufgabe? Falls nicht, was spricht dagegen statt C direkt C++ für dein Projekt zu benutzen? Dann stände std::string zur Verfügung. Oder eine andere Sprache, rust zum Beispiel.
Ist mir bewusst, ist meiner Meinung nach für einen Anfänger aber keine relevante Information, ich wollts halt simpel halten.
 
  • Gefällt mir
Reaktionen: kingd0x
GregoryH schrieb:
Ist es nicht... char antwort[4]; allocated auf dem Stack, malloc auf dem Heap, das ist ein großer Unterschied.

Ist das eine Uni-Aufgabe? Falls nicht, was spricht dagegen statt C direkt C++ für dein Projekt zu benutzen? Dann stände std::string zur Verfügung. Oder eine andere Sprache, rust zum Beispiel.

Hi,
Nein, dies war keine Uni-Aufgabe. Bin in der Berufsschule und stelle mir momentan selbst kleine Aufgaben, die ich versuche mit C zu lösen. Ohne Praxis kann man meiner Meinung nach nicht lernen... und Theorie gibts momentan genug in der Schule.
Aus diesem Grund muss ich mich momentan (zwingend) mit C auseinandersetzten. Im nächsten Schuljahr geht es dann endlich mit Objektorientierten Sprachen weiter.


Und wie es der Zufall will, habe ich erneut eine Frage :)
Bin heute darauf aufmerksam geworden, dass man in C eine Windows MessageBox aufrufen kann.

C:
 int Box= MessageBox(NULL,"Restguthaben %.2lf auszahlen?","Rest-Guthaben",MB_ICONEXCLAMATION | MB_YESNO);
      if(IDYES == Box)
      {
          printf("Bitte Rueckgeld entnehmen! \n");
      }
      if(IDNO == Box) {
        printf("Vielen Dank f\x81r Ihre Spende! \n");
      }

Vielleicht kann man schon erkennen worum es geht.
Ich gebe einen Preis vor, bspw.
C:
double preis = 2.50;
und lasse dann Geld einwerfen.
Wirft die Person nun 5€ ein, entsteht ein Restguthaben von 2.50.
Nun möchte ich mit Hilfe der MessageBox fragen, ob das Restguthaben ausgezahlt werden soll, oder gespendet werden soll. (Ja ich weiß, ich hätte auch einfach mit einer If-Bedingung nach "Ja" und "Nein" fragen können)
Nun zu meiner Frage, kann ich in der MessageBox einen Wert aus einer Variable ausgeben lassen?
Ich berechne in einem Teil des Codes das Restguthaben aus.
Beispiel:
C:
double rest = einwurf - preis;
Beim printf würde es dann bspw so aussehen:
C:
double rest = einwurf - preis;
printf("Restguthaben: %.2lf",rest);
Funktioniert sowas auch bei der MessageBox?
So nach dem Motto:
C:
int Box= MessageBox(NULL,"Restguthaben !!!%.2lf!!! auszahlen?","Rest-Guthaben",!!!!rest!!!!,MB_ICONEXCLAMATION | MB_YESNO);[CODE]

Die !!! sollen nur verdeutlichen, was gemeint ist :D
 
Zuletzt bearbeitet:
Ich hab keine Ahnung von Windows-Programmierung, aber es sollte gehen, wenn du deinen String vorher schreibst und dann an die MessageBox übergibst.
C:
char text[40];
sprintf(text, "Restguthaben: %.2f", rest);
Box= MessageBox(NULL, text, MB_ICONEXCLAMATION | MB_YESNO);
 
  • Gefällt mir
Reaktionen: kingd0x
Zurück
Oben