2 Fragen: Pointer auf Arrays und Problem mit Quelltext
-
Guten Tag zusammen,
ich bin neu hier, da ich seit fast 3 Stunden an einem Problem sitze und echt nicht mehr weiter weiß. In der Schule haben wir C++ Programmierung. Nur ich bin eine richtige Niete darin und wollte ein bisschen dafür üben. Es geht um Funktionen und mit Pointer auf Arrays in Funktionen zugreifen. Zum üben wollte ich ein kleines Rundenbasierendes Spiel coden. Compiler sagt zwar keine Fehler an,doch wenn ich das Programm nicht als Admin starte bekommme ich :
"Windowsbefehlsexplorer funktioniert nicht mehr". Nach einiger Zeit startet das Programm und ich kann dann den Namen es ersten Spielers eingeben. Ich habe das ganze Programm in einer do-while Schleife geschrieben, damit man das Programm immer wieder neu starten kann. Nachdem ich den ersten Namen eingegeben habe, gibt der zwar den Text für die Eingabe des zweiten Namen aus, nur geht dann sofort zu der Eingabeaufforderung für einen Neustart. Wenn es es dann eingebe,
bekomme ich wieder "Windowsbefehlsexplorer funktioniert nicht mehr" und dann ganz weg.Problem 2: Mit Pointer auf Struct Array zugreifen
Ich wollte es so machen, dass man die Anzahl der Spieler in ein Array eingeben kann. Dieses Array hat als Dateityp eine Struct. Die Eingabe will ich in einer Funktion auserhalb der Main machen. Nur da bekomme ich auch keine Lösung. Ich bin mit meinem Latein am Ende und sitze schon seit über 4 Stunden davor.#include <iostream> #include <iomanip> #include <ctime> #include <windows.h> #include <cstdlib> #include <math.h> using namespace std; //=======================Prototypen=============================== void beginning(void); void spieler_name(struct spieler *); void weiter(char *); void umbruch(void); //========================Strukturen============================== struct spieler { char name[30]; }; //========================Main================================== int main () { char h; spieler Spieler1; spieler Spieler2; do { beginning(); spieler_name(&Spieler1); spieler_name(&Spieler2); weiter(&h); system ("CLS"); }while ( h == 'w' || h == 'W'); system("pause"); return 0; } //========================Funktionen========================= void beginning(void) { SetConsoleTitle("Abraxas_Games.cpp"); cout << "-------------------------------------------\n"; cout << "-------Abraxas Games----Version 1.0.0------\n"; cout << "-------------------------------------------\n"; system ("COLOR A"); cout << endl; } void weiter(char *h) { cout << "Fuer einen Neustart 'w' eingeben: "; cin >> h; } void spieler_name(spieler *spieler) { cout << "Geben Sie den Namen des Spielers ein!\n"; cout << "Es sind maximal 30 Zeichen verfuegbar! \n"; cout << "Eingabe: "; cin.get ((*spieler).name, 29); cout << endl; }Hier mal mein Quelltext. Bitte keine anfälligen Bemerkungen. Ich kann C++ einfach nicht. Und bitte helft mit mit meinen beiden Problemen.
Hoffe mal, dass ich hier ein bisschen Hilfe bekomme.
Richy
-
ungetestet:
#include <string> #include <iostream> #include <limits> #include <cctype> namespace AbraxasGames { struct Spieler { std::string Name; }; ::std::istream& operator>> (::std::istream& Stream, Spieler& Rhs) { return ::std::getline(Stream, Rhs.Name); } } int main() { std::cout << "-------------------------------------------\n"; std::cout << "-------Abraxas Games----Version 1.0.0------\n"; std::cout << "-------------------------------------------\n"; char Key; do { AbraxasGames::Spieler Spieler1; std::cout << "Geben Sie den Namen des Spielers ein!\n"; std::cout << "Eingabe: "; std::cin >> Spieler1; std::cout << std::endl; AbraxasGames::Spieler Spieler2; std::cout << "Geben Sie den Namen des Spielers ein!\n"; std::cout << "Eingabe: "; std::cin >> Spieler2; std::cout << std::endl; std::cout << "Fuer einen Neustart 'w' eingeben: "; std::cin.ignore(std::numeric_limits<std::streamsize>::max()); std::cin.get(Key); } while(std::tolower(Key) == 'w'); }
-
Bitte ohne diese ganzen "std::" und so. Bitte mit dem Problem an den Quelltext halten, den ich vorgemacht habe. Denn unsere Lehrerin will zu über 90% alles aus der main() Funktion auslagern. Zudem bin ich ein purer Anfänger.
-
XAbraxasx schrieb:
Zum üben wollte ich ein kleines Rundenbasierendes Spiel coden.
XAbraxasx schrieb:
Denn unsere Lehrerin will zu über 90% alles aus der main() Funktion auslagern.
"ok"
-
Die Fehler sind, wie du schon selber vermutest, in den Pointern. Du kannst damit offensichtlich noch nicht umgehen, was nicht verwunderlich ist, Pointer (und Arrays) sind ein recht schwieriges Thema, da sie anders sind als alles andere in C++. Doch man braucht sie auch gar nicht:
#include <iostream> // #include <iomanip> Wozu? // #include <ctime> Wozu? // #include <windows.h> Lasse ich mal weg, da unportabel // #include <cstdlib> system habe ich mal gestrichen, siehe unten. // #include <math.h> ??? Du hast doch schon cmath und cmath war unnötig // Binde keine Header auf gut Glück ein! Nimm genau die Header, die du brauchst. // Keinen zu viel, keinen zu wenig. #include <string> // Der ist später nützlich. Geht schließlich um Zeichenketten. using namespace std; //=======================Prototypen=============================== // Ich definiere die Funktionen lieber gleich. // Allgemein: // void als Parametertyp ist C. In C++ einfach weglassen: // void beginning(void); // wird zu // void beginning(); // struct vor Typen ist C. In C++ einfach weglassen: // void spieler_name(struct spieler *); // wird zu // void spieler_name(spieler *); // Zeiger braucht es in C++ nicht für "call by reference". Dafür gibt es Referenzen. // void spieler_name(spieler *); // wird zu // void spieler_name(spieler &); //========================Strukturen============================== struct spieler { // char name[30]; // string ist viel besser als char-Arrays string name; }; void beginning() { // SetConsoleTitle("Abraxas_Games.cpp"); // Unportabel cout << "-------------------------------------------\n"; cout << "-------Abraxas Games----Version 1.0.0------\n"; cout << "-------------------------------------------\n"; // system ("COLOR A"); // Unportabel cout << endl; // Wieso denken Anfanger immer, ein Titelbild und Versionsnummern wären das wichtigste? } void weiter(char &h) { cout << "Fuer einen Neustart 'w' eingeben: "; cin >> h; } void spieler_name(spieler &spieler) { cout << "Geben Sie den Namen des Spielers ein!\n"; // cout << "Es sind maximal 30 Zeichen verfuegbar! \n"; // Dank string keine Beschränkung. cout << "Eingabe: "; getline(cin, spieler.name); cout << endl; } //========================Main================================== // Redundante Kommentare lassen wir besser weg. Man sieht doch, dass hier die main // kommt. Steht schließlich dran. int main () { char h; // spieler Spieler1; // spieler Spieler2; // Variablen erst dort definieren, wo man sie braucht. Hier wird nur h gebraucht. do { beginning(); spieler Spieler1; spieler_name(Spieler1); spieler Spieler2; spieler_name(Spieler2); weiter(h); // system ("CLS"); // Unportabel. } while ( h == 'w' || h == 'W'); // system("pause"); // Siehe Konsolen-FAQ wie das besser geht. // return 0; // Brauchen wir in C++ in der main nicht. }Wenn du es übrigens genau wissen möchtest, der Fehler lag in der weiter-Funktion. Da hast du den istream::operator>> auf einen char* angewandt. Das liest eine Zeichenkette im C-Stil ein (nullterminiertes char-Array). Aber dein char* zeigte nur auf ein einzelnes Zeichen (das h in der main), was nicht zusammen passte.
-
Echt vielen Dank für diese ausführliche Antwort. Zu den Sachen, unsere Lehrerin will das wir einen sogenannten "Rohbau" benutzen. Und diesen habe ich auch hier verwendet.
Jetzt hätte ich nur noch eine kleine Frage. Und zwar wie greift man mit einem Pointer in einer Funktion auserhalb von main() auf ein Array innerhalb der main (). Zm Beispiel wenn man aus:#include <iostream> #inlcude <string> using namespace std; void spieler( spieler *); struct spieler { string name; int energie; int Leben; }; int main () { spieler spieler_anz[10]; return 0; } void spieler(*pointer) { //Eingabe des Arrays für mehrere Spieler }Wie ruft man diese Funktion in der main() auf und wie würden die Eingaben für das Array "spieler_anz" in der unteren Funktion aussehen. Geht das auch mit "cin >>" oder was muss ich da noch nutzen ? Da ein kleines Beispiel für den Namen wäre nett.
-
Die Frage ist etwas komisch. Was soll das mit cin zu tun haben? Die Frage ist eher, wie man korrekt mit Arrays umgeht und das hier ist schon im Ansatz falsch.
In (anfängerhaftem) C würde man das so machen:
void spieler(spieler *pointer, size_t length) { // Hier irgendwas mit pointer machen, dabei length beachten }In C++ würde man gar nicht erst mit rohen Arrays arbeiten, sondern stattdessen mit vector oder array. Und natürlich ohne Pointer! zum Beispiel:
void spieler(vector<spieler> &spielervector) { // Hier irgendwas mit spielervector machen }Das ist aber ziemlich unflexibel und macht man eigentlich nicht so. Wenn man irgendeinen Bereich von Objekten übergeben möchte, übergibt man stattdessen Anfang und Ende, meinetwegen als Zeiger:
void spieler(spieler *anfang, spieler *ende) { // Hier irgendwas mit den Objekten zwischen *anfang und *ende machen }Aber besser und viel allgemeiner wieder ohne Zeiger, stattdessen mit einem allgemeinen Iterator (hast du vermutlich noch nie gesehen):
template <typename Iterator> void spieler(Iterator anfang, Iterator ende) { // Hier irgendwas mit den Objekten zwischen *anfang und *ende machen }So sähe das in "normalem" C++ aus. Das ihr bei eurer Lehrerin vermutlich nie zu Gesicht bekommen werdet. Aber fast alle Funktionen der Standardbibliothek, die auf Bereichen von Objekten arbeiten, sehen so aus. Denn dann ist man weder auf Arrays, std:array, vector oder sonst etwas beschränkt, das funktioniert dann automatisch mit allem, ohne dass es Zusatzaufwand beim Programmieren wäre.
Aber hier willst du gar nicht auf einem Bereich von Objekten arbeiten, du willst doch anscheinend Objekte zu etwas hinzu fügen. Das heißt eigentlich wieder etwas in der Art von:
void spieler(vector<spieler> &spielervector) { // Hier etwas zu spielervector hinzu fügen }Aber auch das geht wieder allgemein. Wir kennen nur den Anfang, wo etwas eingefügt werden soll. Das Ende ist da, wo wir mit dem Einfügen aufhören:
template <typename Iterator> void spieler(Iterator it) { // Hier jeweils *it etwas zuweisen und it erhöhen. }So sähe das wieder normal aus.
Das eigentliche Problem hier ist vermutlich der Lehrer. Das ganze sieht sehr nach C mit cout aus, was kein C++ ist, sondern einfach schlechtes C, das nicht einmal mehr mit einem C-Compiler übersetzt werden kann. Auch die sonstigen Tipps sind eher besch..eiden:
will das wir einen sogenannten "Rohbau" benutzen.
Einfach nur unflexibel.will zu über 90% alles aus der main() Funktion auslagern
Naja. Ist schon ziemlich komisch, wenn das zu Funktionen wie deinem
weiterführt.
-
Erstmal wirklich danke nochmal. Zweitens, ich bin schlecht in Programmierung. Gottseidank ist dies nicht mein Wahl Fach und habe ich nur ein Jahr. Nur ein Problem bleibt immer noch,und zwar das mit dem "Windows-Befehlsprozessoer funktioniert nicht".
-
Das liegt an deiner weiter Funktion.
Du übergibst der die Adresse eines chars.
Dann rufst du operator >> mit dem char* auf. Ich hab zwar keine Ahnung welche Funktion da aufgerufen wird* oder welche Konvertierungsregeln da auftreten (kann das sein: char* zu bool?), jedenfalls ist das der falsche operator >>.
Du musst std::cin.get(*h) verwenden, dann liest der ein Zeichen.Laut Referenz gibts nämlich keinen operator >> der char nimmt.
-
Nathan schrieb:
Du musst std::cin.get(*h) verwenden, dann liest der ein Zeichen.+
Besser:
cin >> *h;Denn get überspringt keinen Whitespace.
Oder noch besser, wie in den ersten paar Beiträgen gezeigt.
-
Nathan schrieb:
Das liegt an deiner weiter Funktion.
Du übergibst der die Adresse eines chars.
Dann rufst du operator << mit dem char* auf. Ich hab zwar keine Ahnung welche Funktion da aufgerufen wird* oder welche Konvertierungsregeln da auftreten (kann das sein: char* zu bool?), jedenfalls ist das der falsche operator <<.
Du musst std::cin.get(*h) verwenden, dann liest der ein Zeichen.Laut Referenz gibts nämlich keinen operator << der char nimmt.
Nun, eigentlich gibt es schon einen überladenen Operator >> dafür, nur halt nicht als Memberfunktion: http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt2
-
Flashput schrieb:
Nathan schrieb:
Das liegt an deiner weiter Funktion.
Du übergibst der die Adresse eines chars.
Dann rufst du operator >> mit dem char* auf. Ich hab zwar keine Ahnung welche Funktion da aufgerufen wird* oder welche Konvertierungsregeln da auftreten (kann das sein: char* zu bool?), jedenfalls ist das der falsche operator <<.
Du musst std::cin.get(*h) verwenden, dann liest der ein Zeichen.Laut Referenz gibts nämlich keinen operator << der char nimmt.
Nun, eigentlich gibt es schon einen überladenen Operator >> dafür, nur halt nicht als Memberfunktion: http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt2
Nanu?

Kann mir mal einer den Grund dafür erklären?
Dann liegt der Fehler daran, dass der char* operator >> versucht ein Array einzulesen, h aber nur die Adresse eines Zeichen ist.
-
Edit: Ach, du meinst den Einlese-Operator.
Wurde verwirrt, da du schließlich mehrmals << notierst.
-
- schrieb:
Edit: Ach, du meinst den Einlese-Operator.
Wurde verwirrt, da du schließlich mehrmals << notierst.Ups.