[ C ] Problem mit dem Schlüsselwort char
Sven
- programmiertechnik
0 Montgomery0 Hopsel
2 Der Martin
0 Sven
Hallo,
wie der ein oder andere vieleicht weiß, befasse ich mich seit Gestern mit der C Programmierung unter Linux.
Ich habe mal folgenden Code geschrieben:
--------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <time.h>
int main(void){
system("clear");
// Darf die Variable "wort1" nur 5 Zeichenwerte haben?
char wort1[5];
char wort2[5];
int zahl;
int erg;
int b;
int lang;
int a;
printf(" Erwarte eingabe: \n");
erg=scanf("%s %s %d",&wort1,wort2, &zahl);
if(erg!=3)
{
printf("Es fehlt etwas!");
}
else
{
printf("Du hast: %s und %s und wie Zahl: %d eingegeben!\n Ergebniss: %d \n",wort1,wort2,zahl,erg);
lang=strlen(wort1);
for(a=0;a < lang;a++)
{
//Sollten hier nicht die Buchstaben des eingegebenen Wortes kommen?? Bekomme aber die Meldung: Speicherzugriffsfehler!
printf("%s",wort1[a]);
}
}
return 0;
}
--------------------------------------------------------------------
Ist die Variable die ich mit "char" deklariert habe kein Array?
Ich habe zwar:
char wort1[5];
eingegeben und verstehe das so das jetzt nur 5 Zeichen gültig sind, also so:
wort1[0] = "S"
wort1[2] = "e"
wort1[3] = "l"
wort1[4] = "f"
wort1[5] = "\0"
Ich habe mir strlen die länge des Wortes ausgelesen und mit einer for-schleife wollte ich mir nun die einzelnen Buchstaben ausgeben lassen, aber ohne erfolg.
Gebe ich aber ein Wort mit nicht 5 sondern 10 Zeichen ein, wird das trotzdem angenommen, wieso wenn das doch auf 5 begrenzt ist?
Danke für Hilfreiche antworten!
naja, das ist halt c - da darf man nicht so komplex denken *g*
1. char wort1[5]; ist nur von 0-4 d.h. da bleibt kein platz für '\0' übrig
2. wenn du mehr als 5 zeichen rein schreibst, dann wird da einfach über die grenzen hinaus (in den speicherbereich anderer variablen oder funktionen) geschrieben
Hi Montgomery!
- char wort1[5]; ist nur von 0-4 d.h. da bleibt kein platz für '\0' übrig
0 - 1 - 2 - 3 - 4
Ich zähle fünf. ;-)
MfG H☼psel
Ich zähle fünf. ;-)
hm... stimmt...
»»wort1[0] = "S"
»»wort1[2] = "e"
»»wort1[3] = "l"
»»wort1[4] = "f"
»»wort1[5] = "\0"
da hat aber jemand die 1 vergessen, das hab ich übersehen *g*
Hi,
// Darf die Variable "wort1" nur 5 Zeichenwerte haben?
char wort1[5];
ja - so wie du sie deklarierst, hast du Platz für 5 Zeichen vorgesehen. Also 4 Zeichen Nutzdaten und die abschließende 0 als Endekennzeichen.
printf(" Erwarte eingabe: \n");
erg=scanf("%s %s %d",&wort1,wort2, &zahl);
Das kann heikel sein, wie du weiter unten selbst andeutest.
for(a=0;a < lang;a++)
{
printf("%s",wort1[a]);
//Sollten hier nicht die Buchstaben des eingegebenen Wortes kommen?? Bekomme aber die Meldung: Speicherzugriffsfehler!
Das ist für den Insider auch logisch. Betrachten wir mal dein Beispiel:
wort1[0] = "S" = 0x53
wort1[2] = "e" = 0x65
wort1[3] = "l" = 0x6C
wort1[4] = "f" = 0x66
wort1[5] = 0
Im ersten Schleifendurchlauf hat der printf()-Aufruf also die Werte:
printf("%s", 0x53);
Das bedeutet: Gib den String aus, der im Speicher ab Adresse 0x53 steht. Nur "gehört" diese Speicheradresse höchstwahrscheinlich gar nicht deinem Programm, sondern einem anderen Programm oder gar dem Betriebssystem selbst. Also greifen hier die Schutzmechanismen, die verschiedene Prozesse gegeneinander abgrenzen sollen.
Was du vorhast, nämlich die Zeichen eines Strings einzeln auszugeben, ist eigentlich ganz einfach - du musst die printf-Funktion nur anweisen, das Argument nicht als String (d.h. als Adresse eines char-Arrays) aufzufassen, sondern tatsächlich als Einzelzeichen. Dafür steht die Formatanweisung %c.
Ist die Variable die ich mit "char" deklariert habe kein Array?
Ich habe zwar:
char wort1[5];
eingegeben und verstehe das so das jetzt nur 5 Zeichen gültig sind, also so:wort1[0] = "S"
wort1[2] = "e"
wort1[3] = "l"
wort1[4] = "f"
wort1[5] = "\0"
Absolut korrekt.
Gebe ich aber ein Wort mit nicht 5 sondern 10 Zeichen ein, wird das trotzdem angenommen, wieso wenn das doch auf 5 begrenzt ist?
Die Eingaberoutine, die von scanf() intern benutzt wird, kann nicht wissen, wieviel Speicherplatz du für die eingegebenen Werte vorgesehen hast. Sie speichert so viel, wie tatsächlich eingegeben wurde. In deinem Fall merkt man das bei geringfügigen Überschreitungen nicht, weil die nacheinander deklarierten Variablen auch im Speicher wahrscheinlich direkt hintereinander liegen:
[x + 0] wort1
[x + 5] wort2
[x + 10] zahl
[x + 14] erg
usw.
Das x vorne steht jetzt für eine beliebige Adresse, an der im Speicher dein Variablenbereich beginnt. Der Absolutwert muss uns nicht interessieren.
Aber pass auf: Wenn du bei der Eingabe von wort1 mehr Zeichen eingibst als vorgesehen, wird die überschüssige Länge bereits in wort2 hineingeschrieben. Bei der nachfolgenden Eingabe von wort2 werden diese überzähligen Zeichen wieder überschrieben.
Die Überprüfung der korrekten Länge von Eingaben, die von außerhalb kommen, ist ein *ganz* wichtiges Thema. Viele gravierende Bugs in bekannten Softwareprodukten kommen von einer Schlamperei in diesem Punkt - das führt dann zu den berüchtigten "buffer overflows": Eingegebene Daten laufen über den vorgesehenen Speicherbereich hinaus und überschreiben andere Daten im Speicher. Oft führt das zu einem Programmabsturz. Wenn man aber den Aufbau und die Funktionsweise eines Programms sehr genau kennt, kann man solche Effekte u.U. ausnutzen, um sogar ein vorhersehbares Fehlverhalten zu provozieren - und schon hat man einen Bug für eventuell bösartige Manipulationen ausgenutzt.
Deswegen -um zu deinem Beispiel zurückzukehren- ist es eine gute Idee, die scanf-Funktionsfamilie zunächst zu meiden und stattdessen z.B. gets() zu verwenden. Damit hat man auch eine Eingabe realisiert, aber man kann eine maximale Länge vorgeben, die dann nicht überschritten wird. Überzählige Zeichen bei der Eingabe werden einfach ignoriert.
So long,
Martin
Hallo Martin,
super lieben dank für deine Hilfreiche Antwort, nun verstehe ich, aber
du meintest ja das ich lieber erstmal scanf meiden soll und eingaben mit gets() entgegen nehmen sollte um eine maximal Länge der eingabe festzulegen, aber soweit ich es verstanden habe ist das doch auch mit scanf möglich, also so: scanf("%20",string); ich habe das gelesen und auch ausprobiert, es werden wirklich nur 20 Zeichen angenommen. Oder werden trotzdem alles Zeichen in den Speicher geschrieben?
Danke && einen schönen Sonntag noch!
Hallo Sven,
[...] aber soweit ich es verstanden habe ist das doch auch mit scanf möglich, also so: scanf("%20",string);
stimmt, daran hatte ich gar nicht mehr gedacht. Abgesehen davon, dass du hier das 's' vergessen hast - also "%20s". ;-)
Oder werden trotzdem alles Zeichen in den Speicher geschrieben?
Soweit ich weiß, nein. Aber da bin ich nicht absolut sicher.
Schönen Tag noch,
Martin