Symantische Fehler?

  • Hallo


    folgendes Problem:
    Der folgende Quellcode beeinhaltet eine "Passwortabfrage" für ein Programm.
    Das Passwort wird im Klartext in der Datei conn.txt niedergeschrieben. (Ja, ich weis, nicht sehr sinnvoll. Soll ja aber nur eine Übung sein)
    So:
    Wenn in der Datei conn.txt irgendetwas steht, und das auch beim Start des Programmes eingegeben wird, startet das funktioniert das Programm vollkommen korrekt.
    Wenn allerdings innerhalb der Datei überhaupt nichts steht, fragt das Programm trotzdem nach einem (nat. nicht vorhandenen) Passwort.
    AN der Datei kann es auch nicht liegen, die hab ich zu testzwecken schon des öfteren neu angelegt.Im richtigen Verzeichnis liegt die Datei auf jeden Fall, da es ja Funktioniert, wenn ein Passwort vergeben wurde.


    Das ganze wurde auf einem MS Visual C++ Compiler kompiliert.


    Hier der Code:







    Des weiteren gefallen mir die "goto's" noch nicht so ganz...gibt es da vielleicht eine andere Möglichekeit?


    Danke

  • Hallo,
    also mal abgesehen von den den globalen variabeln,diesen GOTOs und eine Anzeige wenn es
    bis du sicher dass das mit Getline überhaupt so stimmt?
    Ein Blick in die MSN sagt mir irgentwie was anderes:
    "If the function extracts no elements, it calls setstate(failbit). In any case, it returns _Istr.",
    also wird anscheinende immer was zurückgeliefert...
    Setze doch da mal einfach einen Haltepunkt auf die Funktion,und schau dir genau an was da zurückgeliefert wird,ich vermute mal da steht dann conn.txt oder sonst was drin.


    Peter

  • Hallo,
    tja MSN sagt dazu folgendes:


    in der Basisklasse (basic_ios)
    gibt es da die funktionen bad() und fail()
    also probier mal ob
    if(pwd.bad())
    cout<<"FEHLER!"<<endl;
    da ein ergebnis liefert wenn die Datei leer ist.
    oder pwd.fail,da ist der rückgabewert aber anders)


    Peter

  • Ich meld mich hier nun doch noch mal zu Wort.
    Das Problem lag darin, da selbst im Falle des zutreffenden "else"(if(access.length==0) ) als nächstes die Sprungmarke "pw_i:" ausgeführt wird. Das ganze ließ sich durch eine weitere if-Bedingung überbrücken.


    So ein Debugger kann doch eine ganz tolle Sache sein.... :D

  • tja GOTO ARRGGGGHHH
    (Obwohl EIGENTLICH arbeitet das schon sehr zuverlässig....)
    probier es mal mit einem Semikolon in der Zeile vor dem Goto...


    Peter

  • Was habt ihr alle gegen 'goto'...
    Der Code sieht in der funktionierenden Version jetzt so aus:



  • Hallo tja in ganz ganz großen Ausnahmefällen vielleicht mal,
    (Nein,dein Programm gehört nicht dazu,das würde auch sehr sehr gut ohne GOTO gehen... ;) )


    Was ich dagegen habe?
    -Wenn du einmal damit anfängst hört man nicht mehr damit auf,dasselbe gilt im übrigen auch für globale Variabeln und ähnliche "seltsame" Sachen..
    -Es führt sehr leicht zu irgendwelchen Fehlern wo der Debugger dann auch nicht weiterhilft,z.B. wenn noch irgendetwas in der Schleife zu "tun" ist,das wegen dem Goto nicht ausgeführt wird,da dieses GOTP vollkommen unabhängig vom Progrmmfluss arbeitet.
    -Variabeln usw. werden evtl. nicht gelöscht
    -schlecht Stil
    -in 99.5% der Fälle absolut unnötig
    -Es wird entweder wegen Unkenntnis oder Faulheit benutzt.
    -ooccchhh da würden mir auch noch einige Gründe mehr einfallen ;)


    Peter

  • Zitat


    -Es wird entweder wegen Unkenntnis oder Faulheit benutzt.


    Letzteres. Ohne das 'goto' müsste ich aber theoretisch die komplette Passwortabfrage mit in die if-Abfrage packen. Außerdem müsste der Quellcode des Restprogramms auch 2 mal (1x für if, 1x für else) eingefügt werden, was das Programm sinnlos anschwillen lässt.

  • Hallo,
    also irgendwie... ?

    Code
    if(access.length != 0) 
    { 
          goto pw_i; 
    } 
    else{;}
    if(access.length != 0)
    {    
    pw_i: 
    { ;} //mal abgesehen davon,warum diese 2 Klammern?
    }


    :wink: *etwas verwirrt ich bin* :wink:
    Warum schreibst du den Teil der in diesen klammern steht nicht einfach dahin wo jetzt dieses GOTO steht?

  • Hmm, die Frage stell ich mir auch grad :D
    das wird noch überarbeitet.
    Das 2. 'goto' (goto pgrm;) brauch ich aber, sonst muss ich den Code 2 mal einfügen.
    Und die 2 Klammern beim pw_i: aus folgendem Grund. Da folgtr doch ein Block, wenn ich die Klammern nicht hätte, dürfte das ja nur eine Anweisung stehen.
    Direkt wo das goto steht werd ichs wohl hinschreiben...ich bin grad von meinem eigenen Code aufs schlimmste verwirrt....aaaarg

  • Ok,einigen wir uns darauf das du das mal etwas verbesserst :)
    Und das Ergebnis nochmals hierhin schreibst :)


    Ach ja hier mal ein Beispiel wo ich evtl.,möglicherweise,unter gewissen Umständen,ausbahmsweise, mal ein GOTO einsetzen würde,und selbst da sehr wahrscheinlich nicht ;)


    irgend sowas wo ich aus irgendwelchen Gründen eine komplexe Schleife verlassen will,oder so.


    Bevor du fragst,nein das hinter ABC wird immer ausgeführt,unabhängig davon ob ich mit GOTO dahingesprungen bin oder die Schleife normal beendet habe. Es verhält sich bei GOTO ähnnlich wie bei switch/case
    es wird ALLES hinter dem Case Label ausgeführt,wenn du kein break einbaust auch alle nachfolgenden Case Anweisungen.
    Das nur als Hnweis zu diesen Klammern hinter dem Goto,die könntest du auch weglassen...


    Peter

  • Hier der gesamte Code meiner geistigen Schandtaten :D :


    Quelle1.cpp


    head.h



    Vll. hättest du ja noch Vorschläge zu den , in den Kommentaren beschriebenen Problemen.
    [/code]


  • Na,vermisst du da nicht irgendwas ;)


    Das mit dem Rest schau ich mir morgen mal an.
    Peter


    Achso,wenn du das testen willst,entferne bitte ganz am Ende die } der switch Anweisung.


  • Dieses
    case 1:{....}
    case 2:{....}
    du kannst die Klammern setzen ja,musst du aber nicht,ausser vielleicht der Übersichtlichkeit wegen, die haben keine Funktion.


    Zu dieser while Schleife:
    while{true}
    dieses true ist etwas eleganter als nur eine 1,die ganze Konstruktion,sieht zwar nicht so schön aus,aber das wird nunmal so gemacht,oder mit einer Konstruktion
    for( ; ; ) //Endlosschleife
    {
    ....
    }
    was aber das selbe ist.


    gut das mit if(isalpha()==true) ist eigentlich falsch,da isalpha teoretisch einen Wert größer als 0 wiedergibt aber nicht unbedingt 1 ,welches dem true entspricht,also müsstest du schreiben !=false d.h. ungleich 0.
    Nun gut eigentlich könnte man dieses ganze ==true weglassen,also if(isalpha()) ,da if nur prüft ob das Ergebnis Nicht 0 ist,aber lass das Bitte so stehen solange du noch nicht ganz so "fit" in C++ bist,da es evtl verwirrt.


    So nun ist aber wirklich Schluss für heute ;)
    Peter

  • Hallo,
    CASE 2:
    Mir ist unklar was das wie gesucht werden soll, und was ausgegeben werden soll


    CASE 3:
    Ebenfalls etwas unklar,die reine Ausgabe müsste so wie du es geschrieben hast eigentlich funktionieren...


    Zur Klassendefinition:
    1.clear() ist in der Namensgebung etwas ungeschickt,da es diese Bezeichnung mindestens schon 100 Mal gibt,wenn diese Funktion innerhalb einer Klasse wäre,dann ja,aber so als globale Funktion?
    Es geht sicherlich,du kannst auch selber eine printf() Funktion definieren,aber nun ja....


    2.Dieses class leser und class newentry du KANNST das so machen,ABER:
    Wenn da wirklich sonst nichts steht,es gibt 3 C++ Struktur Elemente:
    class->Enthält Daten UND Funktionen die auf diese Daten zugreifen
    struct->Enthält nur Daten
    union->Vergisst du am besten schnell wieder,steht zwar in einigen Lehrbüchern und wird in einigen Standardbibliotheken genutzt,ich glaube aber nicht das du das jemals selber verwenden wirst....


    Das mit class und struct,das sind keine Festlegungen vom compiler her da beide Daten UND Funktionen enhalten können,es ist aber allgemein üblich das wie oben angegeben aufzuteilen, also Elemente nur mit Daten lieber in ein Struct. (Höchstens vielleicht mal einen Destructor,Constructor in einem Struct)
    Elemente mit Daten UND Funktionen in eine Klasse.


    Peter

  • Zitat

    CASE 2:
    Mir ist unklar was das wie gesucht werden soll, und was ausgegeben werden soll


    Im Optimalfall soll der komplette Inhalt d. Datei in einen string eingelesen werden und nach einer Zeichenfolge durchsucht werden. Wenn diese gefundne wird, soll die entsprechende Zeile, in der das Wort gefunden wird, ausgegeben werden.


    Zitat

    CASE 3:
    Ebenfalls etwas unklar,die reine Ausgabe müsste so wie du es geschrieben hast eigentlich funktionieren...


    Die reine Ausgabe funktioniert auch...problematischerweise ist das ganze sehr statisch, da die Arraygröße von 256 vorher festgelegt wird. Wenn jetzt allerdings mehr als 256 Zeichen in der Datei stehen, werden diese einfach ignoriert (zumindest geh ich davon aus, noch nicht getestet). Ich könnte die Arraygröße zwar vorher schon auf 5000 elemente festlegen, das wäre aber verschwendung...


    Zitat

    //goto case 1; //Wie springt man zurück zu einer Sprungmarke? goto case 1; geht ja nicht...


    Ich weiß ja das du gegen goto bist, aber... :D

  • Hallo,
    zu 3.
    doch das funktioniert genauso wie du es geschrieben hast,
    fgets bricht entweder bei "\n" ab oder nach 255 Zeichen,der Dateizeiger steht anschließend auf der nächsten Zeile,das unter Case3 müsste also gehen.
    Du soltest das ganze aber eventuell so erweitern wie im ersten Ccodeblock unten mit dem !=NULL kann sonst zu Problemen mit der letzten Zeile führen.
    Und da du nichts davon geschrieben hast das du die Daten nochmal für was anderes brauchst...


    TIP: Es geht natürlich schon was du willst,entweder du nimmst Standartvorlagen dafür (CArray,CMap,CList und abgeleitete Klassen in Visual C++,STL gibt es so was auch,oder du machst das Ganze mit der eigentlichen Speicherverwaltung,schau dir dazu mal die Hilfe dieses Befehls memset an)


    zu 2. ist doch eigentlich identisch mit 2,das ganze vielleicht so umbauen:

    Code
    while(!feof(Datei)) 
    { 
    if(fgets(xl, 255, Datei)!=NULL)
    cout << xl << endl; 
    }


    Code
    cout<<"Suchtext wurde in folgenden Zeilen der Datei gefunden:"<<endl;
    for(i=1;!feof(Datei);i++) 
    { 
    if(fgets(xl, 255, Datei)!=NULL && xl.find(Suchstring)!=npos)
    cout <<"Zeile:"<<i<<" Text:"<< xl << endl; 
    }


    dieses "npos" ist keine neue Variabel das ist der Rückgabewert wenn find nichts findet,kannst aber auch auf !=-1 prüfen,ich bevorzuge aber die Verwendung dieser Konstanten.


    Peter


    Gegenfrage: Was stört dich daran NICHT Goto zu verwenden...,
    wie du siehst kommt dieses Programm OHNE GOTO aus,und wie gesagt deine Zukünftigen Programme würden auch alle ohne GOTO auskommen,
    wenn du die Anordnung von verschachtelen Schleifen VORHER,etwas besser überlegst ;)


    Peter

  • Zitat

    fgets bricht entweder bei "\n" ab oder nach 255 Zeichen,der Dateizeiger steht anschließend auf der nächsten Zeile,das unter Case3 müsste also gehen.


    Geht auch. Ich hatte wohl nicht beachtet, das es ja 'ne Schleife ist, und der char-Array in jedem DUrchgang wieder 'überschrieben' wird...

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!