Wörter sortieren



  • Hallo,
    eine kurze Frage und zwar schreibe ich eine Funktion welche Wörter nach dem Anfangsbuchstaben sortiert und das klappt soweit auch ganz gut.
    Allerdings mischen sich manchmal Wörter an die falsche Stelle in der Liste und ich verstehe ehrlich gesagt nicht warum.
    Bei fast jedem Versuch ist das Wort das an der letzten Stelle stehen sollte an erster Stelle, bei vielen Versuchen ist auch ein anderes Wort an der falschen Stelle, wobei die Sortierung im Allgemeinen funktioniert.
    Hier der Code:

    void sortieren2DArray(char *wort,int anzahl,int spalten) 
    { 
        int j,i,z,ascii[anzahl],temp; 
        char tempc,tempca[9]; 
        for(i=0; i<anzahl; i++) 
        { 
            ascii[i]= int (wort[i*spalten]); 
        } 
        for(i=0; i<anzahl; i++) 
        { 
            for(j=anzahl; j>0; j--) 
            { 
                if(ascii[j]<ascii[j-1]) 
                { 
                    temp=ascii[j-1]; 
                    ascii[j-1]=ascii[j]; 
                    ascii[j]=temp; 
                } 
            } 
        } 
        char asciic[10]; 
        for(i=0; i<10; i++) 
        { 
            asciic[i]=char(ascii[i]); 
        } 
    
        for(i=0; i<anzahl; i++) 
        { 
            for(j=0; j<anzahl*spalten; j+=spalten) 
            { 
                if(asciic[i]==wort[j]) 
                { 
                    tempc=wort[i*spalten]; 
                    wort[i*spalten]=wort[j]; 
                    wort[j]=tempc; 
                    for(z=1; z<spalten; z++) 
                    { 
                        tempca[z-1]=wort[i*spalten+z]; 
                        wort[i*spalten+z]=wort[j+z]; 
                        wort[j+z]=tempca[z-1]; 
                    } 
                } 
            } 
        }
    }
    

    Im Voraus schon mal danke für die Mühe. 👍



  • Versuche bitte deinen Quellcode immer nach diesem Muster hier einzustellen:

    void sortieren2DArray(char *wort,int anzahl,int spalten)
    {
        int j,i,z,ascii[anzahl],temp;
        char tempc,tempca[9];
        for(i=0; i<anzahl; i++)
        {
            ascii[i]= int (wort[i*spalten]);
        }
        for(i=0; i<anzahl; i++)
        {
            for(j=anzahl; j>0; j--)
            {
                if(ascii[j]<ascii[j-1])
                {
                    temp=ascii[j-1];
                    ascii[j-1]=ascii[j];
                    ascii[j]=temp;
                }
            }
        }
        char asciic[10];
        for(i=0; i<10; i++)
        {
            asciic[i]=char(ascii[i]);
        }
    
        for(i=0; i<anzahl; i++)
        {
            for(j=0; j<anzahl*spalten; j+=spalten)
            {
                if(asciic[i]==wort[j])
                {
                    tempc=wort[i*spalten];
                    wort[i*spalten]=wort[j];
                    wort[j]=tempc;
                    for(z=1; z<spalten; z++)
                    {
                        tempca[z-1]=wort[i*spalten+z];
                        wort[i*spalten+z]=wort[j+z];
                        wort[j+z]=tempca[z-1];
                    }
                }
            }
        }
    

    Als reg. Mitglied kannst du das gar nachträglich entsprechend editieren.
    Zum Test schau mit der Vorschau ob das so ist, wie du es möchtest.



  • Ok ich werde in der Zukunft besser einrücken.
    Aber leider funktioniert es auch so nicht richtig.
    Die allgemeine Sortierung klappt,aber manchmal rutschen immer noch Wörter an die falsche Position. Man könnte sagen, dass von 10 Wörtern 8 richtig sortiert sind, aber dann steht bspw. das Wort ziemlich an der 3. Stelle.



  • Ich kann nirgendwo dein "2D"-Array (damit meinst du wohl eine Stringliste) finden.
    Ich lerne gern dazu, zeig mal wo du sowas hast.
    Ich kann auch nirgendwo C++ entdecken, zeig mal wo dein Code C++ verwendet.



  • Dein Algorithmus ist falsch.

    Angenommen der erste Teil, wo du ein sortiertes Array der Anfangsbuchstaben erstellst ist richtig, so zerschießt Du Dir im zweiten Teil - dort wo Du die tatsächlichen Wörter vertauscht - die Arrayinhalte. (So wie ich das sehe, zumindest, wenn Du Wörter mit gleichem ersten Buchstaben hast.)



  • Das war nur die Funktion.Und stimmt schon mein Code hat nicht wirklich viel mit c++ zu tun, bin eben noch ein ziemlicher Anfänger und muss mir Objektorientierung erst noch beibringen.
    Und ich habe keine Strings benutzt sondern ein zweidimensionales Array.
    Hier der vollständige code:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    void sortieren2DArray(char *wort,int anzahl,int spalten) 
    { 
        int j,i,z,ascii[anzahl],temp; 
        char tempc,tempca[9]; 
        for(i=0; i<anzahl; i++) 
        { 
            ascii[i]= int (wort[i*spalten]); 
        } 
        for(i=0; i<anzahl; i++) 
        { 
            for(j=anzahl; j>0; j--) 
            { 
                if(ascii[j]<ascii[j-1]) 
                { 
                    temp=ascii[j-1]; 
                    ascii[j-1]=ascii[j]; 
                    ascii[j]=temp; 
                } 
            } 
        } 
        char asciic[10]; 
        for(i=0; i<10; i++) 
        { 
            asciic[i]=char(ascii[i]); 
        } 
    
        for(i=0; i<anzahl; i++) 
        { 
            for(j=0; j<anzahl*spalten; j+=spalten) 
            { 
                if(asciic[i]==wort[j]) 
                { 
                    tempc=wort[i*spalten]; 
                    wort[i*spalten]=wort[j]; 
                    wort[j]=tempc; 
                    for(z=1; z<spalten; z++) 
                    { 
                        tempca[z-1]=wort[i*spalten+z]; 
                        wort[i*spalten+z]=wort[j+z]; 
                        wort[j+z]=tempca[z-1]; 
                    } 
                } 
            } 
        } 
    }
    int main(int argc, char** argv) {
    	short zeilen=10,spalten=10;
    	char wort[zeilen][spalten];
    	short i,j,anzahl;
    	cout<<"Anzahl der Woerter";
    	cin>>anzahl;
    	for(i=0;i<zeilen;i++)
    	{for(j=0;j<spalten;j++)
    	{wort[i][j]=' ';
    	}
    	}
    	for(i=0;i<anzahl;i++)
    	{cout<<"Wort"<<i+1<<": ";
    	cin>>wort[i];
    
    }
    
    sortieren2DArray(*wort,anzahl,spalten);
    
    for(i=0;i<anzahl;i++)
    {cout<<i+1<<".";
    for(j=0;j<spalten;j++)
    {
    cout<<wort[i][j];
    }
    cout<<endl;
    }
    	return 0;
    }
    

    Wie gesagt an der ersten Stelle ist fast immer das Wort was eigentlich, das letzte sein sollte und ab und zu rutscht ein Wort an die falsche Position, aber im allgemeinen passt das so.
    Danke für die Rückmeldungen 👍


  • Mod

    Zeichenketten und Arrays in C sind ziemlich unintuitiv für viele Anfänger und du machst prompt so ziemlich alles falsch, was falsch zu machen ist. Vielleicht wärst du besser beraten, richtiges C++ zu lernen? Was du hier zeigst ist das gefürchtete C mit cout und hat weder mit C noch mit C++ so richtig etwas zu tun. Wo hast du das beigebracht bekommen?

    Für konkrete Hilfe müsste man wissen, welche Sprache du denn nun wirklich machen willst. In beiden würde man natürlich eigentlich die eingebauten Sortierfunktionen benutzen, aber mal angenommen, man wollte dies wirklich selber machen: In C wärst du tendenziell auf dem richtigen Weg, aber du gehst halt falsch mit den Arrays um. Die Tatsache, dass du so viel casten musst, sollte dir klar machen, dass dein Code logisch nicht stimmig ist. In C++ hingegen würde man weder Arrays und erst recht nicht Zeichenketten so handhaben. Das mag dann zwar intuitiver sein, aber bei deinem jetzigen Kenntnisstand über C++ (der auf cout/cin beschrankt zu sein scheint) würde dir eine solche Lösung aber vermutlich wie Magie vorkommen und du kaum etwas davon verstehen.



  • Naja ich will mir in den nächsten Wochen sowieso Objektorientierung beibringen und hab das eigentlich nur gemacht um ein Programm geschrieben zu haben in dem ich Zeiger verwendet habe.
    Trotzdem fände es nett wenn du mir sagen würdest wie ich das auf diese Art und Weise(also auf die C-Art) lösen kann.

    Gelernt hab ich das übrigens in der Schule,wobei wir vom Niveau her nie über Zinsrechnungen hinausgegangen sind.


  • Mod

    sony3x schrieb:

    Naja ich will mir in den nächsten Wochen sowieso Objektorientierung beibringen und hab das eigentlich nur gemacht um ein Programm geschrieben zu haben in dem ich Zeiger verwendet habe.

    Objektorientierung hat mit der Sprache nichts zu tun.

    Gelernt hab ich das übrigens in der Schule,wobei wir vom Niveau her nie über Zinsrechnungen hinausgegangen sind.

    Es geht nicht darum wie viel oder wie wenig gelehrt wurde, sondern darum, dass das Gelehrte falsch ist. Es ist weder C noch C++, sondern eine wilde Mischung. Mischung dieser Sprachen funktioniert aber in aller Regel nicht.

    Trotzdem fände es nett wenn du mir sagen würdest wie ich das auf diese Art und Weise(also auf die C-Art) lösen kann.

    Die pragmatische Lösung:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int stringcompare(const void *lhs, const void *rhs)
    {
      return strcmp(*(char* const*) lhs, *(char* const*) rhs);
    }
    
    int main()
    {
      char *strings[] = {"lorem", "ipsum", "dolor", "sit", "amet", "consectetur", 
                         "adipiscing", "elit", "sed", "do", "eiusmod", "tempor", 
                         "incididunt", "ut", "labore", "et", "dolore", "magna", 
                         "aliqua"};
      size_t i;
    
      qsort(strings, sizeof(strings)/sizeof(*strings), sizeof(*strings), stringcompare);
    
      for (i = 0; i < sizeof(strings)/sizeof(*strings); ++i)
        puts(strings[i]);
    }
    

    Die weniger pragmatische Lösung ist, qsort selber nach zu programmieren. Da die Macher von qsort schon wussten, was sie da tun, übernehme ich mal die Schnittstelle, wie sie ist. Dann kann man die Funktion hinterher wenigstens noch für etwas anderes benutzen als nur das Sortieren von Zeichenketten. Es wird natürlich ein wenig komplizierter, weil man die ganze Zeit die Größe und die Vergleichsfunktion mit schleppen muss:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void merge(char *data, size_t size, int (*compare)(const void*, const void*),
               size_t begin, size_t middle, size_t end)
    {
      size_t i, j, k;
      size_t left_count = (middle - begin + 1);
      size_t right_count = (end - middle);
      void *left_storage = malloc(left_count * size);
      void *right_storage = malloc(right_count * size);
      memcpy(left_storage, data + begin * size, left_count * size);
      memcpy(right_storage, data + (middle + 1) * size, right_count * size);
    
      i = 0; j = 0; k = begin;
      while(i < left_count && j < right_count)
        {
          if(compare(left_storage + i*size, right_storage + j*size) <= 0)
            {
              memcpy(data + k*size, left_storage + i*size, size);
              ++i;
            }
          else
            {
              memcpy(data + k*size, right_storage + j*size, size);
              ++j;
            }
          ++k;
        }
      memcpy(data + k*size, left_storage + i*size, (left_count - i) * size);
      k += (left_count - i);
      memcpy(data + k*size, right_storage + j*size, (right_count - j) * size);
    
      free(left_storage);
      free(right_storage);
    }
    
    void sort(char *data, size_t size, int (*compare)(const void*, const void*), 
              size_t begin, size_t end)
    {
      if (begin < end)
        {
          size_t middle = (begin + end) / 2;
          sort(data, size, compare, begin, middle);
          sort(data, size, compare, middle + 1, end);
          merge(data, size, compare, begin, middle, end);
        }
    }
    
    void qsort(void *data, size_t count, size_t size,
               int (*compare)(const void*, const void*))
    {
      sort(data, size, compare, 0, count - 1);
    }
    
    int stringcompare(const void *lhs, const void *rhs)
    {
      return strcmp(*(char* const*) lhs, *(char* const*) rhs);
    }
    
    int main()
    {
      char *strings[] = {"lorem", "ipsum", "dolor", "sit", "amet", "consectetur", 
                         "adipiscing", "elit", "sed", "do", "eiusmod", "tempor", 
                         "incididunt", "ut", "labore", "et", "dolore", "magna", 
                         "aliqua"};
      size_t i;
      qsort(strings, sizeof(strings)/sizeof(*strings), sizeof(*strings), stringcompare);
    
      for (i = 0; i < sizeof(strings)/sizeof(*strings); ++i)
        puts(strings[i]);
    }
    

    Merke, dass ich in keinem Fall ein 2D-Array für die Zeichenketten benutzt habe. Das ist zwar möglich, aber wäre höchst ungewöhnlich. Du willst schließlich wissen, wie es richtig ginge, nicht wie du den halbgaren Mist, den du beigebracht bekommen hast zum Laufen bringst. So wie hier ist es jedenfalls viel einfacher als deine Versuche, wie du hoffentlich siehst; besonders das erste Beispiel. Die entscheidende Frage ist aber wohl, ob du überhaupt meine Beispielen verstanden hast oder diese nun einfach blind übernehmen wirst. Es hatte nämlich einen guten Grund, wieso ich dir eigentlich keinen konkreten Code vorsetzen wollte, bevor du nicht selber gelernt hast, wie man richtig mit Zeichenketten und Arrays umgeht.

    Der Sortieralgorithmus, den ich hier benutzt habe, ist eine naive Implementierung von Mergesort. Wenn du dir eine Beschreibung davon durchliest, sollte das auch für Anfänger recht nachvollziehbar sein.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum C (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • SeppJ schrieb:

    Der Sortieralgorithmus, den ich hier benutzt habe, ist eine naive Implementierung von Mergesort.

    Damit überschreibt man aber keine Standardfunktion wie hier qsort!


Log in to reply