Adressverwaltung



  • Hallo Forum!

    wir sollen in der Schule ein kleines Adressverwaltungprogramm in C schreiben. Wir sollen das Programm in Form einer doppelt verketteten Liste erstellen.
    Das Programm soll zwei Namen a und b einlesen und sie nach dem Alphabet sortieren.

    Dann soll das Programm eine -1 zurückliefern , wenn b vor a steht, 1, wenn a vor b steht, und 0, wenn a und b inhaltsgleich sind.

    Bin beim programmieren auch schon sehr weit gekommen, allerdings gibt das Programm nichts zurück. Ich glaube das die Methode Ordnung nicht auf die Datensätze
    zugreifen kann. Außerdem sollen wir mit Zeigern arbeiten was die Sache nicht unbedingt einfacher macht.

    Leider habe ich nur wenige Kenntnisse in C.

    Danke im Voraus

    #include <stdio.h>
    #include <stdlib.h>
    
    struct datensatz *a;  // hier habe ich die Datensätze deklariert
    struct datensatz *b;
    struct datensatz
    {
       char *name;
    };
    
    int ordnung(struct datensatz *a, struct datensatz *b)
    {
        int i=0;
        int lang=0;
        int geloest=2;
    
        if(strlen(a->name) > strlen(b->name))
        {
            lang=strlen(b->name);  //Länge des zweiten Namen ermitteln falls a>b 
        }
    
        else
        {
         lang=strlen(a->name);  //Länge des ersten Namen ermitteln falls b>a
        }
    
        for(i; i<lang; i++)//... so gibt es keine out of bounds exception
       {
        if ((int)a->name[i]>(int)b->name[i])  //hier soll das Programm Buchstabe für Buchstabe nach dem Alphabet prüfen
         {
           geloest=-1;
           i=lang;
        }
        else
         {
             if ((int)a->name[i]<(int)b->name[i])
             {
                 geloest=1;
                 i=lang;
             }
             else
         if((int)a->name[i]==(int)b->name[i])
         {
          geloest=0;  // und entsprechend -1, 1 oder 0 ausgeben
    
         }
      }
    
        }
      return geloest;
    }
    


  • ...



  • #include <ctype.h>
    
    int ordnung(struct datensatz *a, struct datensatz *b){
     int result = 0, i = 0;
     while(a->name[i] && b->name[i] && !result){
       result = toupper(a->name[i] & 255u) - toupper(b->name[i] & 255u);
       ++i;
     }
     return result < 0 ? -1 : (result ? 1 : 0);
    }
    


  • Compiliert das überhaupt ohne Fehler und Warnungen?

    Programmierer3211 schrieb:

    struct datensatz *a; // hier habe ich die Datensätze deklariert
    struct datensatz *b;

    Das hast du Zeiger auf die Datensätze definiert.
    Speicherplatz für die Datensätze hast du damit aber nicht.

    Für so einen Zweck ist es sinnvoller eine Funktion zu schreiben, die zwei Strings vergleicht und dann den entsprechenden Wert zurück gibt.
    So eine Funktion kann man öfter gebrauchen.

    int stringvergeich(const char *s, const char *t)
    { ....
    }
    
    int ordnung(struct datensatz *a, struct datensatz *b)
    { return stringvergeich(a->name, b->name);
    }
    

    Euren Einrückungsstil solltet ihr überdenken.
    Global Variablen sind schlecht.

    Wisst ihr was a->name="Schmidt"; genau macht?

    Ach und stringvergleich heisst auf englisch string compare oder kurz und knapp als Funktionsname strcmp. Und das ist eine Funktion der C-Standardlibrary



  • Wie kann man denn Speicherplatz für die Datensätze freigeben?
    Auch wenn ich das nachher wie vorgeschlagen mache, muss ich das wissen.
    Und danke für die Hilfe!



  • Programmierer3211 schrieb:

    Wie kann man denn Speicherplatz für die Datensätze freigeben?
    Auch wenn ich das nachher wie vorgeschlagen mache, muss ich das wissen.
    Und danke für die Hilfe!

    Mit welchem Compiler hast Du das übersetzt? In Zeile 9 benutzt Du eine Variable, die erst in Zeile 17 definiert wird.

    Zum Anfordern von Speicher gibt es die Funktion malloc. Zum Freigeben die Funktion free.

    mfg Martin



  • Programmierer3211 schrieb:

    Wie kann man denn Speicherplatz für die Datensätze freigeben?
    Auch wenn ich das nachher wie vorgeschlagen mache, muss ich das wissen.
    Und danke für die Hilfe!

    Im Augenblick habt ihr noch nicht einmal Speicher für Datensätze.

    Und wenn ihr wisst, wie man Speicher anfordert, wisst ihr auch wie man ihn wieder frei gibt. Das ist das selbe Kapitel im Buch.

    Und man lernt i.A. erst dynamische Speicherverwaltung und dann verkettete Listen.



  • Du sollst eine doppelt verkettete Liste erstellen. Es wäre dann sinnvoll, eine Struktur für die Liste zu erstellen, z.b. so:
    struct dListe {
    struct datensatz *daten;
    struct dListe *prev; //Zeiger auf vorhergehenden Datensatz
    struct dListe *next; // Zeiger auf nächsten Datensatz
    }

    struct Liste *a;
    Als struct datensatz kannst Du deine Struktur benutzen.
    Dann musst Du natürlich für die Variable a Speicherplatz resrevieren:
    a = malloc (sizeof(struct Liste));
    Ebenso für Deinen Datensatz (daten);
    Evtl. muss auch noch für den Inhalt der Struktur daten (name) Speicherplatz bereitgestellt werden, wenn es eine Zeigervariable ist.
    In einer weiteren Funktion vergleichst Du jedes Element, das schon in der Liste ist, mit dem einzufügenden: strcmp(a->daten->name, name);
    abhängig vom Rückgabewert wird das neue Element vor oder hinter dem gerade geprüften Listenelement eingefügt.
    Am besten hangelst Du Dich in einer Schleifer durch die Liste und prüfts jedes Element mit dem einzufügenden.
    Für alle Haarspalter: Dies ist kein fertiges Programm, sondern nur der Versuch, zur Problematik hinzuführen!!
    Gruß



  • Bitte immer an Funktionen übergebene Zeiger in der Funktion auf Null-Pointer überprüfen.



  • Die Antworten waren sehr nützlich,danke! Ich denke, ich weiß nun wie ich das Programm am Besten realisiere.



  • Hallo! Da wir, wie es der Zufall so will, die gleiche Aufgabe haben, mogel ich mich mal hier mit rein 😃

    #include <stdio.h>
    #include <stdlib.h>
    
    #define BUFLEN 100 
    
    struct datensatz {
        struct datensatz *vorgaenger, *nachfolger;
        char *name, *vorname, *strasse, *hausnummer, *stadt;
        unsigned char plz[5];
    };
    
    int ordnung(struct datensatz *a, struct datensatz *b){
    
        int i=0,j=0,ges_len,a_len,b_len,result; 
    
        //Länge des kleineren Strings wird festgestellt und in ges_len deklariert
    
        for (j=0; j < BUFLEN; j++) 
        { 
            if (a->name[j] == '\0') a_len=j; 
        } 
    
        for (j=0; j < BUFLEN; j++) 
        { 
            if (b->name[j] == '\0') b_len=j; 
        } 
    
        if(a_len > b_len) 
        { 
            ges_len = b_len;  
        } 
    
        else 
        { 
            ges_len = a_len;  
        } 
    
        //Untersuchung des Namens nach lexikalische Anordnung
    
        for(i=0; i < ges_len; i++) //Es wird nur bis zur Länge des kleineren Strings gezählt
        { 
            if (a_len > b_len){
                if (a->name[i] > b->name[i]) {
                    result = -1; ges_len = i; //Fall: Buchstabe a größer b, also b steht vor a im Alphabet
                }
                else if (a->name[i] == b->name[i]) {
                    result = -1; ges_len = i; //Die untersuchten Buchstaben sind gleich,also b vor a, da a mehr Buchstaben hat              
                }
            }
    
            if (a_len < b_len){
                if (a->name[i] < b->name[i]) {
                    result = 1; ges_len = i; //Fall: Buchstabe b größer a, also b steht vor b im Alphabet
                }
                else if (a->name[i] == b->name[i]) {
                    result = 1; ges_len = i; //Die untersuchten Buchstaben sind gleich,also a vor b, da b mehr Buchstaben hat   
                }
            }
    
            if (a_len == b_len){
                if (a->name[i] > b->name[i]) {
                    result = -1; ges_len = i;
                }
                if (a->name[i] < b->name[i]) {
                    result = 1; ges_len = i;
                }
                if (a->name[i] == b->name[i]) {
                    result = 0; ges_len = i;
                }
            }
    
        } 
        return result; 
    
    }
    
    int main (int argc, const char * argv[])
    {
        struct datensatz a = {/*struct datensatz vorgänger*/,/*struct datensatz Nachfolger*/,"Mustermann","Max","Musterstrasse", "5","Musterstadt","12345"};
        struct datensatz b = {/*struct datensatz vorgänger*/,/*struct datensatz Nachfolger*/,"Mustermann","Max","Musterstrasse", "5","Musterstadt","12345"};
    
        printf("%i",ordnung(&a,&b));  
    
        return 0; 
    
    }
    

    struct datensatz ist in seiner Form, wie sie oben steht, vorgegeben.

    Ich weiß jetzt nicht wie das mit dem *vorgänger und *nachfolger realisierbar sein soll. Außerdem hab ich Probleme mit der Initialisierung von *a und *b. Wenn ich das direkt im Hauptprogramm mit gewünschten Werten initialisiere, brauche ich keine Speicherzuweisung wie malloc oder? Zudem stellt sich hier wieder das Problem mit *vorgänger und *nachfolger.

    Wäre dankbar über ein paar Tipps 🙂



  • Bei der Definition der Variablen a und b kannst du für vorgaenger und nachfolger
    NULL eintragen.

    Danach kannst du dann

    a.nachfolger = &b;
    b.vorgaenger = &a;
    

    Deine Funktion ordnung ist viel zu kompliziert.
    Zu kompliziert gedacht und zu kompliziert umgesetzt: http://www.c-plusplus.net/forum/p2285528#2285528
    Dürft ihr strcmp nutzen?
    Wenn nein, programmiere es nach.



  • Nein strcmp dürfen wir nicht benutzen, aber meine Code von Zeile 44 bis 74 macht doch das gleiche wie strcmp oder wie meinst du das?

    Ich hab da jetzt stehen:

    struct datensatz a = {NULL,NULL,"Mustermann","Max","Musterstrasse", "5","Musterstadt","12345"};
        struct datensatz b = {NULL,NULL,"Musterfrau","Max","Musterstrasse", "5","Musterstadt","12345"};
    
        printf("%i",ordnung(&a,&b));
    

    Da kommt aber leider immer 0 raus 😞



  • Dein "strcmp" ist ja auch falsch.

    Schreibe eine Funktion mystrcmp, die ganz allgemein mit char-Arrays arbeitet und nicht mit der struct.

    Du hast viel zu viel Fallunterscheidungen.

    Geh doch mal Schritt für Schritt durch deine Funktion.
    Am Besten mit dem Debugger, es geht aber auch auf dem Papier
    Da landest du bei i = 0 in Zeile 71. Was passiert dann?



  • Danke Dirk ich habe den Fehler gefunden.

    Dass das Programm mit einer Funktion vereinfacht werden sollte, ist auch ein guter Tipp, da ich nach nach Übereinstimmung des Nachnamens den Vornamen etc. vergleiche. Und das wird dann zu riesig.

    Für den Nachnamen klappt das Programm schonmal, aber wenn ich das ganze jetzt für den Vornamen weiterführe, entsteht ein komischer Fehler.

    #include <stdio.h>
    #include <stdlib.h>
    
    #define BUFLEN 100
    
    struct datensatz {
        struct datensatz *vorgaenger, *nachfolger;
        char *name, *vorname, *strasse, *hausnummer, *stadt;
        unsigned char plz[5];
    };
    
    int ordnung(struct datensatz *a, struct datensatz *b){
    
        int i=0,j=0,ges_len,a_len,b_len,result;
    
        //Länge des kleineren Strings wird festgestellt und in ges_len deklariert
    
        for (j=0; j < BUFLEN; j++)
        {
            if (a->name[j] == '\0') a_len=j;
        }
    
        for (j=0; j < BUFLEN; j++)
        {
            if (b->name[j] == '\0') b_len=j;
        }
    
        if(a_len > b_len)
        {
            ges_len = b_len;
        }
    
        else
        {
            ges_len = a_len;
        }
    
        //Untersuchung des Namens nach lexikalische Anordnung
    
        for(i=0; i < ges_len; i++) //Es wird nur bis zur Länge des kleineren Strings gezählt
        {
            if (a_len > b_len){
                if (a->name[i] > b->name[i]) {
                    result = -1; ges_len = i; //Fall: Buchstabe a größer b, also b steht vor a im Alphabet
                }
                else if (a->name[i] == b->name[i]) {
                    result = -1; ges_len = i; //Die untersuchten Buchstaben sind gleich,also b vor a, da a mehr Buchstaben hat
                }
            }
    
            if (a_len < b_len){
                if (a->name[i] < b->name[i]) {
                    result = 1; ges_len = i; //Fall: Buchstabe b größer a, also b steht vor b im Alphabet
                }
                else if (a->name[i] == b->name[i]) {
                    result = 1; ges_len = i; //Die untersuchten Buchstaben sind gleich,also a vor b, da b mehr Buchstaben hat
                }
            }
    
            if (a_len == b_len){
                if (a->name[i] > b->name[i]) {
                    result = -1; ges_len = i;
                }
                if (a->name[i] < b->name[i]) {
                    result = 1; ges_len = i;
                }
                if (a->name == b->name) {
                    result = 0;
                }
            }
        }
    
      if (result != 0) {
            return result;
      }
    
        result = 0;
        a_len=0;
        b_len=0;
        ges_len=0;
        i=0;
        j=0;
    
        //Vorname
    
        for (j=0; j < BUFLEN; j++)
        {
            if (a->vorname[j] == '\0'){ a_len=j;} //98        
                                                        /*Hier liegt der Fehler*/
            if (b->vorname[j] == '\0'){ b_len=j;} //96
        }
    
        if(a_len > b_len)
        {
            ges_len = b_len;
        }
    
        else
        {
            ges_len = a_len;
        }
    
        //Untersuchung des Namens nach lexikalische Anordnung
    
        for(i=0; i < ges_len; i++) //Es wird nur bis zur Länge des kleineren Strings gezählt
        {
            if (a_len > b_len){
                if (a->vorname[i] > b->vorname[i]) {
                    result = -1; ges_len = i; //Fall: Buchstabe a größer b, also b steht vor a im Alphabet
                }
                else if (a->vorname[i] == b->vorname[i]) {
                    result = -1; ges_len = i; //Die untersuchten Buchstaben sind gleich,also b vor a, da a mehr Buchstaben hat
                }
            }
    
            if (a_len < b_len){
                if (a->vorname[i] < b->vorname[i]) {
                    result = 1; ges_len = i; //Fall: Buchstabe b größer a, also b steht vor b im Alphabet
                }
                else if (a->vorname[i] == b->vorname[i]) {
                    result = 1; ges_len = i; //Die untersuchten Buchstaben sind gleich,also a vor b, da b mehr Buchstaben hat
                }
            }
    
            if (a_len == b_len){
                if (a->vorname[i] > b->vorname[i]) {
                    result = -1; ges_len = i;
                }
                if (a->vorname[i] < b->vorname[i]) {
                    result = 1; ges_len = i;
                }
                if (a->vorname == b->vorname) {
                    result = 0;
                }
            }
    
        }
    
        return result;
    
    }
    
    int main (int argc, const char * argv[])
    {
        struct datensatz a = {NULL,NULL,"Mustermann","Max","Musterstrasse", "5","Musterstadt","12345"};
        struct datensatz b = {NULL,NULL,"Mustermann","Mbx","Musterstrasse", "5","Musterstadt","12345"};
    
        printf("%i",ordnung(&a,&b));
    
        return 0;
    
    }
    

    In Zeile 92 erhält der Vorname für a eine größere Länge als b, obwohl beide Vornamen gleich lang sind. Wie kann dass sein?



  • PapLoth323 schrieb:

    In Zeile 92 erhält der Vorname für a eine größere Länge als b, obwohl beide Vornamen gleich lang sind. Wie kann dass sein?

    Weil die Länge der Vornamen mit BUFLEN nichts, aber auch gar nichts zu tun hat.
    Du findest das letzte vorkommen von '\0'. Nur ist der Speicher der Vornamen da schon lange vorbei.
    Mal einen Code für strcmp, den du verstehen solltest.

    int mystrcmp(char a[], char b[])
    {
       int c = 0;
    
       while( a[c] == b[c] )  // solange die Strings gleiche Zeichen haben
       {
          if( a[c] == '\0' )  // String zu Ende, dann gleich lang (da auch b[c] \0' ist)
            return 0;
          c++;
       }
       return  ( a[c] > b[c]) ? 1 : -1;
    /* oder in lang
       if( a[c] > b[c])
          return 1;
       else
          return -1;
    */
    }
    

    Mehr ist das nicht.
    Das brauchst du einmal. Die rust du dann aus ordnung auf.
    Einmal für die Nachnamen und dann für Vornamen.
    Dann ist ordnung ein 3-Zeiler.



  • Hi! Mithilfe der Funktion ordnung kann man ja eine Funktion erstellen, die einen neuen Daten an der richtigen Stelle entsprechend der Ordnungsrelation einfügt.

    Ich weiß noch nicht so richtig wie ich die Funktion aussehen soll. Ich dachte mir in etwa struct datensatz *ordnungsrelation(struct datensatz *a,...) . Dabei weiß ich aber auch nicht, was ich als zweites Argument nehmen soll.

    Kann mir jemand paar tipps geben, wie ich dabei vorgehen muss?



  • Wenn du Daten einfügen willst, brauchst du einmal die Liste (den Anfang oder den Eintrag vor/nach dem eingetragen werden soll) und dann noch die Daten die eingefügt werden sollen.

    Bevor du jetzt versuchst das alles in der Funktion ordnung zu machen, vergiss es.
    Du brauchst erstmal Funktionen zur Listenverwaltung.



  • Ok ich habe jetzt die Funktion Ordnung, die unverändert bleibt.
    Dann benötige ich eine Funktion zur Listenverwaltung. Und zu guter Letzt die Funktion, die den neuen Datensatz einfügt, richtig?



  • DirkB schrieb:

    Du brauchst erstmal Funktionen zur Listenverwaltung.

    - Datensatz neu anlegen
    - einfügen von Daten
    - löschen von Daten
    - suchen von Daten


Anmelden zum Antworten