Benutzereingabe für getline() wird übersprungen

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
maekki
Beiträge: 2
Registriert: Mi Mär 06, 2013 11:02 pm

Benutzereingabe für getline() wird übersprungen

Beitrag von maekki » Mi Mär 06, 2013 11:18 pm

Hallo, meine erste Frage in eurem Forum. Aber zuerst will ich mich bei euch für die Arbeit an den Tutorials bedanken. Mir gefallen, dass auch Details gut beschrieben werden. Nun zu meinem Problem:

Code: Alles auswählen

#include <iostream>
#include <cstring>
using namespace std;

int main(void) {
     char name[60];
     char vname[5];
     char nname[5];

     cout << "Vorname  : ";
     cin.getline( vname, sizeof(vname) );
     cout << "Nachname : ";
     cin.getline( nname, sizeof(nname) );

     strncpy( name, vname, sizeof(name)-1 );
     strncat( name, " ", 1 );
     strncat( name, nname, sizeof(name)-strlen(name)-1);
     name[sizeof(name)-1] = '\0';

     cout << "Vollständiger Name: " << name << '\n';
     return 0;
}
Wenn ich das Programm ausführe und für "vname" z.B. den String "ABCDEFGH" eingebe, dann wird die Eingabe von "nname" übersprungen und "ABCD" ausgegeben. Diese Ausgabe kann ich mir ja noch erklären, aber warum wird die Eingabe für "nname" übersprungen? Und was passiert mit dem Teilstring "EFGH"?

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Benutzereingabe für getline() wird übersprungen

Beitrag von cloidnerux » Mi Mär 06, 2013 11:38 pm

Hi und Willkommen im Forum.
Dein Problem wird wrsl beim Eingabebuffer liegen:
http://www.proggen.org/doku.php?id=c:faq:input-puffer(Ich hoffe gerade mal, dass es die richtige Seite ist, auf die ich verweisen will :D )

MfG cloidnerux
Redundanz macht wiederholen unnötig.
quod erat expectandum

GilbertDur
Beiträge: 105
Registriert: Fr Mär 01, 2013 10:31 am

Re: Benutzereingabe für getline() wird übersprungen

Beitrag von GilbertDur » Do Mär 07, 2013 11:28 am

versuch es mal mit:

Code: Alles auswählen

cin.clear();
vor dem zweiten

Code: Alles auswählen

cin.getline();

maekki
Beiträge: 2
Registriert: Mi Mär 06, 2013 11:02 pm

Re: Benutzereingabe für getline() wird übersprungen

Beitrag von maekki » Do Mär 07, 2013 12:30 pm

@cloidnerux: Danke für den Link.

@GilbertDur: Hab die Zeile cin.clear() eingefügt vor dem zweiten cin.getline(). Kommt was interessantes heraus. Bei einer Eingabe von "ABCDEFGHIJKL wird im String "vname" "ABCD" gespeichert, und im String "nname" "EFGH". Dabei wird aber die Eingabe für "nname" wieder übersprungen. :?

GilbertDur
Beiträge: 105
Registriert: Fr Mär 01, 2013 10:31 am

Re: Benutzereingabe für getline() wird übersprungen

Beitrag von GilbertDur » Do Mär 07, 2013 2:25 pm

Ok, erst mal ein paar grundsätzliche Sachen. Du hast im Code vname für 5 Zeichen definiert. Da kannst du dann nicht ABCDEFGHIJKL reinbringen. Das wird natürlich abgeschnitten, da es eben mehr als 5 Zeichen sind. Dann ist der strncat-Befehl viel zu kompliziert. Ich würde das eher so machen:

Code: Alles auswählen

#include <iostream>
#include <string>

using namespace std;

int main()
{
     char name[60];
     char vname[6];
     char nname[6];

     cout << "Vorname  : ";
     cin.getline( vname, sizeof(vname)); 
     cout << "Nachname : ";

     cin.getline( nname, sizeof(nname)); 

     strncpy(name, vname, sizeof(vname));
     strncat(name, " ", 1);
     strncat(name, nname, sizeof(nname));
     name[sizeof(name)-1]='\0';
     cout << name;

     return 0;
}
Naja, eigentlich würde ich das nicht so machen, einfach, weil es unpraktikabel ist. Dieses Programm wird immer Probleme mit Zeichenketten haben, die zu lang sind. Daher sollte man das ganze etwas dynamischer gestalten, sprich: so viel Speicher, wie man braucht, mit dem new-Schlüsselwort anlegen.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Benutzereingabe für getline() wird übersprungen

Beitrag von fat-lobyte » Do Mär 07, 2013 4:54 pm

GilbertDur hat geschrieben:versuch es mal mit:

Code: Alles auswählen

cin.clear();
vor dem zweiten

Code: Alles auswählen

cin.getline();
Bitte nicht einfach "Versuch mal". Das wird nicht funktionieren, da cin.clear() nur die Errorflags löscht - nicht aber den eingabepuffer. Das steht übrigens auch in dem Artikel.

Das sind die magischen Zeilen:

Code: Alles auswählen

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
Und vorher noch zusätzlich #include <limits>


Bitte mach das nicht nicht mit strcat/oder ähnlichem!!! Damit schießt du dir selbst ins Knie.

Entweder du akzeptierst, dass du nur eine bestimmte anzahl von Zeichen eingeben kannst, dann kannst du es mit "cin.getline()" einlesen. Oder du machst es mit wahrem dynamischen Memory-management, und verwendest einfach std::string::operator>>:

Code: Alles auswählen

// extract to string
#include <iostream>
#include <string>

main ()
{
  std::string name;

  std::cout << "Please, enter your name: ";
  std::cin >> name;
  std::cout << "Hello, " << name << "!\n";

  return 0;
}
Siehe http://www.cplusplus.com/reference/stri ... tor%3E%3E/

Eine Bitte an alle: Wenn ihr C++ Programmiert, solltet ihr die String-Funktionen von C tunlichst vermeiden.
Haters gonna hate, potatoes gonna potate.

GilbertDur
Beiträge: 105
Registriert: Fr Mär 01, 2013 10:31 am

Re: Benutzereingabe für getline() wird übersprungen

Beitrag von GilbertDur » Do Mär 07, 2013 6:27 pm

fat-lobyte hat geschrieben:
GilbertDur hat geschrieben:versuch es mal mit:

Code: Alles auswählen

cin.clear();
vor dem zweiten

Code: Alles auswählen

cin.getline();
Bitte nicht einfach "Versuch mal". Das wird nicht funktionieren, da cin.clear() nur die Errorflags löscht - nicht aber den eingabepuffer. Das steht übrigens auch in dem Artikel.
Da hast du natürlich recht. cin.ignore() ist mir dann später auch noch eingefallen. Das kommt davon, wenn man unregelmäßig C++ macht :D
Aber hier noch mal die Frage an den Threadersteller: Willst du C oder C++ programmieren? Der Code sieht wie eine Mischung beider Sprachen aus, was meistens nicht lange gut geht.

Antworten