Wo ist der Fehler ?



  • Hey ihr, ich programmiere in C auf dem MAC.

    Ich hab folgendes Problem:

    ich möchte die Zeilen einer Datei zählen, reine Kommentarzeilen aber ignorieren, also bei

    /* Hauptteil */
    main ()

    soll er mir als Zeilenzahl 1 und nicht 2 ausgeben und bei

    printf("c"); /* C ausgeben */

    soll er diese Zeile mitzählen.

    Ich packe mir die Datei in einen Buffer, auf den ich mit einem Handle zugreife. Ich möchte nun, dass er den Inhalt des Handles Zeichen für Zeichen abfragt bis er ein /-Zeichen findet. Wenn das direkte Zeichen danach ein * und direkte Zeichen davor ein \r (Zeilentrenner) ist, dann steht logischerweise die Zeile am Anfang einer Zeile. Nun soll er ab dem zweiten Zeichen nach / den String weiter durchsuchen, bis er ein *-Zeichen findet. Ist das direkte Zeichen danach ein / und das zweite Zeichen danach ein \r, dann ist die reine Kommentarzeile beendet. Dann soll er eine Variable "Number of Lines" (nl) inkrementieren.

    Meine Anweisung hierfür sieht so aus:

    char     a = *;
    
    if (GetHandleSize(hlnBuf) != 0) {
        for (i = 0; i < GetHandleSize(hlnBuf); i++) {
            if (i != 0) {
                if (*(*hlnBuf + i) == '\r')
                    nl++;
                if (*(*hlnBuf + i) == '/')
                    if (strcmp((*hlnBuf +(i+1)), &a) == 0) 
                        if (*(*hlnBuf + (i-1)) == '\r')
                            for (j = i+2; j < GetHandleSize(hlnBuf); j++) {
                                if (*(*hlnBuf + j) == '*')
                                    if (*(*hlnBuf + (j+1)) == '/')
                                        if (*(*hlnBuf + (j+2)) == '\r')                                 
                                            --nl;
                                            break;
                            }
            }
        }
    }
    HUnlock(hlnBuf);
    DisposeHandle(hlnBuf);
    hlnBuf = NULL;
    

    Mein Compiler überspringt aber einfach schon die dritte Bedingung Zeichen == \r, womit das Programm nicht funktionieren kann. Ich verstehs aber nicht so ganz, denn die Funktion sieht für mich richtig aus.
    Könnt ihr mir bitte sagen, wo der Fehler ist?



  • Hi,

    if (**(hlnBuf + i) == '\r')

    Ich glaube es sollte so heissen:

    [cpp]
    if (*(hlnBuf + i) == '\r')[/cpp]

    mfg
    v R

    [ Dieser Beitrag wurde am 25.10.2002 um 09:39 Uhr von virtuell Realisticer editiert. ]

    [ Dieser Beitrag wurde am 25.10.2002 um 09:40 Uhr von virtuell Realisticer editiert. ]



  • Hey!
    Nope, das haut nicht hin, das ist dann einmal zu wenig dereferenziert.
    Entweder

    (*(*hlnBuf + i) == '\r')
    

    oder

    (*hlnBuf[i] == '\r')
    

    [ Dieser Beitrag wurde am 25.10.2002 um 11:00 Uhr von Casi666 editiert. ]



  • Der Denkfehler liegt wohl bei Einsatz von strcmp.



  • Hallo,

    char a=*; Läßt der Compiler das durch?

    Mfg Lem



  • Wieso öffnest du die Datei eigentlich binär mittels irgendwelcher Systemfunktionen? Nimm doch fopen(..., "r"); dann bleibst du portabel.

    Der Fehler liegt natürlich vordergründig im Einsatz von strcmp, allerdings denke ich, dass die Programmstruktur auch an sich zu kompliziert ist, so dass du nicht mehr durchblickst.

    *(a+i) ist übrigens das gleiche wie a[i]



  • @<Lem>: Ich hab die Anführungszeichen vergessen zu posten, aber sie stehen im Programm *räusper*
    Muss also char a = '*'; sein.

    @Bashar: Hast Recht, das mit dem strcmp war schon eine Änderung des Quellcodes wie es mir ein weiterer Azubi hier aus der Firma als richtig aufgedrängt hat.
    Deinen ersten Satz allerdings kann ich nicht so ganz nachvollziehen... Naja, wie gesagt, ich arbeute auf einem MAC und da hat jedes File ein Data-Fork und ein Ressource-Fork wohingegen Dateien auf dem PC nur das Data-Fork haben, daher sind Files auf dem Mac anders zu bearbeiten (würde ich sagen...).
    Ich muss dem Mac also erstmal sagen, dass überhaupt ein neues File erstellt wird, dann muss ich das Data-Fork anlegen, dann kann ich es erst öffnen und dann erst reinschreiben.
    Aber ich glaube, das war nicht das, was du meintest, oder?



  • Übrigens sieht das Ganze mittlerweile so aus (das Programm unterliegt ja laufend fliessenden Änderungen):

    void IgnoreComments (Handle hSource, Handle hCollect)
    {
        short   nCount = 1;
        int     i, j;
        char    Placeholder[25] = " ";
    
        if (GetHandleSize(hSource) != 0) {
            for (i = 0; i < GetHandleSize(hSource); i++) {
                if (i != 0) {
                    if (*hSource[i] == '\r')
                        nCount++;
                    if ((*hSource[i] == '/') && (*hSource[i+1] == '*') && (*hSource[i-1] == '\r'))
                        for (j = i+2; j < GetHandleSize(hSource); j++)
                            if ((*hSource[j] == '*') && (*hSource[j+1] == '/') && (*hSource[j+2] == '\r'))  {                           
                                break;
                            }
                }
            }
        }
        sprintf(Placeholder, "Zeilen der Datei ohne Kommentare: %d\n", nCount);
        HUnlock(hCollect);
        i = strlen(Placeholder);
        PtrAndHand(&Placeholder, hCollect, i);
        HLock(hCollect);
    }
    

    Vielleicht ist es jetzt für euch übersichtlicher? 🙂



  • Der Satz "Zeilen der Datei ohne Kommentare" ist zu groß für Placeholder.
    Zu if(i!=0) fehlt imho ein else.
    Vor breake; würde vielleicht --nCount passen.
    Und Du berücksichtigst nicht die Leerzeichen(Tabs), die for /* und nach */ stehen können.

    MfG Lem



  • Stimmt, du hast Recht 🙂
    Ich sitz jetzt seit insgesamt 3 Arbeitstagen daran, die Funktion sieht mittlerweile wieder ganz anders und grösser aus und funzt leider immer noch nicht. Das noch bestehende Problem: eingerückte Leerzeilen werden als Kommentare erkannt.
    Ich hab die Funktion erstmal komplett beiseite gelegt und mich mit was anderem beschäftigt, aber wenn ich mich wieder dran setze und sie läuft werde ich sie hier mal posten, da ihr euch ja immerhin auch den Kopf drüber zerbrochen habt, ok?



  • So, die Funktion läuft jetzt bei mir, aber ich bin mir 100%ig sicher, dass sie auch viel, viel kürzer zusammenzufassen ist.
    Ich poste sie jetzt hier mal, wenn jemand von euch sie aber zusammenkürzen will, fühlt euch frei das zu tun 😉

    void IgnoreComments(Handle hSource, Handle hCollect)
    {
        short   nCount = 1;
        int     i, j = 1;
        char    Placeholder[25] = " ";
    
        if (GetHandleSize(hSource) != 0)
            for (i = 0; i < GetHandleSize(hSource); i++) {
                /* Kommentar erste Zeile */
                if (i == 0 && (*(*hSource + i) == '/')) {
                    if ((*(*hSource + (i+1)) == '/') || (*(*hSource + (i+1)) == '*')) {
                        while (!(((*(*hSource + (i+2)) == '*') && (*(*hSource + (i+3)) == '/') && 
                            (*(*hSource + (i+4)) == '\r'))  || (*(*hSource + (i+2)) == '\r'))) {
                            i++;
                            if (((*(*hSource + (i+2)) == '*') && (*(*hSource + (i+3)) == '/') && 
                                (*(*hSource + (i+4)) == '\r'))  || (*(*hSource + (i+2)) == '\r'))
                                ;
                        }
                        if (*(*hSource + (i+2)) == '\r')
                            i = i+2;
                        else if (*(*hSource + (i+4)) == '\r')
                            i = i+4;
                    }
                }
                /* genereller Kommentar am Anfang einer Zeile */
                 else if ((*(*hSource + i) == '/') && ((*(*hSource + (i+1)) == '*') || 
                    (*(*hSource + (i+1)) == '/'))) {
                    if (*(*hSource + (i-1)) == '\r') {
                        while (!(((*(*hSource + (i+2)) == '*') && (*(*hSource + (i+3)) == '/') && 
                            (*(*hSource + (i+4)) == '\r')) || (*(*hSource + (i+2)) == '\r'))) {
                            i++;
                            if (((*(*hSource + (i+2)) == '*') && (*(*hSource + (i+3)) == '/') && 
                                (*(*hSource + (i+4)) == '\r')) || (*(*hSource + (i+2)) == '\r'))
                                ;
                        }
                        if (*(*hSource + (i+2)) == '\r')
                            i = i+2;
                        else if (*(*hSource + (i+4)) == '\r')
                            i = i+4;
                    }
                }
    
                /* eingerückter Kommentar */
                else if ((*(*hSource + i) == '\t') || (*(*hSource + i) == ' ')) {
                    if (*(*hSource + (i-1)) == '\r') {
                        for (j = i; (*(*hSource + j) != '\r'); j++) {
                            // eingerückte Leerzeile
                            if (*(*hSource + (j+1)) == '\r')
                                i = j;
                            // Kommentar nach Anweisung
                            if (isalnum(*(*hSource + j)) || (*(*hSource + j) == '}')) {
                                while (*(*hSource + (j+1)) != '\r')
                                    j++;
                                if (*(*hSource + (j+1)) == '\r')
                                    i = j;
                            }
                            // eingerückter "richtiger" Kommentar
                            if ((*(*hSource + j) == '/') && ((*(*hSource + (j+1)) == '/') || 
                                (*(*hSource + (j+1)) == '*'))) {
                                while (!(((*(*hSource + (j+2)) == '*') && (*(*hSource + (j+3)) == '/') && 
                                    (*(*hSource + (j+4)) == '\r')) || (*(*hSource + (j+2)) == '\r'))) {
                                    j++;
                                    if (((*(*hSource + (j+2)) == '*') && (*(*hSource + (j+3)) == '/') && 
                                        (*(*hSource + (j+4)) == '\r')) || (*(*hSource + (j+2)) == '\r'))
                                        ;
                                }
                                if (*(*hSource + (j+2)) == '\r') {
                                    j = j+2;
                                    i = j;
                                }
                                else if (*(*hSource + (j+4)) == '\r') {
                                    j = j+4;
                                    i = j;
                                }
                            j = j-1;
                            }
                        }
                    }
                }
                /* generelles Zeilenzählen */
                else if (*(*hSource + i) == '\r')
                    nCount++;
            }
    
        sprintf(Placeholder, "Zeilen der Datei ohne Kommentare: %d\n", nCount);
        HUnlock(hCollect);
        i = (strlen(Placeholder)+1);
        BlockMove(&Placeholder, *hCollect, i);
        HLock(hCollect);
    }
    


  • Und was ist mit Tee?

    #if 0
    jetzt staunst Du aber
    #endif

    char xxx[]="und das\
    //gibt Dir den Rest\
    ";

    [ Dieser Beitrag wurde am 09.11.2002 um 18:27 Uhr von Bitsy editiert. ]



  • Original erstellt von Bitsy:
    **
    #if 0
    jetzt staunst Du aber
    #endif
    **

    Das ist fies. Dann muss er ja fast einen eigenen Präprozessor nachprogrammieren für

    #if 34 < 23
     jetzt staunst Du aber
    #endif
    

    Ich würde sowas als 3 Zeilen Code ansehen, wenn ich so ein Programm bauen müsste. Oder willst Du nur den Fall '#if 0' ausnehmen.



  • Ich habe solch einen Präprozessor sogar derzeit in Arbeit, deshalb kenne ich den Fall gut. Solch ein Block findet sich tatsächlich in der Q2-Source.

    Der Nutzen eines solchen Präprozessors liegt auf der Hand:
    Replace in Files von Symbolen (also nicht in Strings oder Comments),
    Aufsuchen von bestimmten Situationen,
    Sourceformatierung, etc.
    Programmzeilenzählen ohne Comments pur wäre als Nebenfunktion möglich.

    Gleichwohl muss ich sagen, dass jener 'Structurizer' auch nur eine Teilmenge aller denkbaren Projekte behandeln kann. Man denke an 'offene' Macros, oder gar includes, stringize-Token, oder ##. Also doch eher ein 'private only'-Projekt.

    [ Dieser Beitrag wurde am 09.11.2002 um 21:06 Uhr von Bitsy editiert. ]



  • Original erstellt von Bitsy:
    **Und was ist mit Tee?

    #if 0
    jetzt staunst Du aber
    #endif

    char xxx[]="und das\
    //gibt Dir den Rest\
    ";

    [ Dieser Beitrag wurde am 09.11.2002 um 18:27 Uhr von [qb]Bitsy** editiert. ][/QB]

    Äh... Wie jetzt... Tee ?!?

    Ausserdem soll die Funktion sämtliche Quelltextzeilen zählen AUSSER Kommentarzeilen.
    Deine if und endif-Bedingung da oben ist kein Kommentar, wird also als 3 Zeilen mitgezählt. Und die Sache darunter enthält in der zweiten Zeile einen Kommentar, sonst doch nicht, und wird somit als 2 Zeilen gezählt, was doch richtig ist.
    Oder was willst du mir sagen?

    Mit euren nachfolgenden Texten zum Präprozessor bin ich als C-Anfänger momentan überfordert...



  • Original erstellt von <Casi666>:
    Deine if und endif-Bedingung da oben ist kein Kommentar, wird also als 3 Zeilen mitgezählt.

    ja, aber es wird NIE ausgefuehrt, insofern könnte man es für kommentare nutze...

    Und die Sache darunter enthält in der zweiten Zeile einen Kommentar,

    nein!

    char xxx[]="und das\
    //gibt Dir den Rest\
    ";
    ist gleich
    char xxx[]="und das//gibt Dir den Rest";



  • und wenn man das in nem anständigen Editor schreibt sieht man sogar das das in der zeiten Zeile kein Kommentar ist... 😉



  • @Casi:
    Jetzt mach Dir über diese Spezialfälle mal keine Gedanken, die dürften in der Praxis kaum vorkommen. Trotzdem sind sie zumindest denkbar, und mit ein wenig Böswilligkeit könnten Dich andere mit sowas ärgern. Bringst Du die Fälle irgendwie mit unter, bist Du derjenige, der zuletzt lacht.

    Und:
    Wenn Du nicht werbegeschädigt bist, hat es keinen Sinn die Sache mit dem Tee zu erklären. 😉



  • Okay, keine Gedanken machen kann ich besonders gut 🙂

    Die Sache mit den #if-Sachen stimmt natürlich, aber dafür gibt es ja Konventionen laut ANSI an die man sich halten sollte betreffs Kommentare 🙂

    Und die zweite Sache wusste ich so nicht. Hast natürlich Recht, es wird als Kommentar erkannt, da ich das Ding ja so programmiert habe und nicht wusste, dass sowas wie in deinem Beispiel geht *arghz*

    Anway: Danke, okay und Gute Nacht *grinsel*



  • Original erstellt von Shade Of Mine:
    ja, aber es wird NIE ausgefuehrt, insofern könnte man es für kommentare nutze...

    Es verhält sich aber schon ein wenig anders:

    /* 'bla */                          /* darf */
    
    #if 0
       'bla                             /* darf nicht */
    #endif
    

    Also ist es kein vollwertiger Ersatz für richtige Kommentare.


Anmelden zum Antworten