Würde mich gern mal mit C befassen

Es gibt 196 Antworten in diesem Thema, welches 20.617 mal aufgerufen wurde. Der letzte Beitrag (24. Mai 2023 um 15:33) ist von Axellander.

  • Wer Pointer, Arrays und Strings verstanden hat, hat auch C verstanden.

    Und was ist mit Sequenzpunkten?

    10 x=rnd(-1963):fori=1to81:y=rnd(1):next
    20 forj=1to5:printchr$(rnd(1)*16+70);:next
    30 printint(rnd(1)*328)-217

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Ingo: Erstmal finde ich gut, daß ich / wir eine Rückmeldung bekommen.

    Ansonsten verstehe ich Dein "pf[2]" nicht. Was ist denn mit "pf[0]" und "pf[1]"? Und welcher Datentyp ist "pf", und wo wurde der deklariert?

    Das, was man hinter die struct-Definition schreibt, ist sozusagen der Name einer bestimmten struct. Also erst beschreibt man die allgemeine Definition der Struktur unter dem Namen "struct person" (Warum "person" klein? Ich würde das wie einen Klassennamen groß schreiben).

    Und dann wie gesagt, der Name einer bestimmten struct, wie in der OOP der Name eines bestimmten Objekts. Hier war das Beispiel, das ich mal hatte:

    Code
    struct Fruit {
        char colour[10];
    } apple, banana;

    Und "pf[2]" finde ich da einen wirklich seltsamen Namen. Das sieht nicht gut aus.

    Und warum machst Du das alles über Zeiger? Das macht es doch viel komplizierter, als es sein müßte.

    Also, ja, es läuft, aber ich bin nicht sicher, ob Du schon so genau weißt, was Du tust (was ja bei C auch immer ein Problem ist). ;) Aber wird schon.

  • Was ist denn mit "pf[0]" und "pf[1]"? Und welcher Datentyp ist "pf", und wo wurde der deklariert?

    pf bzw. pf[] ist ein Array von person-Structs. In C ist es ja möglich, bei einer struct-Deklaration auch Variablen mitzudefinieren. struct person{ ... } pf[2] definert also auch das Array pf[] mit 2 Elementen, auf die mit pf[0] und pf[1] zugegriffen werden kann.

    Eine längere Version wäre:

    Code
    typedef struct person person;
    struct person {
        char name[20];
        int alter;
        person *vater;
    };
    person pf[2];
  • Was ist denn mit "pf[0]" und "pf[1]"? Und welcher Datentyp ist "pf", und wo wurde der deklariert?

    pf bzw. pf[] ist ein Array von person-Structs. In C ist es ja möglich, bei einer struct-Deklaration auch Variablen mitzudefinieren. struct person{ ... } pf[2] definert also auch das Array pf[] mit 2 Elementen, auf die mit pf[0] und pf[1] zugegriffen werden kann.

    Eine längere Version wäre:

    Code
    typedef struct person person;
    struct person {
        char name[20];
        int alter;
        person *vater;
    };
    person pf[2];

    Ja so hatte ich das auch verstanden.

    Macht das mit dem Zeiger p auf das Feld pf (soll wohl für personFeld stehen) denn nicht Sinn? Ansonsten müßte man das Feld über Indizes ansprechen.

    Übrigens hatte ich das Beispiel von hier: Bitte melde dich an, um diesen Link zu sehen.. Am Ende ist eine Nutzungsmöglichkeit als Ahnentafel. Mit der Zeigerarithmetik könnte man den Baum dann rekursiv durchsuchen. Wollte das mal als Übung machen.

    (Warum "person" klein? Ich würde das wie einen Klassennamen groß schreiben).

    Und dann wie gesagt, der Name einer bestimmten struct, wie in der OOP der Name eines bestimmten Objekts

    Ich dachte, dass ein struct eher so verstanden werden kann, wie ein neuer Datentyp und nicht wie eine Klasse in der OOP, deshalb würde das auch klein geschrieben. Ich hatte das bis jetzt auch nur klein geschrieben gesehen.

    Also, ja, es läuft, aber ich bin nicht sicher, ob Du schon so genau weißt, was Du tust (was ja bei C auch immer ein Problem ist). ;) Aber wird schon.

    Da könntest du recht haben. Manchmal denke ich, so langsam lichtet sich der Dschungel und im nächsten Moment kapier ich dann wieder gar nix mehr... :)

  • Macht das mit dem Zeiger p auf das Feld pf (soll wohl für personFeld stehen) denn nicht Sinn?

    Doch, das klappt, weil der reine Name eines Arrays (ohne die eckigen Klammern) auf das erste Arrayelement zeigt.

    Deshalb könnte man die obige Zeile

    person *p = pf;

    auch so schreiben

    person *p = &(pf[0]);

  • "Ein Array ist ein Pointer, und ein Pointer ist ein Array."

    Gefährlicher Spruch... Bitte melde dich an, um diesen Link zu sehen. vs. Bitte melde dich an, um diesen Link zu sehen.

    10 x=rnd(-1963):fori=1to81:y=rnd(1):next
    20 forj=1to5:printchr$(rnd(1)*16+70);:next
    30 printint(rnd(1)*328)-217

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Ich weiß ja nicht, wie genau die Aufgabenstellung ist, aber von der Idee her würde ich das einfach so modellieren:

    No pointers needed. ;)

    K&R schreiben struct-Namen tatsächlich klein, das ist richtig.

  • Ich weiß ja nicht, wie genau die Aufgabenstellung ist, aber von der Idee her würde ich das einfach so modellieren:

    No pointers needed. ;)

    Ja, man kann natürlich auch statische Initialisierung verwenden. Kommt drauf an was man machen will. Ich hatte das so verstanden das jemand C lernen will, insofern ist die Benutzung der Pointer durchaus sinnvoll. Schliesslich arbeitet man in einem "echten" Programm in der Regel nicht nur mit statischen Strukturen, sondern mit dynamischen. Also sollte man schon verstehen wie man Pointer benutzt.

    Da das aber ein triviales Beispielprogramm zum lernen ist, kann man es so oder so machen, je nachdem was man ausprobieren will.

  • Da das aber ein triviales Beispielprogramm zum lernen ist, kann man es so oder so machen, je nachdem was man ausprobieren will.

    Es scheint aber auch nicht beliebig zu sein, was das Programm machen soll. Da gibt es einen Vater und einen Sohn, die haben Namen und Alter, und diese Daten sollen ausgegeben werden. Und zwar in C, mit Hilfe einer Struktur.

    Dabei versucht man zu lernen, wie Strukturen funktionieren.

    Das macht mein Vorschlag alles.

    Was das mit den Zeigern dann noch soll, ist mir nicht klar. Soll die Beziehung zwischen den "Objekten" (Vater - Sohn) in der Struktur gespeichert werden? Dann würde man z.B. sowas wie eine "verkettete Liste" anlegen, eben mit Zeigern, die auf das jeweils nächste "Objekt", den nächsten "Knoten" verweisen ("Bitte melde dich an, um diesen Link zu sehen."). Was das ursprüngliche Beispiel ja auch andeutet. Das wäre aber ein ganz anderes Thema, und solche Lernprogramme sollten eigentlich erstmal nur bei einem Thema bleiben.

  • Zusatzfrage: WIe trennt man eigentlich begrifflich die Strukturbeschreibung ("struct person") von den "Objekten" ("vater"). In der OOP nennt man das eine ja "Klasse", das andere "Objekt". Wie ist das bei C-Strukturen, wie nennt man das da?

  • WIe trennt man eigentlich begrifflich die Strukturbeschreibung ("struct person") von den "Objekten" ("vater").

    Aus der deutschen Ausgabe von K&R, Programmieren in C, Zweite Ausgabe:

    Zitat

    Wir unterscheiden zwei Arten von Vereinbarungen:

    * Definitionen, die Objekte erzeugen, und

    * Deklarationen, die nur die Eigenschaften von Objekten festlegen.

  • Ne, Definition und Deklaration ist die jeweilige Beschreibung im Sourcecode. Ich würde in C von Typ (struct person) und Instanz (vater) sprechen.

    ────────────────────────────────────────────────────────────
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    ────────────────────────────────────────────────────────────

  • Zusatzfrage: WIe trennt man eigentlich begrifflich die Strukturbeschreibung ("struct person") von den "Objekten" ("vater"). In der OOP nennt man das eine ja "Klasse", das andere "Objekt". Wie ist das bei C-Strukturen, wie nennt man das da?

    Das sind auch in C Objekte. Siehe Bitte melde dich an, um diesen Link zu sehen. §3.14.

    Den Begriff "Instanz" einer Klasse, Struktur usw. (im Gegensatz zur Deklaration dergleichen) gibt es auch.

  • Was das mit den Zeigern dann noch soll, ist mir nicht klar. Soll die Beziehung zwischen den "Objekten" (Vater - Sohn) in der Struktur gespeichert werden? Dann würde man z.B. sowas wie eine "verkettete Liste" anlegen, eben mit Zeigern, die auf das jeweils nächste "Objekt", den nächsten "Knoten" verweisen ("Bitte melde dich an, um diesen Link zu sehen."). Was das ursprüngliche Beispiel ja auch andeutet. Das wäre aber ein ganz anderes Thema, und solche Lernprogramme sollten eigentlich erstmal nur bei einem Thema bleiben.

    Welche Beziehung die Objekte untereinernander haben ist ja etwas anderes, als wie man sie speichert. Das hängt dann von den Anforderungen ab. Eine Person ist eine Datenstruktur ohne besondere Bedeutung. Eine Vater-Sohn Beziehung dagegen ist ja eher die "Businesslogik". Da weist du also den Personen bestimmte Rollen zu die sie miteinander verbinden. Wenn du z.B. eine verkette Liste verwendest und sagst dass die Liste eine Vater-Sohn Beziehung abbildet dann ist das ja quais einen Ahnenreihe. Das ist etwas anders als wenn du vieleverschiedene Personen in einer List speicherst von denen dann einige eine spezielle Beziehung haben. Das Problem bei so trivialen Beispielen ist, dass sie zu wenig Fleisch haben um eine Aussage machen zu können wie etwas vernünftig abgebildet wird. Du hast halt nur einen Sohn und einen Vater und den kann man in beliebigen Strukturen ablegen und begründen warum das eine gute Struktur ist um diese Beziehung abzubilden. Aber um darüber eine Aussage machen zu können müsste man etwas mehr Beispiele haben um zu sagen wie man die Daten am Besten organisert.

  • Wenn du z.B. eine verkette Liste verwendest und sagst dass die Liste eine Vater-Sohn Beziehung abbildet dann ist das ja quais einen Ahnenreihe. Das ist etwas anders als wenn du vieleverschiedene Personen in einer List speicherst von denen dann einige eine spezielle Beziehung haben. Das Problem bei so trivialen Beispielen ist, dass sie zu wenig Fleisch haben um eine Aussage machen zu können wie etwas vernünftig abgebildet wird. Du hast halt nur einen Sohn und einen Vater und den kann man in beliebigen Strukturen ablegen und begründen warum das eine gute Struktur ist um diese Beziehung abzubilden. Aber um darüber eine Aussage machen zu können müsste man etwas mehr Beispiele haben um zu sagen wie man die Daten am Besten organisert.

    Ja, genau. Eigentlich wäre eine Baumstruktur passender, da ein Elter ja mehrere Kinder haben kann. =)

  • In dem Beispiel Bitte melde dich an, um diesen Link zu sehen. macht das obere für sich gesehen wenig Sinn, das stimmt schon.

    Aber für mich war es sehr lehrreich. Ich wollte unbedingt verstehen, wie das funktioniert, es hat mir einfach keine Ruhe gelassen und habe dabei sehr viel gelernt.

    Und ich glaube, nichts anderes wollte man hier erreichen.

    Ich habe mich nun dem Stammbaum auf dieser Seite gewidmet und ein bisschen rumprogrammiert. Das ist dabei rausgekommen:

    Zuerst werden die Daten aus der Datei "Daten.txt" gelesen und in die Personenstruktur eingetragen.

    Dann werden sie ausgegeben. Einmal per Indizierung und (auskommentiert) über den Pfeiloperator.

    Anschließend suche ich nach einem Namen. Dies geschieht in der Funktion "sucheName".

    Hierin wird die Baumstruktur rekursiv durchsucht.

  • Kleine Anmerkung zu dem Block in Zeile 37.

    1. Du setzt voraus das die Eingabedatei genau 15 Personen enthält.

    Wenn die Datei weniger als 15 enthält dann gibst du bei der Ausgabe in Zeile 51 trotzdem das volle Array aus, auch wenn das nicht vorhanden ist.

    Wenn die Datei mehr als 15 Personen enthält dann überschreibst du das Array (array overflow)

    Wenn die Datei "krumm" ist (z.B. 16 Personen), dann gibst du den Vater nicht aus (obwohl er bekannt wäre) weil die Mutter dann fehlt.

    2. Die Variable j wird eigentlich nicht gebraucht. j ist in deinem Beispiel IMMER i+1 für den Vater und i+2 für die Mutter. Du könnstest also genausogut eine lokale Variable "int elternteil = i+1; ... elternTeil++;" verwenden. Das macht dann die Berechnung des Index einfacher und verständlicher als der Ausdruck "i-(j+1)". Ausserdem hat das den Vorteil dass du eine Variable weniger in der Funktion hast, die eigentlich nur an dieser Stelle benötigt wird.

    Variablen sollten möglichst begrenzt in ihrem Scope sein, dadurch vermeidet man "seltsame" Fehler.