Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

26.07.2012, 13:40

Fragen eines Anfängers (Debugging, Löschen von Werten) aus der Übungsaufgabe 5.11

Einen schönen guten Tag,

ich habe ein paar Fragen, die mir aufgekommen sind, als ich die Aufgabenstellung in Kapitel 5 lösen wollte.

Bei mir hat sich ein heimtückischer Käfer eingeschlichen, welchen in glücklicherweise inzwischen erkannt habe (Abgleich mit der Musterlösung). Allerdings sind mir daraus weitere Fragen aufgekommen, welche ich noch nicht befriedigend beantworten konnte. Von daher dieses Posting.

In der Aufgabe geht es darum ein Spielfeld (Array, erstellt aus einer Struktur) zu erzeugen, auszugeben und einzelne Felder zu bearbeiten.

Da ich bereits gute Vorkenntnisse aus LUA habe ist mir die Lösung nicht außerordentlich schwer gefallen (Tabels ähneln Arrays sehr).

Ich zeige euch einfach einige Teile aus meinen Quelltext, benenne den Fehler und komme dann zu meinen Fragen. Dies ist wahrscheinlich unüblich, aber lässt es mir keine Ruhe, denn ich möchte gerne wissen, wie diese Fehler entsprechend zukünftig besser vermeiden und erkennen kann.


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//Ich überspringe einfach mal den Header und die Präprozessor-Befehle, diese haben nichts mit meinem Problem zu tun.

// Struktur erstellen
struct S_Feld
{
    char cName[10];
    bool bBelegt;
};

// Konstanten erstellen
const int Breite = 10;
const int Hoehe = 5;

// Array erstellen
S_Feld A_Feld[Breite][Hoehe];

// Es folgt ein Menü, welches die einzelnen Funktionen ansteuert.
//Besetzen() besetzt ein Feld des Arrays mit Werten

void Besetzen()
{
    int x = 0;
    int y = 0;

    do
    {
        cout << "X? ";
        cin >> x;

        cout << endl << "Y? ";
        cin >> y;

        cout << endl;

    } while (x < 1 || x > Breite || y < 1 || y > Hoehe);

    cout << "Womit? ";
    cin.ignore();
    cin.get(A_Feld[x - 1][y - 1].cName, 9);

    A_Feld[x - 1][y - 1].bBelegt = true;

    cout << endl;
};

//Array auf default rücksetzen

void kill()
{
    for (int y = 0; y < Hoehe; y++)
    {
        for (int x = 0; x < Breite; x++)
        {
            A_Feld[x][y].bBelegt = false;
A_Feld[x][y].bBelegt = "";
        };
    };

    cout << "Geloescht!" << endl;
};


Den Fehler findet Ihr in Zeile 55 (blödes Copy&Paste). Sollte eigentlich ein cName werden.

Nun zu meinen Fragen:

Ich hätte es ja verstanden, wenn meine Funktion kill() Probleme erzeugen würde, allerdings hat sie dies nicht. Dafür hat meine Funktion Besetzen() vollkommen durchgedreht.

Wenn ich über das Menü die Funktion Besetzen() angesteuert habe und ungültige Werte in die while-Schleife eingegeben habe, hat sich diese ordnungsgemäß wiederholt.
Das Kuriosum: Sobald ich gültige Werte eingegeben habe hat sich diese Schleife einfach in eine Unendlich-schleife verwandelt und mir in der Konsole (cin vollständig außer Acht gelassen) "X? " endl "Y? " endl "X? "... ausgegeben. Zu Beenden nur durch ein beherztes Schließen der Konsole.

Ich habe die Funktion durchsucht und durchsucht, aber habe einfach keinen Fehler gefunden, vor allem, da eine kopierte Schleife (Auslesen des Arrays) fehlerfrei funktionierte.

Dann, weil in der kill() auch etwas nicht stimmig war habe ich mir diese angeschaut und den Fehler erkannt, behoben und schubs war auch meine Besetzen() wie durch Zauberhand repariert.


Nun meine Fragen (wird nach so viel Text auch Zeit):
  1. Wie entstehen Fehler in einer Funktion, die fehlerfrei ist, wenn diese nicht im entferntesten mit einer fehlerhaften Funktion interagiert? In LUA kannte ich dies so, dass entweder die gesamte Datei nicht interpretiert wurde, oder die fehlerhafte Funktion nicht arbeitete, dafür alle anderen schon.
  2. Wie ist das eigentlich mit den Debugging allgemein? In LUA hatte ich bei Syntaxfehlern meist den oben beschrieben Ablauf während der Laufzeit mit einer mehr oder minder aussagekräftigen Fehlermeldung. Diese finde ich unter C++ ja während des Compilierens allerdings erhielt ich keine Fehlermeldung bei meinem fehlerhaften Code. Mir ist bewusst, dass ein automatisches Tool niemals alle Fehler erkennen kann, doch scheint hier etwas schwerwiegendes schief gelaufen zu sein. Gibt es da eine Trickkiste im Compiler, die mir noch nicht aufgefallen ist?
  3. Eigentlich wollte ich den Wert von cName löschen. Habe aber bis jetzt nicht herausgefunden wie. In LUA wäre die Zuweisung "cName = nil". Wie sieht das in C++ aus, kann man dort Werte löschen (nil oder null bzw void helfen nicht weiter)? Im Anschluss daran habe ich versucht die Variable mit einem Leerstring zu belegen, doch "" hat nicht funktioniert, '' warf im Compiler einen Fehler. Ist dieses Vorgehen, das Löschen von Werten, egal ob global oder lokal, in C++ üblich? In LUA war dies immer ein willkommenes Mittel um z.B. mit einer Boolean 3 Möglichkeiten abzudecken (true, false oder nil) Die fehlerhafte Zeile habe ich letzten Endes entfernt.
  4. In LUA sind "" und '' gleichbedeutend und zugleich ein nützliches Helferchen. print("Hallo Welt!") ist gleichbedeutend mit print('Hallo Welt!'). Kann allerdings für das Konstrukt: loadstring("print('Hallo Welt!')") [loadstring führt einen string als function aus] genutzt werden. Was sind die Unterschiede zwischen '' und "" in C++?
Auf jeden Fall danke für das Lesen dieses langen Postings und ich hoffe ich habe euch nicht überrannt bzw. meine Fragen nicht uneindeutig formuliert. Leider war der ganze Text nötig um einerseits meine Problemstellung und die Beobachtung zu schildern.
Ich hoffe Ihr könnt mir helfen und mein Verständnis für C++ durch eure Antworten zu verbessern.

Herzlichen Dank

Tinsus

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

2

26.07.2012, 14:51

Ich verstehe die Bedingung deiner do-while-Schleife nicht ganz.

Du willst das mindestens 1x wiederholen, solange x < 1 ODER x > Breite ODER y < 1 ODER y > Hoehe?

Für mich sieht das eher nach den Bedingungen aus, bei denen abgebrochen, nicht wiederholt, werden soll.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

3

26.07.2012, 15:20

die do while Schleife soll prüfen, ob meine Variablen Zwischen 2 Werten liegen, also:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const int Breite = 10;
const int Hoehe = 5;

    do
    {
        cout << "X? ";
        cin >> x;

        cout << endl << "Y? ";
        cin >> y;

        cout << endl;

    } while (x < 1 || x > Breite || y < 1 || y > Hoehe);


Wiederholen wenn, x < 1 ODER x > 10 ODER y < 1 ODER y > 5, wobei die Variablen beide zu Anfang 0 sind, also die Schleife mindestens 1x durchlaufen wird.
Werden nun Werte (oder nur einer) außerhalb eingegeben, so wiederholt sich die Schleife bis beide Werte OK sind. Ich gebe gerne zu, dass dies nicht die schönste Variante ist, da eigentlich für beide Variablen eine eigene Schleife besser wäre.

Du hast natürlich Recht, das der eigentliche Sinn der Schleife ein Abbruch ist.

Die Schleife soll sicherstellen, dass nur gültige Werte eingegeben werden. Sobald ein Wert ungültig ist, wird so oft wiederholt bis die Werte gültig sind. (Das Array ist ja in seiner Größe limitiert). Wird also beispielsweise x=2 und y=3 angegeben, wird abgebrochen, bei x=2 und y=324 wird wiederholt bis beide Werte passen.

Ich denke nicht, dass hier ein Fehler steckt, da diese Zeile ohne Änderung jetzt funktioniert.

Musterlösung der Schleife ist

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
    int x = 0;
    int y = 0;

    // Koordinaten abfragen
    do
    {
        cout << "x-Position (1-" << Breite << "): ";
        cin >> x;
    } while (x<1 || x>Breite);


Wie gesagt, ich habe die Überprüfung von 2 Variablen in einer Schleife vereint.


Ich hoffe die Ausführungen verbessern das Verständnis zu dem Sinn der Schleife.


Das Kuriose ist ja, dass die Schleife durchlaufen wurde, ohne, dass auf cin gewartet wurde. Hätte man jedes Mal etwas Neues eingeben müssen, wäre dies ja verständlich gewesen, aber ohne jede weitere Eingabe wurde bei gültigen Werte immer der cout-Teil durchlaufen und als Unendlichschleife bearbeitet. Abzubrechen, wie gesagt nur durch Schließen oder STRG+C.

Grüße

Tinsus

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

4

26.07.2012, 15:43

Ah, entschuldige, hatte beim Lesen einen kleinen Denkfehler.

Interessanterweise kann ich deinen Fehler bei mir nicht reproduzieren, tut mir Leid, sonst setze mal ein cin.ignore an den Anfang der do-while-Schleife, vllt. hilft das.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

5

26.07.2012, 15:54

Hmmm... Dumm, dass ich den Fehlerquellcode in keiner Repository gesichert habe. Leider habe ich den Code schon entsprechend der Musterlösung angepasst und nun ebenfalls kein Problem damit, auch nicht, wenn ich den Fehler wieder einbaue.

naja, offen bleiben dann ja noch Fragen 3 und 4 ;)

Ich bin inzwischen etwas weiter im Buch und lese nun von NULL, ist NULL ein Äquivalent zu nil in LUA? (Ich vermisse die blaue Hervorhebung) oder ist NULL bloß eine Ersetzung mit 0 als Präprozessorenbefehl (und damit nach meinem Verständnis nicht nil, da 0 auch als false interpretiert werden könnte)? Und die Frage, ob und was der Unterschied zwischen " und ' in C++ ist.

S4My

unregistriert

6

26.07.2012, 17:22

Hi, ich hoffe mal folgendes wird ein wenig helfen :D .

So, Frage 3:

Löschen von Werten wäre das eigentlich nicht, du setzt sie nur "zurück", wobei das eigentlich nicht mehr ist als gewöhnliches setzten nur eben mit Default-Werten. Da du das sicherlich weißt, weiter im Text. Versuch einmal den Wert auf ' ' zu setzen, das wäre nämlich leer, '' allein ist soweit ich weiß rein gar nichts und wird deshalb denke ich nicht unterstützt, sicher bin ich mir nicht ;) .

Dann zu dem Unterschied beider Möglichkeiten der Textkennezeichnung:

In C++ ist es meines Wissens nach so, das Apostrophe einen Character, also einzelnen char kennzeichnen und Anführungszeichen einen String, also eine Zeichenkette. Ich kenne mich mit LUA an sich nicht aus, aber es scheint wie etwa bei JavaScript zu sein, in C++ ist das glaube ich leider nicht so. Was aber auch sein kann das beide akzeptiert werden würden (was ich weniger glaube), solange sie mindestens ein "Space" haben :) .

Am Schluss noch zu "NULL": Das ist ein konstanter Wert welcher mittels der Präprozessordirektive "#define" erstellt wurde. Was genau "nil" ist weiß ich nicht, aber NULL ist genau was es verspricht, die Zahl. Ach und ja, diese würde als "false" erkannt werden wenn sie in eine entsprechende Variable gespeichert werden würde, jedoch hab ich das bisher selten gesehen, eher verwendet man da griffigere Bezeichnungen, in deinem Fall wahrscheinlich so etwas:

C-/C++-Quelltext

1
2
#define BESETZT true
#define FREI false

Du kannst natürlich auch einfach englische Begriffe verwenden, sofern dir das als besser erscheint, ich hab einfach mal richtig schön auf Herr Deutschmann gemacht :D .

Einfach mal testen ob das stimmt was ich sage, muss ja nicht ^^ . Ich selbst habe bisher allerdings keine Probleme mit sowas gehabt, also von das her kann es nicht einmal so verkehr sein ;) .

Mlg
S4My

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »S4My« (26.07.2012, 17:27)


7

28.07.2012, 08:28

Danke an alle - ich werde mich noch weiter damit befassen, aber einige graue Stellen wurden beseitigt.

Beste Grüße

Tinsus

Werbeanzeige