komische Ausgabe obwohl Funktion identisch



  • saveit schrieb:

    wie kann man das umgehen?

    void sort_a()
    {
    ...
    }
    
    int main()
    ...
    
        cout << "\nnew array: ";
        sort_a();
    


  • Schlangenmensch schrieb:

    Was deine Funktion machen soll ist soweit klar. Sie sortiert ein globales Array. Das ist vom Stil her schon unschön, aber hier ja nicht der Punkt.

    Eine Funktion mit der Deklaration

    int something();
    

    gibt ein Integer (Ganzzahlentyp) zurück, mit hilfe des Schlüsselwortes return. Das machst du aber in deiner Funktion nicht. Damit erzeugst du undefiniertes Verhalten. Je nach Compiler solltest du dazu auch eine Warnung bekommen!

    Ich würde dir empfehlen, dir nochmal das Kapitel über Funktionen / Methoden in deinem C++ Buch / Tutorial durchzuarbeiten.

    Was wäre denn ein schöner Stil? Der Compiler gibt mir tatsächlich eine Warnung aus. Bloß kann ich damit derzeitig noch nichts anfangen. Werde deinen Rat befolgen und schauen was dort so im Kapitel steht.



  • Bei mir wird der Code gar nicht erst kompiliert.

    Um die globalen Variablen zu vermeiden, gibst du der Funktion einfach den Array mit und den Integer temp kannst du einfach in die Funktion packen, da der außerhalb dieser nicht benötigt wird.
    Also:

    void sort_a(int *values);
    

    und den Array schreibst du als lokale Variable in die main-Funktion.
    Bei dem Funktionsaufruf darfst du dann allerdings nicht die Funktion ausgeben, du musst einfach nur den Funktionsnamen mit den Parametern verwenden. Als Parameter nimmst einen Zeiger auf das erste Element des Arrays, der identisch mit dem Namen des Arrays ist.

    Den schöneren Stil hat bereits manni66 gepostet.



  • Pointer kommen leider erst im nächsten Kapitel. Muss mich erst mit den Übungsaufgaben rumschlagen. Leider gibt es dafür auch keine Lösungen.



  • saveit schrieb:

    Pointer kommen leider erst im nächsten Kapitel. Muss mich erst mit den Übungsaufgaben rumschlagen. Leider gibt es dafür auch keine Lösungen.

    leider kann man das geschriebenen als Gast nich editieren, nun denn, was bedeutet schöner Stil?



  • saveit schrieb:

    saveit schrieb:

    Pointer kommen leider erst im nächsten Kapitel. Muss mich erst mit den Übungsaufgaben rumschlagen. Leider gibt es dafür auch keine Lösungen.

    leider kann man das geschriebenen als Gast nich editieren, nun denn, was bedeutet schöner Stil?

    gerade gesehen.^^


  • Mod

    Skylac06 schrieb:

    Also:

    void sort_a(int *values);
    

    Dann auch bitte gleich noch mit irgendeiner Art Größeninformation. Kann ja nicht sein, dass man sonst später nur Felder mit genau 10 Elementen sortieren kann. Also entweder die Größe angeben, oder flexibler Anfang und Ende:

    void sort_a(int *begin, int *end)
    


  • So sieht er jetzt aus. Wurde alles beachtet was ihr geschrieben habt?

    #include <iostream>
    
    using namespace std;
    
    void sort_a(int *values)
        {
    
           int temp;
    
                    for (int i=0;i<10;i++)
                    {
                      for(int j=i+1;j<10;j++)
                        {
                            if(values[i]>values[j])
                                {
                                   temp=values[i];
                                   values[i]=values[j];
                                   values[j]=temp;
                                }
                        }
                        cout<<values[i]<<" | ";
                    }
    
        }
    
    int main()
    {
        int values[10]={23,11,67,3,9,0,28,30,21,15};
        cout <<"old array: ";
        for(int i=0;i<10;i++)
        {
          cout<<values[i]<<" | ";
        }
    
        cout << "\nnew array: ";
          sort_a(values);
    
    }
    


  • Ich habe mich versehen.
    Schlangenmensch meinte mit schönem Stil, dass globale Variablen, also Variablen, die nicht innerhalb einer Funktion deklariert werden, zu vermeiden sind.
    In deinem Fall kannst du zum Beispiel einfach die Variable temp in die Funktion sort_a() packen.
    Den Array kannst du nur in die main-Funktion packen, wenn du bereits Parameter gelernt hast.
    Ein (eindimensionaler) Array wird immer über den Arraynamen übergeben. Dieser entspricht &array[0]. Das kommt dann aber sicher im nächsten Kapitel.

    Außerdem solltest du dir vielleicht kleinere Abstände beim Einrücken angewöhnen und allgemein einen einheitlichen Schreibstil.

    Edit: fast.
    Die main-Funktion hat auch einen Rückgabewert. Deshalb muss auch die einen Wert zurückliefern, das ist normalerweise 0.
    Also einfach ein

    return 0;
    

    Als letzte Anweisung in die main-Funktion schreiben.
    Außerdem noch das Einrücken und dann sollte es passen.
    Ich persönlich habe es zudem noch immer lieber, wenn die Funktionsdefinition erst unterhalb der main-Funktion stattfindet, aber das ist vermutlich Geschmackssache (?).



  • Deshalb muss auch die einen Wert zurückliefern, das ist normalerweise 0.
    Also einfach ein
    return 0;

    no need. stört nur



  • unskilled schrieb:

    Deshalb muss auch die einen Wert zurückliefern, das ist normalerweise 0.
    Also einfach ein
    return 0;

    no need. stört nur

    Dann habe ich das falsch gelernt. Danke für die Korrektur. 🙂
    Aber sollte man dann nicht auch eher eine void main() benutzen?



  • Soweit habe ich hoffentlich alles übernommen Skylac06?

    void sort_a(int *begin, int *end)

    wie würde man das hier einbauen? habs probiert aber anscheinend falsch.

    #include <iostream>
    
    using namespace std;
    
    void sort_a(int *values)
        {
        int temp;
        for (int i=0;i<10;i++)
            {
            for(int j=i+1;j<10;j++)
                {
                if(values[i]>values[j])
                    {
                    temp=values[i];
                    values[i]=values[j];
                    values[j]=temp;
                    }
                }
            cout<<values[i]<<" | ";
            }
        }
    
    int main()
    {
        int values[10]={23,11,67,3,9,0,28,30,21,15};
        cout <<"old array: ";
        for(int i=0;i<10;i++)
            {
            cout<<values[i]<<" | ";
            }
        cout << "\nnew array: ";
        sort_a(values);
          return 0;
    
    }
    


  • Wie ich gerade selbst erst erfahren habe kannst du auch das return 0 weglassen. 🙄
    Falsch ist es aber nicht. 😉

    Du sollst einen Zeiger auf das erste Element des Arrays und einen auf das letzte übergeben, oder?
    Wie hast du das denn bisher versucht?



  • Copy and past, da mir zeiger noch unbekannt sind.^^



  • #include <iostream>
    
    using namespace std;
    
    void sort_a(int *begin, int *end);
    
    int main()
    {
    	int values[10] = { 23,11,67,3,9,0,28,30,21,15 };
    
    	cout << "old array: ";
    	for (int i = 0; i<10; i++)
    	{
    		cout << values[i] << " | ";
    	}
    
    	cout << endl << "new array: ";
    	sort_a(&values[0], &values[9]);
    
    	cin.get();
    	return 0;
    }
    
    void sort_a(int *begin, int *end)
    {
    	int temp;
    
    	for (int i = 0; i<10; i++)
    	{
    		for (int j = i + 1; j<10; j++)
    		{
    			if (*(begin + i) > *(begin + j))
    			{
    				temp = *(begin + i);
    				*(begin + i) = *(begin + j);
    				*(begin + j) = temp;
    			}
    		}
    		cout << *(begin + i) << " | ";
    	}
    }
    

    So würde ich das dann vermutlich machen.
    Aber wieso wird so eine Aufgabe von dir verlangt, wenn noch gar keine Zeiger behandelt wurden?

    Edit: vergessen int *end zu verwenden.
    So ist das eigentlich genau das gleiche wie oben.



  • Aber wieso wird so eine Aufgabe von dir verlangt, wenn noch gar keine Zeiger behandelt wurden?

    Das ist die Aufgabe.. Write a program that detects if a list is sorted or not, and if it is not sorted, sort it.



  • Das mit den Zeigern ist mir noch total unbekannt. Das übernächste Kapitel behandelt es aber.



  • Mir ist erst jetzt SeppJs Beitrag aufgefallen. Ich habe mich die ganze Zeit gefragt woher du dann das mit int *begin und int *end hast.
    Aber würde man wenn dann nicht eher die 10 als Konstante anlegen und die dann als Parameter mitgeben?
    Ansonsten halt so:

    void sort_a(int *begin, int *end)
    {
    	int temp;
    
    	int size = end - begin;
    
    	for (int i = 0; i <= size; i++)
    	{
    		for (int j = i + 1; j <= size; j++)
    		{
    			if (*(begin + i) > *(begin + j))
    			{
    				temp = *(begin + i);
    				*(begin + i) = *(begin + j);
    				*(begin + j) = temp;
    			}
    		}
    		cout << *(begin + i) << " | ";
    	}
    
    }
    

    Oder wie meinst du das, SeppJ?

    Edit: dann nimm jetzt erstmal wahlweise einen globalen Array oder nimm schon einmal die Informationen über Zeiger, die du jetzt hier gelesen hast.
    Das mit dem int *begin und int *end vergisst du bis zu dem entsprechenden Kapitel.
    Was du machen kannst, ist, dass du einen Integer anlegst mit der Arraygröße, bei dir also 10. Den übergibst du dann als zweiten Parameter.

    void sort_a(int *values, int arraysize)
    

    Wenn du schon Konstanten hast, dann kannst du den Integer von arraysize auch als Konstante nehmen.



  • Ich persönlich habe es zudem noch immer lieber, wenn die Funktionsdefinition erst unterhalb der main-Funktion stattfindet, aber das ist vermutlich Geschmackssache (?).

    Das geht aber nur, wenn die Deklaration schon vorher stattfindet.

    saveit schrieb:

    Das ist die Aufgabe.. Write a program that detects if a list is sorted or not, and if it is not sorted, sort it.

    Dann fehlt ja noch der Teil in dem du prüfst ob die Liste bereits sortiert ist.

    Wenn man sich die *begin, *end Notation angewöhnt, hat das den großen Vorteil, dass einem hinterher Iteratoren nicht mehr so schwer fallen, als wenn man am Anfang immer Startpunkt + größe übergibt.
    Aber das Lehrbuch auf den Kopf zu stellen wird auch nicht zielführend sein, da hat sich hoffentlich jemand was bei gedacht.


  • Mod

    Das begin/end-Schema ist später nützlich, wenn man sich mal nicht auf Arrays und Zeiger einschränken möchte:

    #include <iostream>
    using namespace std;
    
    void sort_a(int *begin, int *end)
    {
        for (int *i = begin; i != end; ++i)
        {
            for (int *j = i; j != end; ++j)
            {
                if (*i > *j)
                {
                    int temp = *i;
                    *i = *j;
                    *j = temp;
                }
            }
        }
    }
    
    int main() {
    	int values[10] = { 23,11,67,3,9,0,28,30,21,15 };
    	sort_a(begin(values), end(values));
    	for (auto i: values)
    		cout << i << '\n';
    }
    

    So habe ich als einzige Eigenschaft benutzt, dass man ++, =, != und * auf begin und end anwenden kann. Das ist aber etwas, das nicht exklusiv auf Zeiger beschränkt ist. Da könnte man nun ein Template draus machen, dass statt int* beliebige Typen zulässt, die ++, =, != und * können. Solche Objekte nennt man unter Programmierern "output iterator". Ein Zeiger ist ein output iterator, aber jede Menge andere Objekte auch, beispielsweise die Elemente einer verketteten Liste. Das heißt, man bekommt hier quasi geschenkt, dass man nun so ziemlich beliebige Container sortieren kann, die nur irgendwie ein Konzept von "von vorne nach hinten durchgehen" haben. Was so ziemlich alles ist, was man überhaupt sortieren kann.

    Warum nicht Anfang und Größe? Das ginge im Prinzip auch, aber man müsste irgendwann einmal begin + N berechnen, das heißt, begin müsste auch + können. Das ist eine Einschränkung, die nicht nötig ist, wie man oben sieht. Ein Objekt, das ++, =, !=, * und + kann, nennt man einen "random access iterator". Zeiger sind auch random access Iteratoren und alle random access Iteratoren sind auch output Iteratoren, aber nicht alle output Iteratoren sind auch random access Iteratoren. Beispielsweise sind die Elemente einer verketteten Liste keine random access Iteratoren. Man könnte dann also unnötigerweise keine verketteten Listen mehr sortieren.

    #include <iostream>
    #include <list>
    using namespace std;
    
    template<typename Iterator> void sort_a(Iterator begin, Iterator end)
    {
        for (Iterator i = begin; i != end; ++i)
        {
            for (Iterator j = i; j != end; ++j)
            {
                if (*i > *j)
                {
                    auto temp = *i;
                    *i = *j;
                    *j = temp;
                }
            }
        }
    }
    
    int main() {
    	// Geht mit Arrays:
    	int values[10] = { 23,11,67,3,9,0,28,30,21,15 };
    	sort_a(begin(values), end(values));
    	for (auto i: values)
    		cout << i << '\n';
    
    	// Geht mit list:
    	list<int> my_list = { 23,11,67,3,9,0,28,30,21,15 };
    	sort_a(begin(my_list), end(my_list));
    	for (auto i: my_list)
    		cout << i << '\n';
    }
    

Anmelden zum Antworten