Zeiger Verständnis



  • CrispyTurtleAlligator schrieb:

    Mal angenommen ich tippe nun das Wort "Programm" ein. Dann wird demnach das P in ascii[0], das r in ascii[1], ..., aufrufbar sein.

    Nein, das ist falsch.

    CrispyTurtleAlligator schrieb:

    Für mich stellt sich dann die Frage, warum?

    //Count
        for(ptr = string; *ptr != '\0'; ptr++) {
            ascii[*ptr]++;
        }
    

    ptr zeigt ja zuerst auf das P. Daraufhin steht doch eigentlich in den Klammern des Arrays ascii ein P bzw. eine 80, laut der ASCII Tabelle. Oder liege ich hier erneut falsch?

    Soweit richtig. (Besser: es ist ein 'P'. Die einfachen Hochkommas kennzeichnen das Zeichen)

    CrispyTurtleAlligator schrieb:

    Ich sehe hier einfach keinen Zusammenhang, warum dann das P über ascii[0] und nicht über ascii[80] aufrufbar ist. Ich stelle mich glaube ich gerade einfach nur dämlich an.

    Deine erste Annahme ist ja falsch.
    Bei einer falschen Annahme kannst du mit Logik nicht weiter machen. Es kommt was falsches raus.
    In ascii['P'] bzw. ascii[80] steht auch kein P. Da steht die Anzahl des Vorkommens von 'P' in deinem Text drin.

    Du hast ein https://de.wikipedia.org/wiki/Histogramm von deinem Text. (Die Klassenbreite ist ein Zeichen)



  • Ich bin davon ausgegangen, weil mir Xcode folgendes ausspuckt, siehe Bild auf Link. http://fs2.directupload.net/images/150820/4hyvt4n9.png

    Dabei geht es aber wohl eher darum, dass das P in string[0], r in string[1], ... steht.

    In den Klammern steht als tatsächlich ein 'P', daraufhin ein 'r', ..., 'm'. Sämtliche Werte wurden ja zuvor gleich 0 gesetzt, da ja ansonsten nicht richtig gezählt wird. Somit hat eben das 'P' bzw. die 80 eben den Wert 0, richtig? Und sobald der Buchstabe einmal vorhanden ist, wird durch das ascii[*ptr]++ der Wert um eins erhöht. Wenn das nun alles so richtig ist, dann bin ich damit zufrieden und bedanke mich bei allen für die Hilfsbereitschaft und die Geduld mit mir. 🙂


  • Mod

    CrispyTurtleAlligator schrieb:

    Dabei geht es aber wohl eher darum, dass das P in string[0], r in string[1], ... steht.

    Nicht "eher darum", sonder es geht darum! Dir ist schon klar, dass string und ascii zwei ganz unterschiedliche Arrays sind?

    In den Klammern steht als tatsächlich ein 'P', daraufhin ein 'r', ..., 'm'. Sämtliche Werte wurden ja zuvor gleich 0 gesetzt, da ja ansonsten nicht richtig gezählt wird. Somit hat eben das 'P' bzw. die 80 eben den Wert 0, richtig? Und sobald der Buchstabe einmal vorhanden ist, wird durch das ascii[*ptr]++ der Wert um eins erhöht.

    Tut mir leid, aber das ist kompletter Blödsinn. Ich komme mir so langsam verarscht vor.



  • SeppJ schrieb:

    CrispyTurtleAlligator schrieb:

    Dabei geht es aber wohl eher darum, dass das P in string[0], r in string[1], ... steht.

    Nicht "eher darum", sonder es geht darum! Dir ist schon klar, dass string und ascii zwei ganz unterschiedliche Arrays sind?

    In den Klammern steht als tatsächlich ein 'P', daraufhin ein 'r', ..., 'm'. Sämtliche Werte wurden ja zuvor gleich 0 gesetzt, da ja ansonsten nicht richtig gezählt wird. Somit hat eben das 'P' bzw. die 80 eben den Wert 0, richtig? Und sobald der Buchstabe einmal vorhanden ist, wird durch das ascii[*ptr]++ der Wert um eins erhöht.

    Tut mir leid, aber das ist kompletter Blödsinn. Ich komme mir so langsam verarscht vor.

    Warum ist das kompletter Blödsinn?

    //Read user input
        printf("Geben Sie etwas ein: ");
        scanf("%s", string);
    

    Dadurch wird eine Eingabe erwartet. Die Eingabe wird anschließend durch die Variable string aufrufbar sein.

    //Every element of ascii code has counter value, first 0
        for(i = 0; i < 256; i++) {
            ascii[i] = 0;
        }
    

    Hier wird der Wert von ascii[0], ascii[1], ... auf 0 gesetzt.

    //Count
        for(ptr = string; *ptr != '\0'; ptr++) {
            ascii[*ptr]++;
        }
    

    Bei der Eingabe von 'Programm' zeigt ptr nun zuerst auf das P. Wenn dieses ungleich \0 ist, dann wird der Wert für ascii['P'] um eins erhöht. Dann wird durch das ptr++ von 'P' weiter zu 'r' gegangen.



  • CrispyTurtleAlligator schrieb:

    Warum ist das kompletter Blödsinn?

    Er hat es doch bereits geschrieben - string und ascii sind zwei unterschiedliche Arrays. Und der Wert der Zelle des einen Arrays wird wiederum als Index für das zweite Array verwendet. Und darauf wird dann inkrementiert.

    Der Code durchsucht ja den String nach der Häufigkeit der Buchstaben, deswegen wird der Wert des Buchstaben als Index verwendet. Anfangen tust du mit der Häufigkeit 0 für alle Buchstaben. Und das Inkrementiert sich dann halt je nachdem, welcher Index verwendet wird.


  • Mod

    CrispyTurtleAlligator schrieb:

    SeppJ schrieb:

    CrispyTurtleAlligator schrieb:

    Dabei geht es aber wohl eher darum, dass das P in string[0], r in string[1], ... steht.

    Nicht "eher darum", sonder es geht darum! Dir ist schon klar, dass string und ascii zwei ganz unterschiedliche Arrays sind?

    In den Klammern steht als tatsächlich ein 'P', daraufhin ein 'r', ..., 'm'. Sämtliche Werte wurden ja zuvor gleich 0 gesetzt, da ja ansonsten nicht richtig gezählt wird. Somit hat eben das 'P' bzw. die 80 eben den Wert 0, richtig? Und sobald der Buchstabe einmal vorhanden ist, wird durch das ascii[*ptr]++ der Wert um eins erhöht.

    Tut mir leid, aber das ist kompletter Blödsinn. Ich komme mir so langsam verarscht vor.

    Warum ist das kompletter Blödsinn?

    Weil es nicht das ist, was passiert und es völlig unverständlich ist, wie du überhaupt da drauf gekommen bist.

    //Read user input
        printf("Geben Sie etwas ein: ");
        scanf("%s", string);
    

    Dadurch wird eine Eingabe erwartet. Die Eingabe wird anschließend durch die Variable string aufrufbar sein.

    //Every element of ascii code has counter value, first 0
        for(i = 0; i < 256; i++) {
            ascii[i] = 0;
        }
    

    Hier wird der Wert von ascii[0], ascii[1], ... auf 0 gesetzt.

    //Count
        for(ptr = string; *ptr != '\0'; ptr++) {
            ascii[*ptr]++;
        }
    

    Bei der Eingabe von 'Programm' zeigt ptr nun zuerst auf das P. Wenn dieses ungleich \0 ist, dann wird der Wert für ascii['P'] um eins erhöht. Dann wird durch das ptr++ von 'P' weiter zu 'r' gegangen.

    Diese Beschreibung ist 100% richtig. Wenn du sie mit dem vergleichst, was ich "vollkommenen Blödsinn" schimpfte, wirst du feststellen, dass sie völlig unterschiedlich sind.

    Falls du mit dem "vollkommenen Blödsinn" bereits das gleiche ausdrücken wolltest: Hast du nicht. Und da in der Programmierung, wie schon erklärt, jedes einzelne Zeichen wichtig ist, tendieren viele Programmierer dazu, auch im Alltag so zu denken. Man muss sich eben ganz genau und korrekt ausdrücken. Aber hier ist das nicht einmal der Fall, ich bin schließlich gewohnt, dass Leute sich manchmal ungenau ausdrücken. Aber ich kann nicht einmal im Ansatz erkennen, wie du mit deiner ersten Beschreibung vielleicht den richtigen Sachverhalt ungeschickt ausgedrückt haben könntest. Daher habe ich die Beschreibung "vollkommenen Blödsinn" genannt.



  • dachschaden schrieb:

    CrispyTurtleAlligator schrieb:

    Warum ist das kompletter Blödsinn?

    Er hat es doch bereits geschrieben - string und ascii sind zwei unterschiedliche Arrays. Und der Wert der Zelle des einen Arrays wird wiederum als Index für das zweite Array verwendet. Und darauf wird dann inkrementiert.

    Der Code durchsucht ja den String nach der Häufigkeit der Buchstaben, deswegen wird der Wert des Buchstaben als Index verwendet. Anfangen tust du mit der Häufigkeit 0 für alle Buchstaben. Und das Inkrementiert sich dann halt je nachdem, welcher Index verwendet wird.

    Ja, ich habe doch zugegeben, dass ich mich da vertan habe. In dem letzten Beitrag und vor allem in dem Bereich, den er zitiert hat, war aber gar nicht mehr die Rede davon. In dem Zitat ist von string gar keine Rede mehr, sondern nur von dem ASCII Array.



  • SeppJ schrieb:

    Falls du mit dem "vollkommenen Blödsinn" bereits das gleiche ausdrücken wolltest: Hast du nicht. Und da in der Programmierung, wie schon erklärt, jedes einzelne Zeichen wichtig ist, tendieren viele Programmierer dazu, auch im Alltag so zu denken. Man muss sich eben ganz genau und korrekt ausdrücken. Aber hier ist das nicht einmal der Fall, ich bin schließlich gewohnt, dass Leute sich manchmal ungenau ausdrücken. Aber ich kann nicht einmal im Ansatz erkennen, wie du mit deiner ersten Beschreibung vielleicht den richtigen Sachverhalt ungeschickt ausgedrückt haben könntest. Daher habe ich die Beschreibung "vollkommenen Blödsinn" genannt.

    Dann bedanke ich mich mal dafür, dass du das so eng siehst, damit ich mich in der Hinsicht verbessere. 😉



  • Moin!
    Ich will auch noch zur Verwirrung beitragen. 🙂

    @CrispyTurtleAlligator:

    Die Ausgabe dieses Programms kannst Du nachvollziehen?

    #include <stdio.h>
    
    #define HISTSIZE 6
    
    int main(void){
      int arr[] = { 3,3,  5,5,5,5,5,5,5,5,5,5,5,5,5,  1,1,1,  -1 };
    
      int histogram[HISTSIZE]={0};
      for(int* ptr=arr; *ptr!=-1; ++ptr)
        ++histogram[*ptr];
    
      for(int i=0; i<HISTSIZE; ++i)
        printf("Zahl %d, Haeufigkeit: %d\n", i, histogram[i]);
    }
    
    Zahl 0, Haeufigkeit: 0
    Zahl 1, Haeufigkeit: 3
    Zahl 2, Haeufigkeit: 0
    Zahl 3, Haeufigkeit: 2
    Zahl 4, Haeufigkeit: 0
    Zahl 5, Haeufigkeit: 13
    


  • Furble Wurble schrieb:

    Moin!
    Ich will auch noch zur Verwirrung beitragen. 🙂

    @CrispyTurtleAlligator:

    Die Ausgabe dieses Programms kannst Du nachvollziehen?

    #include <stdio.h>
    
    #define HISTSIZE 6
    
    int main(void){
      int arr[] = { 3,3,  5,5,5,5,5,5,5,5,5,5,5,5,5,  1,1,1,  -1 };
    
      int histogram[HISTSIZE]={0};
      for(int* ptr=arr; *ptr!=-1; ++ptr)
        ++histogram[*ptr];
    
      for(int i=0; i<HISTSIZE; ++i)
        printf("Zahl %d, Haeufigkeit: %d\n", i, histogram[i]);
    }
    
    Zahl 0, Haeufigkeit: 0
    Zahl 1, Haeufigkeit: 3
    Zahl 2, Haeufigkeit: 0
    Zahl 3, Haeufigkeit: 2
    Zahl 4, Haeufigkeit: 0
    Zahl 5, Haeufigkeit: 13
    
    int arr[] = { 3,3,  5,5,5,5,5,5,5,5,5,5,5,5,5,  1,1,1,  -1 };
    

    Das legt ein Array fest, welches keine Anzahl der Elemente in den eckigen Klammern benötigt, weil C das automatisch anhand der Anzahl der Elemente in den geschweiften Klammern macht.

    int histogram[HISTSIZE]={0};
      for(int* ptr=arr; *ptr!=-1; ++ptr)
        ++histogram[*ptr];
    

    Dadurch wird ein Array mit 6 Elementen initialisiert. Die Werte dieser Elemente werden allesamt auf 0 gesetzt. Daraufhin zeigt der Zeiger auf die erste 3 aus arr[]. Solange der Wert, auf den der Pointer zeigt ungleich -1 ist, wird die for-Schleife weiter durchgeführt. In der Schleife wird zuerst der Wert von histogram[3], ... um eines erhöht. Die -1 in arr[]; dient dazu, um der Schleife ein Ende zu verpassen.

    Schließlich wird mit einer weiteren Schleife das im Programm erarbeitete ausgegeben.

    Korrekt? Was kann man besser formulieren?



  • Perfekt.

    Dementsprechend ist das auch klar?

    #include <stdio.h>
    
    #define HISTSIZE 127
    
    int main(void){
      char arr[] = { 'H', 'a', 'l', 'l', 'o', 0 };
      int histogram[HISTSIZE]={0};
    
      for(char* ptr=arr; *ptr!=0; ++ptr)
        ++histogram[*ptr];
    
      for(int i=0; i<HISTSIZE; ++i)
        printf("Zahl %d, Haeufigkeit: %d\n", i, histogram[i]);
    }
    

    Zur Kontrolle die ASCII Tabelle auf Wikipedia.

    Der Ablauf ist natürlich derselbe. Bist Du jetzt überrascht wg. der Ausgabe?



  • Warum sollte ich überrascht sein? Vielleicht, weil anstelle von Buchstaben die Häufigkeit von Zahlen ausgegeben wird? Das liegt an dem %d, welches anstelle von dem %c genutzt wird. Übrigens danke für die Mühe, mir das zu verdeutlichen. 😉



  • Als ich den Thread gestern Abend entdeckt habe, dachte ich da sei noch Erklärungsbedarf.
    Wenn ich mir den Thread heute allerdings bei Lichte betrachte, hattest Du's ja schon geschnallt gehabt, bevor ich überhaupt in die Diskussion eingestiegen bin...ein wenig überflüssig also...

    Naja...war mir ein Vergnügen! 🙂



  • Nochmal eine Frage bezüglich der Zeiger:

    /* struct3.c */
    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 30
    
    struct adres {
       char vname[MAX];
       char nname[MAX];
       long PLZ;
       char ort[MAX];
       int geburtsjahr;
    } adressen;
    
    /* Funktion zur Ausgabe des Satzes */
    void ausgabe(struct adres *struct_ptr) {
       printf("\n\nSie gaben ein:\n\n");
       printf("Vorname.........:%s",(*struct_ptr).vname);
       printf("Nachname........:%s",(*struct_ptr).nname);
       printf("Postleitzahl....:%ld\n",(*struct_ptr).PLZ);
       printf("Ort.............:%s",(*struct_ptr).ort);
       printf("Geburtsjahr.....:%d\n",(*struct_ptr).geburtsjahr);
    }
    
    int main(void) {
       printf("Vorname      : ");
       fgets(adressen.vname, MAX, stdin);
       printf("Nachname     : ");
       fgets(adressen.nname, MAX, stdin);
       printf("Postleitzahl : ");
       do {
          scanf("%5ld",&adressen.PLZ);
       } while(getchar()!= '\n');
       printf("Wohnort      : ");
       fgets(adressen.ort, MAX, stdin);
       printf("Geburtsjahr  : ");
       do {
          scanf("%4d",&adressen.geburtsjahr);
       } while(getchar()!='\n' );
    
       ausgabe(&adressen);
       return EXIT_SUCCESS;
    }
    

    Speziell hierum geht es:

    void ausgabe(struct adres *struct_ptr) {
       printf("\n\nSie gaben ein:\n\n");
       printf("Vorname.........:%s",(*struct_ptr).vname);
       printf("Nachname........:%s",(*struct_ptr).nname);
       printf("Postleitzahl....:%ld\n",(*struct_ptr).PLZ);
       printf("Ort.............:%s",(*struct_ptr).ort);
       printf("Geburtsjahr.....:%d\n",(*struct_ptr).geburtsjahr);
    }
    

    Dabei gehts es mir um den Inhalt zwischen den Klammern nach void ausgabe . Hier wird eine Struktur mit der Bezeichnung struct_ptr (als Pointer) des Typs adres erzeugt. Richtig?


  • Mod

    Wo hast du ständig diese Schrottbeispiele her? Schreibst du die selber? Wohl kaum, sonst würdest du sie ja verstehen. Also wohl aus irgendeinem Internettutorial. Bestätigt alle Vorurteile gegen Internettutorials. Egal, wo auch immer du das her hast: Finger weg!



  • CrispyTurtleAlligator schrieb:

    Hier wird zuerst das struct adres in die Funktion ausgabe übergeben. Dann

    .... dann ward abgebrochen. 🙂

    struct_ptr ist ein Pointer auf ein struct adres . Kein Objekt, sondern ein Pointer. Um auf die Elemente (vname, nname, PLZ, usw ...) zugreifen zu können, muss der Pointer erst dereferenziert werden - sprich, das Objekt, auf den der Pointer zeigt, muss geladen werden. Das passiert in den (*struct_ptr) -Blöcken.

    Übrigens schreibt man das so nicht. Gebräuchlicher ist diese Syntax:

    printf("\n\nSie gaben ein:\n\n");
       printf("Vorname.........:%s",struct_ptr->vname);
       printf("Nachname........:%s",struct_ptr->nname);
       printf("Postleitzahl....:%ld\n",struct_ptr->PLZ);
       printf("Ort.............:%s",struct_ptr->ort);
       printf("Geburtsjahr.....:%d\n",struct_ptr->geburtsjahr);
    

    Der ->-Operator macht das gleiche - Dereferenzierung und dann Zugriff auf das spezifizierte Element. Auch so eine Sache, die die Lesbarkeit um über 9000 Prozent steigert - vor allem dann, wenn du richtig komplizierten Code schreiben musst irgendwann, wo du über etliche Objekte auf Schlüsseljagd bist, immer auf der Suche nach dem nächsten Wert.

    SeppJ schrieb:

    Wo hast du ständig diese Schrottbeispiele her?

    Kann auch sein, dass er die von seinem Prof hat. Und dass die gerne mal an der Praxis vorbei lehren, sollte hier eigentlich bekannt sein. 😉



  • SeppJ schrieb:

    Wo hast du ständig diese Schrottbeispiele her? Schreibst du die selber? Wohl kaum, sonst würdest du sie ja verstehen. Also wohl aus irgendeinem Internettutorial. Bestätigt alle Vorurteile gegen Internettutorials. Egal, wo auch immer du das her hast: Finger weg!

    C von A bis Z von Galileo Computing. Viele Sachen sind dort mangelhaft erklärt und auch falsch, deshalb auch die häufigen Fragen. Sobald das neue Monat kommt, steht ein neues Buch an, damit ich euch damit nicht mehr Quäle. 😉

    Ist denn meine Erklärung wenigstens richtig?



  • CrispyTurtleAlligator schrieb:

    C von A bis Z von Galileo Computing.

    Nuff said. Wirf es weg. JETZT!

    Nein, keine Debatte. JETZT!



  • dachschaden schrieb:

    CrispyTurtleAlligator schrieb:

    C von A bis Z von Galileo Computing.

    Nuff said. Wirf es weg. JETZT!

    Nein, keine Debatte. JETZT!

    🙄 😃

    Ay ay, Captain! 😉



  • Wennde mir nicht glauben willst: Klick!


Anmelden zum Antworten