Zeiger Verständnis
-
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
undascii
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
undascii
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
undascii
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.
-
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
undascii
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
undascii
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.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.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 Bezeichnungstruct_ptr
(als Pointer) des Typsadres
erzeugt. Richtig?
-
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 Funktionausgabe
übergeben. Dann.... dann ward abgebrochen.
struct_ptr
ist ein Pointer auf einstruct 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!
-
dachschaden schrieb:
Wennde mir nicht glauben willst: Klick!
Doch doch, ich glaub das schon. Ich hab das ja öfters schon gelesen. Alles, was ich in dem Buch lese, hinterfrage ich auch zig mal um mir möglichst nichts falsches anzueignen. Aber danke für die Warnung. Womit hast du persönlich gelernt?
-
Mit einem C++-Buch. Irgendein Markt+Technik Dingens, was billiges aus der Stadtbibliothek. Würde ich heute nicht mehr mit der Kneifzange anfassen, vor allem deswegen, weil auf neue Features von C++ nie Rücksicht genommen wurde.
Später bin ich dann von Windows auf Linux gewechselt, und habe erst mal gestaunt, wie schnell C im Vergleich kompiliert. Zuerst war C++ immer noch einfacher für mich, weil mir die ganzen C-Fallstricke nicht bekannt waren - während ich heute nicht mal mehr darüber nachdenke.
Wenn du wirklich C lernen willst: installiere Linux und lies dir während des Programmierens die man-pages durch, aber übernehme keinen direkten Code aus ihnen. So habe ich nach C++ und Perl einigermaßen erfolgreich C gelernt.
Der Grund, warum du nicht direkt Code aus den man-pages übernehmen solltest, ist weil dieser meist aus antiken Zeiten stammt, schlecht formatiert ist und noch weniger gut kommentiert. Halte dich stur an die Text-Passagen, und schau dir den Code nur dann an, wenn du wirklich absolut nix verstehst.