Forum: PC-Programmierung char Verständnis bei der Eingabe


von Michael (Gast)


Lesenswert?

Kurze frage zu char mit c++:

Wenn ich eine Eingabe tätigen möchte,  geht das mit findet. Aber wenn 
ich lediglich cin nutze,reicht die angabe des array:

char name[30];
cin >> name;
cout << name ;

Das char array "name" liefert ja die anfangsadresse. Wenn ich aber cin>> 
name[0] schreibe, geht das nur wenn ich den Adress Operator davor 
schalte. Verstehe ich das richtig?

Dann habe ich noch eine Frage zu cin.ignore. Wenn ich das verwende, wird 
mein erster Buchstabe angeschnitten, ohne gibt es aber eine 
Endlos-Schleife

von Felix U. (ubfx)


Lesenswert?

Michael schrieb:
> Kurze frage zu char mit c++:
>
> Wenn ich eine Eingabe tätigen möchte,  geht das mit findet.
?

> Aber wenn
> ich lediglich cin nutze,reicht die angabe des array:
>
> Das char array "name" liefert ja die anfangsadresse.

Es liefert sogar auch noch den Typ des Arrays. Und daran kann der 
überladene Operator >> dann erkennen, um was es geht. Konkret wird wenn 
du ein char-array übergibst, diese Überladung ausgeführt:
1
basic_istream<_Elem, _Traits>& operator>>(
2
    basic_istream<_Elem, _Traits>& _Istr, _Elem *_Str)

Und die liest von der Konsole bis ein EOF oder whitespace (enter) 
Zeichen kommt. Und zwar auch, wenn dein buffer gar nicht lang genug ist. 
Das heißt, du kannst in einen char[3] auch 10 Zeichen einlesen. Und dann 
gibt es einen Buffer overflow, darauf sollte man also achten.

> Wenn ich aber cin>>
> name[0] schreibe, geht das nur wenn ich den Adress Operator davor
> schalte. Verstehe ich das richtig?

&foo[0] ist das gleiche wie foo, das ändert also nichts. Wenn du aber 
einen einzelnen Char einlesen willst, kannst du
1
std::cin >> foo[0];

benutzen, das ruft die folgende Version des Operators auf:
1
basic_istream<_Elem, _Traits>& operator>>(
2
    basic_istream<_Elem, _Traits>& _Istr, _Elem& _Ch)
Da wird also nur ein einzelner Char gelesen.

> Dann habe ich noch eine Frage zu cin.ignore. Wenn ich das verwende, wird
> mein erster Buchstabe angeschnitten, ohne gibt es aber eine
> Endlos-Schleife

Wie genau wendest du das an?

: Bearbeitet durch User
von Michael (Gast)


Lesenswert?

Hi, das hier löscht mir das erste Zeichen, laut meinem Buch sollte es 
aber funktionieren:

cout << "Bitte Spielernamen eingeben:" ;
cin.ignore();
cin.get(m_Name, 29);
cout << "Name: "<< m_Name << endl;

von nicht"Gast" (Gast)


Lesenswert?

Hallo,


wenn du schon C++ benutzt, dann nimm für so was bitte std::string. Damit 
brauchst du dir keine Sorgen mehr über irgend welchen Speicher machen.

von Felix U. (ubfx)


Lesenswert?

Michael schrieb:
> Hi, das hier löscht mir das erste Zeichen

Das wird daran liegen, dass die Standardparameter von istream.ignore 
angeben, dass mindestens 1 Zeichen entfernt wird. Ob da noch 
Zeilenumbrüche (\r, \n oder beides) im Buffer rumhängen wird vermutlich 
betriebssystemabhänhig sein. Kann also gut sein, dass es unter Linux 
funktioniert aber unter Windows nicht.
Mit den Streams die irgendwelche OS-Funktionen kapseln habe ich in C++ 
auch nur schlechte Erfahrungen gemacht, deshalb nutze ich da immer nur 
die stdio.h Funktionen, also scanf, printf, fopen, fread und so weiter.

von Michael (Gast)


Lesenswert?

Jetzt habe ich mal eine andere Frage:
1
char name[30];
2
cin >> name;

oder
1
char name[30];
2
cin >> &name[0];

funktioniert beides. Das heißt, dass das Array mir die Anfangsadresse 
bei der Eingabe liefert.

Wieso schreibt man bei einfachen Variablen nicht einfach auch:
1
int x;
2
cin >> &x;  // & Operator ist hier falsch, aber wieso? Bei Arrays wird doch auch die Anfangdadresse geliefert.

Im Vergleich zu C++ ist das in C auch nicht anders. Entweder schreibt 
man für scanf einfach "&x", also mit Adressoperator oder aber bei einem 
char-Array "name", dass ja die Anfangdadresse liefert. Warum ist bei C++ 
das ganze bei normalen Variablen ohne den Adressoperator?

von Felix U. (ubfx)


Lesenswert?

Michael schrieb:
> funktioniert beides. Das heißt, dass das Array mir die Anfangsadresse
> bei der Eingabe liefert.

Richtig. Das Array IST zur Laufzeit auch nur noch seine Anfangsadresse. 
Die Information über die Größe, die du deklariert hast, ist zur Laufzeit 
nicht mehr vorhanden. Und zwar sowohl in C als auch in C++. Ein Array 
ist also nichts anderes als ein Pointer auf das erste Element.
1
char bla[10];
2
char *bla1 = bla; // bla1 ist zur Laufzeit komplett identisch zu bla

Jetzt ist auch einleuchtend, warum &bla[0] genau das gleiche ist wie 
bla. Denn der [] Operator dereferenziert den Pointer ein mal, und der 
Adressoperator macht das direkt wieder rückgängig.

> Wieso schreibt man bei einfachen Variablen nicht einfach auch:
>
>
1
> int x;
2
> cin >> &x;  // & Operator ist hier falsch, aber wieso? Bei Arrays wird 
3
> doch auch die Anfangdadresse geliefert.
4
>

Weil es eben keine Überladung des >> Operators für int-Arrays gibt. Wenn 
du wolltest, könntest du eine schreiben, dann würde das funktionieren.

> Im Vergleich zu C++ ist das in C auch nicht anders. Entweder schreibt
> man für scanf einfach "&x", also mit Adressoperator oder aber bei einem
> char-Array "name", dass ja die Anfangdadresse liefert. Warum ist bei C++
> das ganze bei normalen Variablen ohne den Adressoperator?

Weil der >> Operator für jeden zulässigen Typ eine eigene Überladung 
hat.

Wenn du cin >> x; machst wird intern eine Referenz auf x an die 
Einlesefunktion übergeben. Referenzen sind nochmal spezielle 
C++-Konstrukte ähnlich wie Pointer, die der aufgerufenen Funktion 
ermöglichen, die Variable zu ändern, ohne dass du einen Pointer 
übergeben hast (in C ginge das nicht).

: Bearbeitet durch User
von Michael (Gast)


Lesenswert?

Guten Morgen,
vielen Dank für die ausführliche Erklärung. Das heißt, dass durch das 
Überladen durch den Operator ">>" erkannt wird, um welchen Datentyp es 
sich handelt und der Nutzer muss sich nicht mehr darum kümmern, ob er 
eine Referenz einer Variablen oder die Variable selbst übergibt, 
korrekt?

In C war das nämlich anders, da hier die Adresse der Variablen übergeben 
werden sollte und zwar für alle Datentypen. Bei Arrays und Zeiger 
entfiel dies, weil das Array selbst, z.B. XYZ, bereits die 
Anfangsadresse liefert.

von Felix U. (ubfx)


Lesenswert?

Michael schrieb:
> Guten Morgen,
> vielen Dank für die ausführliche Erklärung. Das heißt, dass durch das
> Überladen durch den Operator ">>" erkannt wird, um welchen Datentyp es
> sich handelt und der Nutzer muss sich nicht mehr darum kümmern, ob er
> eine Referenz einer Variablen oder die Variable selbst übergibt,
> korrekt?
Genau. Und weil es keinen Referenz Operator gibt, muss der Nutzer sich 
auch darum nicht kümmern. Wenn die aufgerufene Funktion oder der 
Operator eine Referenz erwartet, dann wird die Variable automatisch 
referenziert.

> In C war das nämlich anders, da hier die Adresse der Variablen übergeben
> werden sollte und zwar für alle Datentypen. Bei Arrays und Zeiger
> entfiel dies, weil das Array selbst, z.B. XYZ, bereits die
> Anfangsadresse liefert.
jap

von Dr. Sommer (Gast)


Lesenswert?

Felix U. schrieb:
> Mit den Streams die irgendwelche OS-Funktionen kapseln habe ich in C++
> auch nur schlechte Erfahrungen gemacht, deshalb nutze ich da immer nur
> die stdio.h Funktionen, also scanf, printf, fopen, fread und so weiter.

Aber das sind C-Wrapper, die die eigentlichen OS Funktionen kapseln 
(open/read/write unter Unix, CreateFile, ReadFile, WriteFile unter 
Windows).
Die Bedienung der io streams ist für C Programmierer ungewohnt, aber die 
können genau so viel und sind dabei auch noch Typ sicher - wenn man den 
Typ einer Variablen ändert passt sich bei cout die Ausgabe automatisch 
an, bei printf nicht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.