Ergebnis 1 bis 9 von 9

C++ nur Eingabe einzelner Zeichen erlauben

  1. #1 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Hallo,
    ich habe folgendes Problem:
    Wir sollen Schiffe versenken programmieren als Prüfungsbeleg. Das Programm an sich läuft schon ganz gut, es werden zufallsgeneriert Schiffe in ein 10x10-Feld gesetzt und man hat mehrere Spielmodi wo man einmal die Schiffe anzeigen lassen kann und einmal nur das Meer. Das bereitete uns soweit keine Probleme.
    Jetzt kommt man aber zu der Stelle wo man dann Koordinaten eingeben muss und da geht es los, das ist jetzt ein ausschnitt, bei dem die eingabe anfängt, davor ist nur noch eine schleife, die nach fehlerhafter eingabe die eingabe erneut ablaufen lassen soll..

    Code:
    (char spalte1[2]; int  zeile; int spalte2; //wurde an früherer stelle im programm geschrieben)
    
    for (int eingabeRichtig = 0; eingabeRichtig < 1;){
    			printf_s("\n\nWohin willst du schiessen?\n");
    			printf_s("\nnach Westen (Spalte):");
    			scanf_s("%2c", &spalte1);
    			printf_s("\nnach Sueden (Zeile):");
    			scanf_s("%d", &zeile);
    			if (zeile >= 0 && zeile <= 9){
    				if (spalte1[1] >= 'A' && spalte1[1] <= 'J'){
    					spalte2 = spalte1[1] - 'A';
    					eingabeRichtig = 1;
    				}
    				if (spalte1[1] >= 'a'&&spalte1[1] <= 'j'){
    					spalte2 = spalte1[1] - 'a';
    					eingabeRichtig = 1;
    				}
    				else printf_s("\nDas Feld gibt es nicht. Nocheinmal so ein Unfug und ich lass dich Kielholen. \nNOCHMAL!");
    				spalte2 = spalte2 + 3;
    				zeile = zeile + 3;
    				if (Spielfeld[zeile][spalte2].getroffen == 1){
    					printf_s("\nDahin haben wir schon geschossen. Kanonenkugeln sind kein Fischfutter!");
    				};
    			}
    			else{
    				printf_s("\nDas Feld gibt es nicht. Ich lass dich die Kombuese schrubben! \nNOCHMAL!");
    			}
    		}
    ich bin mir sicher, dass allein in diesen zeilen schon fehlerquellen stecken, denn:
    wenn man nach dem ersten scanf_s nicht nur einen buchstaben, sondern schon direkt eine zahl mit eingibt, so wird diese direkt in zeile gespeichert, dann wird das zweite printf_s ausgegeben, aber die eingabe bleibt leer und es passiert direkt alles was nach dem zweiten scanf_s kommt..(was vllt auch eine elegante lösung ist, aber ich hätte es lieber erstmal getrennt..). in dem fall bspw: "b2" ist wird dann auch ins feld b2 geschossen.
    wenn ich allerdings ausversehen "br" eingebe und das r in "zeile" als intwert gespeichert wird, dann sollte doch r außerhalb des bereiches von "zeile >= 0 && zeile <= 9" liegen oder? es wird aber statt der ausgabe die bei dem else "printf_s("\nDas Feld gibt es nicht. Ich lass dich die Kombuese schrubben! \nNOCHMAL!");" vorgesehen ist einfach das feld b/0 beschossen.. woran liegt das?
    ich weiß auch, dass die ganze schleife an sich schon sicher nicht besonders toll ist, aber wie machen informatik auch nur als nebenfach und hatten es auch nur dieses semster, da kennen wir bei weitem nicht den vollen funktionsumfang den c++ bietet und müssen uns meistens irgendwie mit den sachen behelfen die wir einigermaßen gelernt haben..

    was wir also eigentlich konkret wollten: die eingabe so gestalten, dass wirklich nur einzelne buchstaben(A/a-J/j) und einzelne zahlen(0-9) eingegeben werden können und ansonsten eine fehlermeldung kommt. habt ihr da tipps wie man das anstellen könnte?
    ich hätte jetzt vor, statt scanf_s cin>> zu benutzen und den string in einen integer-wert umzuwandeln. danach würde ich(welche integerwerte auch immer bei den buchstaben dann rauskommen) mit einem switch abhängig davon den werrt für die spalte zu setzen.. und bei default(was ja dann alles andere als die buchstaben sein sollte die ich erlaube) geht die schleife wieder von vorne los..

    unabhängig davon wäre es vllt klug, wenn man die eingabe der einzelnen koordinaten in eigenen schleifen schon ablaufen lässt oder?
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline Geändert von Momo (27.07.2018 um 15:27 Uhr)

  2. #2 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    UPDATE:
    ich bin mittlweile an diesem punkt angekommen:
    ich kann einen char einlesen und nur die erste stelle des chars wird in einer anderen variable von int gespeichert.
    Code:
    char westen[100];
    int spalte;
    cout << "\n\nWohin sollen wir schiessen?" << endl;
    cin>>westen;
    spalte = westen[0];
    cout<<westen<< endl;
    cout << spalte << endl;
    das heißt, wenn ich jetzt noch prüfe, ob in westen[1] eine 0 steht(weil nichts eingegeben wurde) kann ich doch eigentlich schon sagen, ob das eine valide eingabe war oder?
    ich hab die länge von 100 genommen für den fall dass man ausversehen 100 statt einem zeichen eingibt undso... ;D

    UPDATE 2:
    und jetzt hat es so geklappt wie ich das wollte!
    Code:
    		char westen[100];
    		int spalte, zeile;
    		cout << "\n\nWohin sollen wir schiessen?\nNach Westen:\t";
    		for (int i = 0; i < 1;){
    			cin >> westen;
    			if (westen[1] == 0 && westen[0] >= 'A' && westen[0] <= 'J'){
    				spalte = westen[0] - 'A';
    				i++;
    			}
    			if (westen[1] == 0 && westen[0] >= 'a' && westen[0] <= 'j'){
    				spalte = westen[0] - 'a';
    				i++;
    			}
    			else{
    				cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:";
    			}
    		}
    		cout << "Nach Sueden:\t";
    		for (int i = 0; i < 1;){
    			cin >> zeile;
    			if (zeile >= 0 && zeile <= 9){
    				i++;
    			}else{
    				cout << "Das ist ausserhalb der Reichweite!\nNeuer Wert:\t";
    			}
    		}
    Damit hat sich mein Problem im Prinzip erledigt..
    falls trotzdem noch anmerkungen anfallen, gerne posten!
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline Geändert von Momo (27.07.2018 um 15:26 Uhr)

  3. #3 Zitieren
    Ranger
    Registriert seit
    Sep 2017
    Beiträge
    142
    Ich würde statt einer for-Schleife eine while-Schleife verwenden, mit "true" in den Klammern, also while(true). Dann ersparst du dir das Flag eingabeRichtig. Die Schleifenausführung kannst du dann mit break; beenden.
    ThiccWookie ist offline

  4. #4 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Zitat Zitat von ThiccWookie Beitrag anzeigen
    Ich würde statt einer for-Schleife eine while-Schleife verwenden, mit "true" in den Klammern, also while(true). Dann ersparst du dir das Flag eingabeRichtig. Die Schleifenausführung kannst du dann mit break; beenden.
    okay danke für den tip, aber der quelltext aus dem ersten post ist jetzt eh überholt.. ;P
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline

  5. #5 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.328
    An deiner zweiten Version ist u. a. besser, dass die Funktionen scanf_s und printf_s entfallen, denn sie gehören nicht zu C++, sondern optional zu C (zum C11-Standard). Ein standardkonformer C11-Compiler darf sie weglassen, und kein offizieller C++-Standard kennt sie. Demnach sind sie unter C++ grundsätzlich nicht vorhanden, denn was über den Umfang von C++ hinaus mitgegeben wird, kann nicht vorausgesetzt werden. Deine erste Version erfüllt also nicht die Anforderung nach einem portablen C++-Programm. So bringt mein GNU-Compiler berechtigterweise kein scanf_s mit, weswegen er den Code nicht übersetzen kann.

    Wie lassen sich solche Verwechslungen vermeiden?
    Abhilfe:
    Verwende bitte nicht dieses (was ein schlechtes Vorbild aus Tutorials ist, um Platz, Tipp- oder Lesearbeit zu sparen oder Anfänger nicht zu verwirren; aber der Schuss geht nach hinten los (du hattest mehr Arbeit, nicht weniger und wurdest verwirrt!), und bessere Tutorials tun das eher nicht)):
    using namespace std;
    Denn deswegen^ hast du dir angewöhnt, den Namensraum std nicht mit anzugeben, weswegen dir nicht rechtzeitig aufgefallen ist (wofür du nichts kannst, das Tutorial schon), dass es weder std::scanf_s noch std::printf_s gibt.
    Alle Namen, die der Standardbibliothek von C++ angehören, befinden sich im Namensraum (namespace) std.
    Wenn ein Name (Schlüsselwörter ausgenommen) trotz Einbindung der richtigen Header-Datei (ohne .h am Ende, also z. B. cstdio und nicht das veraltete stdio.h) nicht in std enthalten ist, dann ist das ein starkes Indiz dafür, dass er nicht implementiert ist (Compiler erfüllt den Standard nicht ganz) oder gar nicht im Standard enthalten ist, also nicht zu C++ gehört.
    Wenn der Name im globalen Namensraum verfügbar ist, nicht aber std angehört, dann kannst du ziemlich sicher sein, dass er nicht zu C++ gehört.
    Also lässt du (wie es erfahrene C++-Programmierer in richtigen Projekten machen) diese using-Direktive weg und stellst den Namen von C++ (Schlüsselwörter ausgenommen) stets std:: für den Zugriff auf den Namensraum std voran, also:
    std::cin, std::cout, std::string, std::vector, std::istringstream, std::ostringstream . . .

    Falls dich das nicht überzeugt (du kannst noch nicht alle Gründe wissen, es gibt weitere), verwende dieses Schema:
    using std::scanf_s; // schlägt fehl (beabsichtigter Zweck)
    using std::printf_s; // schlägt fehl (beabsichtigter Zweck)
    using std::cin; // funktioniert
    using std::cout; // funktioniert
    using std::string; // funktioniert
    using std::vector; // funktioniert
    using std::istringstream; // funktioniert
    using std::ostringstream; // funktioniert
    // usw.

    Dabei importierst du genau diejenigen Namen, die du tatsächlich gebrauchst, keinen weniger, keinen mehr! Es ist aber nur die zweitbeste Lösung, denn an der Stelle der Verwendung des jeweiligen Namens würde nichts auffallen, weil du kein std:: voranstellst. Der erwünschte Hinweis ergäbe sich also nur bei der entsprechenden using-Direktive - falls du sie nicht vergisst! Um was wollen wir wetten, dass früher oder später...

    Innerhalb von Header-Dateien verbieten sich in der Regel Importe in den globalen Namensraum ganz. Denn der Benutzer, der die Datei einbindet, hätte die Namen automatisch mit am Hals. Er könnte sie im selben Gültigkeitsbereich nicht mehr verwenden, während innerhalb einer darin enthaltenen Klammerungsebene jedoch Verdeckung erlaubt ist, was ganz schön verwirren kann. Es könnte also leicht zu folgenreichen Verwechslungen kommen. Das Problem mit den hier diskutierten Verwechslungen von Namensräumen (z. B. dem globalen mit std) bestünde natürlich ebenfalls, aber auf subtilere Weise, indem der Benutzer nicht wissen kann, was importiert wurde und was nicht, was das Problem verschärfen würde. Eine einzige faule Header-Datei würde also genügen, um den globalen Namensraum zuzumüllen. Man nennt den Effekt auch Namespace Pollution.

    Die einfachste und beinahe idiotensichere Lösung, bei der man am wenigsten erklären muss, lautet daher: Stelle immer std:: voran, wenn du etwas von C++ verwenden willst (ausgenommen Schlüsselwörter). Aber ein Anfänger kommt dabei leicht auf den Gedanken, man wolle es ihm unnötig schwer machen. Das Gegenteil ist der Fall, wie du nun gesehen hast. Die Probleme kommen regelmäßig von denjenigen, die sich einbilden, sie könnten es noch leichter machen, was bei C++ aber nicht geht. Deswegen darf man dann ausführliche und zugleich nicht mit ihrer Länge überfordernde Abhandlungen wie diese schreiben, was ein anstrengender und kaum zu bewältigender Spagat ist. Hier oder dort ein Wort weniger, und die Aussage wird irreführend oder falsch.

    Hier kannst du nachlesen, wie (zumeist professionelle) C++-Programmierer über using namespace std; denken. Es handelt sich also nicht bloß um eine Einzelmeinung von mir.


    Dein zweiter Code hat noch einige Bugs.
    Ich fange mit einem an (die anderen hebe ich für später auf), finde ihn:
    Code:
    for (int i = 0; i < 1;){
        cin >> westen;
        if (westen[1] == 0 && westen[0] >= 'A' && westen[0] <= 'J') {
            spalte = westen[0] - 'A';
            i++;
        }
        if (westen[1] == 0 && westen[0] >= 'a' && westen[0] <= 'j') {
            spalte = westen[0] - 'a';
            i++;
        else{
            cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:";
        }
    }
    Was passiert, wenn du einfach einen Wert aus ['A', 'J'] eingibst? Warum passiert das?


    Zitat Zitat von Momo Beitrag anzeigen
    okay danke für den tip, aber der quelltext aus dem ersten post ist jetzt eh überholt.. ;P
    Das^ verstehe ich nicht. Denn strukturell ist es doch dasselbe geblieben. In beiden Fällen verwendest du diesen irritierenden Schleifenkopf, welcher suggeriert, es gäbe etwas hochzuzählen. Als Experiment mag das in Ordnung sein, aber nicht zum Ab- oder Weitergeben. Denn Code sollte die Absicht seines Autors ausdrücken. Vielleicht kommst du schon selber darauf, warum er das sollte.

    Also könntest du dem (sinnvollen) Vorschlag von ThiccWookie folgen...
    Code:
    while (true) {
        if (Hier_steht_ein_konditionaler_Ausdruck) {
            //...
            break;
        }    
    }
    ...wobei diese Variante gleichwertig ist:
    Code:
    for (;;) {
        if (Hier_steht_ein_konditionaler_Ausdruck) {
            //...
            break;
        }    
    }
    In beiden Fällen ist schon am Schleifenkopf ablesbar, dass recht wahrscheinlich mit break herausgesprungen wird, bevor man also das break überhaupt sieht (return oder void std::exit(int exit_code); ist hier nicht sinvoll, und goto meidet man).
    Das ist gut, weil man das Konzept versteht, sobald man mit dem Lesen anfängt!

    Wenn du unbedingt an deiner Variante festhalten willst, dann solltest du auch hier das Konzept verdeutlichen (da war dein erster Code sogar näher dran, aber nicht nah genug):
    Code:
    // wie leicht vertut man sich hier bei der Abbruchbedingung...
    //
    for (bool eingabeRichtig = false; !eingabeRichtig;) {
        if (Hier_steht_ein_konditionaler_Ausdruck) {
            //...
            eingabeRichtig = true;
        }    
    }
    Wenn du mich fragst, so finde ich das^ etwas unübersichtlich (aber immerhin kompakt!). Da fände ich dieses vielleicht besser (aber dennoch unbefriedigend):
    Code:
    bool eingabeRichtig = false;
    do {
        if (Hier_steht_ein_konditionaler_Ausdruck) {
            //...
            eingabeRichtig = true;
        }    
    } while (!eingabeRichtig);
    Das^ drückt durchaus klar aus, was gemeint ist: Es soll in jedem Fall in die Schleife eingetreten werden, und am Ende wird überprüft, ob eine Wiederholung nötig ist, was den beabsichtigten Programmfluss schon leichter erkennen lässt. Es stört dabei jedoch, dass die Variable für die Abbruchbedingung außerhalb des Gültigkeitsbereichs (scope) der Schleife definiert werden muss, was richtig nerven kann, wenn mehr Code drumherum steht. Ja, alles gleichzeitig bekommt man nicht so leicht unter einen Hut, außer beinahe mit break. Dafür fehlt dort die implizite Dokumentation über eingabeRichtig. Doch das lässt sich handhaben.

    Finde erst mal den Bug (s.  o.). Denn das wirft nebenher ein neues Licht auf die Verwendung von break. Danach können wir weitere Bugs behandeln.
    jabu ist offline Geändert von jabu (04.08.2018 um 19:58 Uhr) Grund: verflixte Details

  6. #6 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    f***, mein ipod hat das posten verlackt und jetzt ist der beitrag den ich die letzten 10 minuten geschrieben habe weg..
    nur so viel: das programm war in der zweiten version ebenfalls nicht final! es funktionierte nach neumaligem überarbeiten so wie wir uns das vorstellten.
    das programm wurde schon abgegeben! es lässt sich also nichts mehr daran ändern :P ich poste morgen mal die letzte version, auch wenn das wahrscheinlich herzschmerzen verursacht oder augenkrebs oder kp.. bin ja schon einige kommentare gewohnt über meinen amateurcode :P
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline

  7. #7 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.328
    Zitat Zitat von Momo Beitrag anzeigen
    f***, mein ipod hat das posten verlackt und jetzt ist der beitrag den ich die letzten 10 minuten geschrieben habe weg..
    nur so viel: das programm war in der zweiten version ebenfalls nicht final! es funktionierte nach neumaligem überarbeiten so wie wir uns das vorstellten.
    Das freut mich (vllt. guckst du dir trotzdem die Sache mit std:: an).

    Aus Fehlern, die lediglich deine Kommilitonen bearbeitet haben oder die nicht aufgefallen sind, hast du bisher nicht lernen können, weswegen ich das an deiner Stelle nachholen wollte, sowohl am alten Code (ab dem zweiten) wie auch am neuen. Das könntest du mal bei beiden Versionen ausprobieren:

    Gib mal
    ...bei jeder Abfrage rund 250 Zeichen ein (Copy & Paste erleichtert das),
    ...bei jeder Abfrage alle verfügbaren Steuerzeichen ein (sollte beim voreingestellten std::skipws eigentlich keine Probleme verursachen),
    ...bei der Abfrage einer Zahl einen Buchstaben ein,
    ...bei jeder Abfrage jeweils mehrere Buchstaben ein,
    ...bei jeder Abfrage End of File (unter Windows [Strg]+[z]) ein.

    Gut, der letzte Punkt ist ein wenig gemein, aber Benutzer können nun mal fast alles eingeben, was ein Programm aber nicht aus dem Tritt bringen darf!
    Außerdem kann es eine Umleitung des Eingabedatenstroms geben, der ebenfalls nicht in unkontrolliertem Programmfluss resultieren sollte. Das lässt sich testen, indem man aus einer Datei anstatt aus der Konsole einlesen lässt. Dazu kannst du eine Ebene oberhalb des Release-Verzeichnisses eine Datei mit ein paar Zeichen drin anlegen. Der genaue Inhalt ist erst mal nicht so wichtig, weil du ihn beim Testen immer noch abändern kannst. Dann legst du (unter Windows) eine Batch-Datei daneben, z. B. test.bat. In die schreibst du hinein:
    Release\hier_der_Name_deines Programms < hier_der_name_deiner_datei
    pause


    Das < leitet die Textdatei in den Eingabedatenstrom der Standardeingabe um. Mit pause wird verhindert, dass sich die Konsole schließt, nachdem das Programm abgelaufen ist.

    Die Batchdatei lässt du ausführen, womit dein Programm in der Konsole starten sollte, mit der benannten Datei als Eingabe. Falls stattdessen der Editor aufgeht, steht am Ende nicht bat, sondern txt. Also solltest du den Explorer so einstellen, dass die Dateinamen nicht beim letzten Punkt abgeschnitten werden. Denn dieser (wegen .exe, .cmd, .bat etc. auch noch gefährliche) Unsinn ist bei Windows leider die Standardeinstellung. Da bekommt die Omi ein Liesmich.exe zugemailt und sieht nur Liesmich und das vertraute Symbol des PDF-Readers, weil das als Ressource eingebettet ist. "Oh, ja, das muss ich lesen", klick! Dann geht das Popup der UAC auf, welches die Omi auch bei anderen Programmen sowie bei vielen Updates wegklickt, also klick! => powned
    Ja, wer so einen Mist verkauft, bei dem man standardmäßig Administratorberechtigungen hat, gehört eigentlich geteert und gefedert, sollte man meinen, habe ich mal gehört. Dass man dazu erzogen wird, dass es einem egal sein sollte, welchen Code man ausführen lässt, setzt dem noch die Krone auf.

    das programm wurde schon abgegeben! es lässt sich also nichts mehr daran ändern :P ich poste morgen mal die letzte version, auch wenn das wahrscheinlich herzschmerzen verursacht oder augenkrebs oder kp.. bin ja schon einige kommentare gewohnt über meinen amateurcode :P
    Mach mal ruhig. Nein, bisher kann ich bei mir weder Lachen noch Schmerzen beobachten, sondern ein Lächeln, weil ich mich an meine eigenen Anfänge erinnere. Was war ich froh, als der Code überhaupt erst mal durch den Compiler ging! Was konnten die Fehlermeldungen nerven! Und was war das für ein kryptischer Scheiß (zugegeben, manchmal sind sie auch heute noch kryptisch)... Heutzutage sitze ich hier und erzähle wildfremden Leuten, wie hochwillkommen doch Fehlermeldungen sind, damit sie sich auch an diesem tollen Tool, das ein Compiler ist, erfreuen mögen. Also, wenn ich lache, dann eigentlich über meine eigene Dusseligkeit.
    jabu ist offline Geändert von jabu (06.08.2018 um 01:33 Uhr)

  8. #8 Zitieren
    Ehrengarde Avatar von Momo
    Registriert seit
    Feb 2011
    Beiträge
    2.142
    Ja, ich schau mir das mal an, aber hab erstmal leider noch andere sachen zu tun.. schreibe mir mit c++ jetzt ein einfaches rechenprogramm, was numerisch die maximalen verformungen von einer baugruppe ermitteln soll... da ist aber nicht mal eine eingabe dabei, die werte verändert man im quellcode und es kommt dann eine ausgabe die die jeweiligen maximalwerte ausgibt. dafür nützt mir c++ zum ersten mal auch in einem anderen fach was, auch wenn das nicht mehr ist als eine einzelne große rechnung ;D

    also hier das was dann funktioniert hat... wir wollten mit dem code ja auch lediglich tippfehler abfangen, haben den char in dem die eingabe gespeichert wird deswegen auch auf 10 zeichen begrenzt. es steht ja auch in der spielanleitung wie man was eingeben soll, aber wenn man ausversehen zwei buchstaben trifft und dann enter drückt sind vorher immer schlimme sachen passiert in der .exe...
    Code:
    cout << "\n\nWohin sollen wir schiessen?\nNach Westen:\t";
    		while(true){
    			cin >> westen;
    			if (westen[1] == 0 && westen[0] >= 'A' && westen[0] <= 'J' || westen[1] == 0 && westen[0] >= 'a' && westen[0] <= 'j'){
    				if (westen[0] >= 'A' && westen[0] <= 'J'){
    					spalte = westen[0] - 'A' + 3;
    					break;
    				}
    
    				if (westen[0] >= 'a' && westen[0] <= 'j'){
    					spalte = westen[0] - 'a' + 3;
    					break;
    				}
    
    			}
    			else{
    				cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:";
    			}
    		}
    		cout << "Nach Sueden:\t";
    		while(true){
    			cin >> sueden;
    			if (sueden[1] == 0 && sueden[0] >= '0' && sueden[0] <= '9'){
    				zeile = sueden[0] - '0' + 3;
    				break;
    			}
    			else{
    				cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:";
    			}
    		}
    also das wäre jetzt der code mit while schleife und break statt der for-schleife.. ich kann es allerdings leider nicht überprüfen ob es funktioniert, weil ich das in codeblocks nicht kompilieren kann.. wir haben das nur auf den uni-rechnern mit visual studio geschrieben und codeblocks fehlen irgendwelche dateien die es in den code implementieren müsste.. aber du kannst ja mal sagen ob das so ist wie du es vorgeschlagen hast ^^
    bei dieser doppelten if-abfrage ist glaube auch noch nicht alles ganz rein, aber es ist manchmal passiert, dass die eingabe dann nicht erneut abgefragt wurde oder man trotzdem zu süden gekommen ist.. wäre das so:
    Code:
    cout << "\n\nWohin sollen wir schiessen?\nNach Westen:\t";
    		while(true){
    			cin >> westen;
                            if (westen[1]==0){
    			   if (westen[0] >= 'A' && westen[0] <= 'J'){
    			   	   spalte = westen[0] - 'A' + 3;
    				   break;
    			   }else cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:"; 
    
    			   if (westen[0] >= 'a' && westen[0] <= 'j'){
    				   spalte = westen[0] - 'a' + 3;
    				   break;
    			   }else cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:"; 
                            }
    			else cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:";              
    		}
    
    cout << "Nach Sueden:\t";
    		while(true){
    			cin >> sueden;
    			if (sueden[1] == 0 && sueden[0] >= '0' && sueden[0] <= '9'){
    				zeile = sueden[0] - '0' + 3;
    				break;
    			}
    			else cout << "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:";
    		}
    machbar?
    so wie ich mir das vorstelle sollte es doch genauso funktionieren oder? ich kann es wie gesagt leider nicht nachprüfen und wir hatten schon öfter sachen, die funktionieren SOLLTEN, das aber leider dann doch nicht taten..

    EDIT:
    ...bei jeder Abfrage End of File (unter Windows [Strg]+[z]) ein.
    ja, damit kommt er nicht klar.. sofort in einer endlosschleife gefangen die immer wieder "Das liegt ausserhalb der Schussweite!\nNeue Koordinate:" ausgibt..
    "The most unusual day would occur when nothing unusual happened."
    Momo ist offline Geändert von Momo (07.08.2018 um 13:57 Uhr)

  9. #9 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.328
    Zitat Zitat von Momo Beitrag anzeigen
    Ja, ich schau mir das mal an, aber hab erstmal leider noch andere sachen zu tun..
    [...]
    ich kann es allerdings leider nicht überprüfen ob es funktioniert, weil ich das in codeblocks nicht kompilieren kann.. wir haben das nur auf den uni-rechnern mit visual studio geschrieben und codeblocks fehlen irgendwelche dateien die es in den code implementieren müsste..
    [...]
    ich kann es wie gesagt leider nicht nachprüfen und wir hatten schon öfter sachen, die funktionieren SOLLTEN, das aber leider dann doch nicht taten..
    [...]
    Finde den Widerspruch in deinen Aussagen!
    Gut, wenn es dir egal ist, wieviel Zeit du noch verlierst und wie du vorankommst, will ich nichts gesagt haben.

    Auflösung:
    Spoiler:(zum lesen bitte Text markieren)
    Verwende die Standardbibliothek* von C++ und nicht irgendwas anderes, und die Sache sollte laufen, siehe meinen langweiligen vorletzten Beitrag, den du wirklich mal lesen solltest (es geht um die erste Hälfte), denn so kompakt und vergleichsweise unaufwendig bekommst du das nur selten woanders beigebogen. Dafür fehlen Details, die du dir woanders besorgen müsstest (mit Internet kein Problem).
    Der Fehler liegt nicht bei Code::Blocks und auch nicht bei deinem GCC-Derivat, sondern ganz einfach bei dir, indem du meinst, mit dem Überspringen wichtiger Grundlagen Zeit sparen zu können. Doch ohne die verlierst du durch solche Probleme ein Vielfaches an Zeit.
    Es muss dabei nicht unbedingt um scanf_s oder printf_s gehen. Der Spaß kann sich locker auch mit anderen herstellerspezifischen Bibliothekserweiterungen wiederholen. Ich sage bewusst "herstellerspezifisch", denn in den C++-Standards sind diese beiden nicht mal definiert (anders als bei C11, wo sie optional sind). Es ist daher kein Fehler, wenn sie nach Übersetzung auf einem anderen System die Festplatte formatieren oder nach Amerika telefonieren oder wenn es erst gar nicht zur Übersetzung kommt, weil unter den Namen keine Funktionen gefunden wurden.

    *Ausgenommen optionale, aber solche sind extra in inneren Namespaces geschachtelt, wobei der jeweilige Namespace einen auffälligen Namen hat.

    Falls du eine Sprachreferenz brauchst, siehe:
    https://en.cppreference.com/w/
    http://www.cplusplus.com/reference/
    Hilfreiche Links:
    https://en.cppreference.com/w/cpp/links
    Darunter sind auch Links zu den letzten frei verfügbaren Entwürfen der jeweiligen Standards gegeben. Nur die Standards selbst sind verbindlich. Leider sind die nur zu Preisen erhältlich, über die sich Normalsterbliche wundern, weswegen sie gerne die kostenlosen Entwürfe verwenden. Bei der Überarbeitung des letzten Entwurfs für den offiziellen Standard geht es im Wesentlichen um Formulierungsdetails, wodurch die Unterschiede eher gering ausfallen.

    C++ ist eine gewachsene Sprache, die stark C beerbt (wobei C keine reine Untermenge von C++ mehr ist*). Und so sind auch die Werkzeuge und Bibliotheken mitgewachsen, beginnend bei C. Es gibt also diese zwei Ebenen, die man auseinanderhalten muss, einmal die des Compilers und einmal die der Sprachimplementierung in Form der Bibliotheken. Zunächst ist wichtig - und das hatten wir im Nachbarthread, dass der Compiler sich in einem standardkonformen Modus befindet, denn sonst würde er sich schon selbst falsch verhalten. Das hält ihn aber nicht davon ab, alles zu kompilieren, was nach dem jeweils gewählten Standard syntaktisch korrekt ist. Syntaktisch korrekt sind auch veraltete Bestandteile sowie Erweiterungen, wie sie jeweils in den Bibliotheken mitgegeben werden, teils zur Wartung von veraltetem Code, zur Wahrung oder Herstellung von Kompatibilität mit C, zur Bereitstellung sichererer Alternativen zu Funktionen von C oder aus sonstigen Gründen. Solcher Kram müllt also den globalen Namensraum zu. Und ohne vorangestelltes std:: verwendet man ihn ganz leicht versehentlich.

    *So ganz ist sie das nie gewesen (abgesehen vielleicht von dem frühen "C with Classes", wenn man das hinzurechnet), wenn man die Untermenge strikt versteht. Schon das strengere Typsystem und das Verbot von Mehrfachdefinitionen verletzen die Eigenschaft als Untermenge. Aber die C-Library von C90 war noch eine Untermenge von C++98 (zumindest sollte sie das). Das ist meistens damit gemeint (falls es derjenige weiß), wenn gesagt wird, C sei eine Untermenge von C++.
    jabu ist offline Geändert von jabu (09.08.2018 um 19:21 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •