C lernen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Benutzeravatar
BigR
Beiträge: 17
Registriert: 03.08.2024 00:05:56

Re: C lernen

Beitrag von BigR » 18.10.2024 13:07:15

Ich habe C nach Herbert Schildt gelernt, K und R gab es damals auch war aber auch schon alt. Wer sich für Linux Programmierung interessiert, ich habe ein Buch Linux Programmierung, da lernt man make und wie man man Pages schreibt. An sonsten würde ich freie Unterlagen im Internet suchen, die sind auch nicht schlecht. Für Fortgeschrittene ist Literatur über C Systemprogrammierung zu empfehlen.

Benutzeravatar
ralli
Beiträge: 4380
Registriert: 02.03.2008 08:03:02

Re: C lernen

Beitrag von ralli » 29.10.2024 11:06:21

Ihr habt mich angesteckt, jetzt bin ich auch dabei. Hier habe ich ein kostenloses Online Tutorial gefunden:

https://www.c-howto.de/

Wem das nicht reicht, der kann sich auch die Print Ausgabe in gedruckter Form als Buch bestellen.

Gruß ralli

TuxPeter
Beiträge: 2020
Registriert: 19.11.2008 20:39:02
Lizenz eigener Beiträge: MIT Lizenz

Re: C lernen

Beitrag von TuxPeter » 29.10.2024 15:55:34

Hi,
den Start von https://www.c-howto.de/ finde ich ein wenig ermüdend. Habe jetzt begonnen, meine Nase in das Kernighan-Ritchie-Werk zu stecken und bin davon recht angetan. Zwei Dinge haben mich bis jetzt verwundert.

1. Funktionsergebnisse können nicht nur elementare Werte sein, sonder auch Strukturen und Unionen als Ergebnis liefern. Das gab's in Pascal nicht! Oder doch? Probiert und siehe da, in FreePascal funktioniert auch ein Record als Fuktionstyp. Sollte mir das damals entgangen sein? Aber nein, mit TurboPascal in der Dosbox probiert, geht nicht. Zum Glück, wäre ja peinlich.

2. Folgendes simple Beispielprogramm (hier auf S.17):

Code: Alles auswählen

#include <stdio.h>
void main () {
int c;
while ((c = getchar()) != EOF)
       putchar (c);
}
(kopiert von Tastatur -> Konsole) Zuerst dachte ich: O wie elegant!
Dann aber irritiert: "EOF" ist eine vordefinierte Konstante. Ein logischer Vergleich müsste somit mit einem implizit oder explizit gleichem Datentyp stattfinden. "c = getchar()" ist aber eine Wertzuweisung auf eine Variable.

Wie kann eine ganze Wertzuweisung überhaupt einen Datentypen haben? Eine Wertzuweisung ist doch nicht identisch mit einem Wertausdruck? Vermutlich in C dann wohl den des Ergebnistypen. Irritiert mich immer noch. Vielleicht kommt die Erleuchtung noch, aber erstmal finde ich es sehr befremdlich. Halt von meiner Pascal-Übung her kommend, den Zuweisungsoperator := streng vom Gleichheitstest = zu unterscheiden. Dann braucht man auch nicht diese Stolper-Klammern um alle log. Vergleichsausdrücke. (sondern nur bei zusammengesetzten Ausdrücken)
Kommt mir vor wie der Spruch: "Nachts ist es kälter als draußen". Ich verstehe, was gemeint ist, finde es auch witzig, aber klar, sprachlich-semantisch ist es nicht korrekt.

tobo
Beiträge: 2346
Registriert: 10.12.2008 10:51:41

Re: C lernen

Beitrag von tobo » 29.10.2024 17:47:13

TuxPeter hat geschrieben: ↑ zum Beitrag ↑
29.10.2024 15:55:34
1. Funktionsergebnisse können nicht nur elementare Werte sein, sonder auch Strukturen und Unionen als Ergebnis liefern. Das gab's in Pascal nicht! Oder doch? Probiert und siehe da, in FreePascal funktioniert auch ein Record als Fuktionstyp. Sollte mir das damals entgangen sein? Aber nein, mit TurboPascal in der Dosbox probiert, geht nicht. Zum Glück, wäre ja peinlich.
Dann ändere mal innerhalb der Funktion "result" in den Funktionsnamen um - Turbo Pascal kannte noch kein Schlüsselwort Result und hat die Zuweisung an den Funktionsnamen als Rückgabewert aufgefasst. Und das konnte ein Zeiger sein, also auch ein Record.

PS: Free Pascal hat übrigens einen Turbo_Pascal-Mode durch entweder inline {$mode TP} oder Kompilierungsschalter -MTP.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C lernen

Beitrag von Meillo » 29.10.2024 19:03:27

TuxPeter hat geschrieben: ↑ zum Beitrag ↑
29.10.2024 15:55:34
2. Folgendes simple Beispielprogramm (hier auf S.17):

Code: Alles auswählen

#include <stdio.h>
void main () {
int c;
while ((c = getchar()) != EOF)
       putchar (c);
}
(kopiert von Tastatur -> Konsole) Zuerst dachte ich: O wie elegant!
Dann aber irritiert: "EOF" ist eine vordefinierte Konstante. Ein logischer Vergleich müsste somit mit einem implizit oder explizit gleichem Datentyp stattfinden. "c = getchar()" ist aber eine Wertzuweisung auf eine Variable.

Wie kann eine ganze Wertzuweisung überhaupt einen Datentypen haben? Eine Wertzuweisung ist doch nicht identisch mit einem Wertausdruck? Vermutlich in C dann wohl den des Ergebnistypen. Irritiert mich immer noch. Vielleicht kommt die Erleuchtung noch, aber erstmal finde ich es sehr befremdlich. Halt von meiner Pascal-Übung her kommend, den Zuweisungsoperator := streng vom Gleichheitstest = zu unterscheiden. Dann braucht man auch nicht diese Stolper-Klammern um alle log. Vergleichsausdrücke. (sondern nur bei zusammengesetzten Ausdrücken)
Kommt mir vor wie der Spruch: "Nachts ist es kälter als draußen". Ich verstehe, was gemeint ist, finde es auch witzig, aber klar, sprachlich-semantisch ist es nicht korrekt.
Pascal und C sind konzeptionell schon sehr verschieden -- zwei unterschiedliche Sprachfamilien -- darum kann man Erwartungen nicht unbedingt uebertragen.

Pascal wurde als Lehrsprache entworfen, darum ist alles sehr klar und deutlich und eindeutig (... und umstaendlich :-P ).

C wurde als pragmatische Sprache von Entwicklern fuer ihre eigene Arbeit entworfen, darum ist alles so, dass der Compiler simpel zu entwickeln ist und man knackigen Code schreiben kann.

Der Ausdruck, ueber den du stolperst ist gerade so etwas: zunaechst verwirrend, aber letztlich sehr praktisch.

Beim Verstaendnis hilft die Grammatik von C: https://cs.wmich.edu/~gupta/teaching/cs ... 20form.htm

Code: Alles auswählen

<expression> ::= <assignment-expression>
               | <expression> , <assignment-expression>

<assignment-expression> ::= <conditional-expression>
                          | <unary-expression> <assignment-operator> <assignment-expression>
Hier siehst du, dass eine Zuweisung (Assignment) in C auf ein Ausdruck (Expression) ist. Die Zuweisung hat als Ausdruck den Wert des zugewiesenen Wertes.

`(c = getchar())' hat also den Wert des eingelesenen Zeichens, z.B. 'a'.

Obwohl nur Zeichen eingelesen werden, hat die Variable c nicht den Typ char, sondern int, da ausserhalb des Werteraums der Zeichen noch ein Wert fuer End-of-File abgebildet werden muss. Das passiert mittels der Konstante `EOF', die typischerweise den Wert -1 hat.

Dieser eingelesene Wert wird dann mit EOF verglichen, als Schleifenbedingung.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C lernen

Beitrag von Meillo » 31.10.2024 09:20:33

Dazu wollte ich noch etwas schreiben:
TuxPeter hat geschrieben: ↑ zum Beitrag ↑
29.10.2024 15:55:34
Pascal [...] Zuweisungsoperator := [...] Gleichheitstest =
Ich persoenlich finde die zwei Operatoren in Pascal eigentlich auch sinnvoller als = bzw. == in C. Irgendwo habe ich mal gelesen, warum sie in C sind wie sie sind: Und zwar liegt das daran, dass Zuweisungen oefter vorkommen als Vergleiche, darum wurde fuer die Zuweisung der einzeichige Operator gewaehlt und fuer den selteneren Vergleich der zweizeichige Operator. Das erklaert die Wahl in C ... und es fuegt sich ein in das was ich im vorigen Post zum Design von C geschrieben habe.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C lernen

Beitrag von Meillo » 31.10.2024 09:22:11

Mal eine Frage an alle: Wer ist denn nun eigentlich alles dran am C-Lernen? Wie kommt ihr voran? Wollt ihr mal ein kleines selbstgeschriebenes Programm vorstellen? Sollen wir eine kleine Programmieraufgabe hier starten (so aehnlich wie beim Shellscripting-Contest)?
Use ed once in a while!

Benutzeravatar
MSfree
Beiträge: 11605
Registriert: 25.09.2007 19:59:30

Re: C lernen

Beitrag von MSfree » 31.10.2024 09:39:17

Meillo hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 09:20:33
Ich persoenlich finde die zwei Operatoren in Pascal eigentlich auch sinnvoller als = bzw. == in C.
Nunja, eigentlich ist die Zuweisung schon in der Mathematik mit "=" definiert und die meisten Programmiersprachen (z.B. Fortran, Basic, Java, C, C++, C#...) verwenden diese Definition. Pascal sticht da mit ":=" eigentlich wie ein Fremdkörper heraus.

Bei den Vergleichsoperatoren in den verschiedenen Sprachen herrscht Uneinigkeit:

Code: Alles auswählen

Fortran        .eq.
C/C++/C#/Java  ==
Basic/Pascal   =
Man kann allerdings in C so "verrückte" Dinger wie

Code: Alles auswählen

if( ( value = FunctionCall( Parameter ) ) == 0 ) {
  ...
}
bauen. Die Notwendigkeit zur Unterscheidung von Zuweisung und Vergleich wird hier deutlich.

Basic erlaubt im IF-Statement keine gleichzeitige Zuweisung, so daß hier keine Unterscheidung der Operatoren passieren muß.

Benutzeravatar
GregorS
Beiträge: 3144
Registriert: 05.06.2008 09:36:37
Wohnort: Freiburg
Kontaktdaten:

Re: C lernen

Beitrag von GregorS » 31.10.2024 09:41:12

Meillo hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 09:22:11
Wollt ihr mal ein kleines selbstgeschriebenes Programm vorstellen?
Sollen wir eine kleine Programmieraufgabe hier starten (so aehnlich wie beim Shellscripting-Contest)?
Da ich C++ quasi „direkt“ gelernt habe, musste ich mich mit vielen C-Grundlagen gar nicht näher befassen. Den K+R habe ich mir seinerzeit nur zugelegt, um irgendwann die C-Grundlagen nachzuholen. Und ich befasse mich hin und wieder mit Teilaspekten von C, soweit sie mir zum tieferen Verständnis der C++-Ideen helfen. Wenn es hier auch Selbstgeschriebenes zu lesen gäbe, würde ich es zumindest lesen :-)
Wenn man keine Probleme hat, kann man sich welche machen. ("Großes Lötauge", Medizinmann der M3-Hopi [und sog. Maker])

Benutzeravatar
ralli
Beiträge: 4380
Registriert: 02.03.2008 08:03:02

Re: C lernen

Beitrag von ralli » 31.10.2024 10:12:23

Da ich auch lieber aufgabenorientiert arbeite, hier der C Code für ein kleines Adressverwaltungsprogramm. Es funktioniert, ist aber bestimmt noch verbesserungswürdig. Die Grundlagen habe ich mit ChatGPT gelernt, das ging schneller als wie mit jedem Buch. Der Quellcode ist im Grunde selbsterkärend. Ich möchte das dann demnächst ändern und eine Literaturdatenbank daraus machen. Ich nehme geany als Editor meiner Wahl.

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_PERSONEN 100
#define MAX_NAME_LENGTH 50
#define MAX_ADDRESS_LENGTH 100
#define FILE_NAME "adressen.txt"

// Struktur für eine Person

struct Person {
    char name[MAX_NAME_LENGTH];
    char address[MAX_ADDRESS_LENGTH];
    char phone[15];
};

// Funktion zur Eingabe einer neuen Person

void addPerson(struct Person personen[], int *anzahl) {
    if (*anzahl >= MAX_PERSONEN) {
        printf("Die Adressliste ist voll!\n");
        return;
    }

system("clear");  // Bildschirm löschen unter Linux

    struct Person p;
    printf("Name: ");
    fgets(p.name, MAX_NAME_LENGTH, stdin);
    p.name[strcspn(p.name, "\n")] = '\0';

    printf("Adresse: ");
    fgets(p.address, MAX_ADDRESS_LENGTH, stdin);
    p.address[strcspn(p.address, "\n")] = '\0';

    printf("Telefonnummer: ");
    fgets(p.phone, 15, stdin);
    p.phone[strcspn(p.phone, "\n")] = '\0';

    personen[*anzahl] = p;
    (*anzahl)++;

    // Speichere die neue Person in die Datei
    
    FILE *file = fopen(FILE_NAME, "a");
    if (file == NULL) {
        printf("Fehler beim Öffnen der Datei!\n");
        return;
    }
    fprintf(file, "%s;%s;%s\n", p.name, p.address, p.phone);
    fclose(file);

	printf("\n");

    printf("Person erfolgreich hinzugefügt!\n");
    }

// Funktion zur Anzeige aller Personen

void listPersons(const struct Person personen[], int anzahl) {
    printf("\n--- Adressliste ---\n");
    printf("\n");
    for (int i = 0; i < anzahl; i++) {
        printf("Person %d:\n", i + 1);
        printf("  Name: %s\n", personen[i].name);
        printf("  Adresse: %s\n", personen[i].address);
        printf("  Telefonnummer: %s\n", personen[i].phone);
        printf("\n");
    }
}

// Funktion zur Suche nach einer Person

void searchPerson(const struct Person personen[], int anzahl) {
    char name[MAX_NAME_LENGTH];
    printf("Geben Sie den Namen ein, nach dem Sie suchen möchten: ");
    fgets(name, MAX_NAME_LENGTH, stdin);
    name[strcspn(name, "\n")] = '\0';

    int found = 0;
    for (int i = 0; i < anzahl; i++) {
        if (strcmp(personen[i].name, name) == 0) {
            printf("\nGefunden:\n");
            printf("  Name: %s\n", personen[i].name);
            printf("  Adresse: %s\n", personen[i].address);
            printf("  Telefonnummer: %s\n", personen[i].phone);
            found = 1;
            break;
        }
    }

    if (!found) {
        printf("Person mit dem Namen '%s' wurde nicht gefunden.\n", name);
    }
}

// Funktion zum Löschen einer Person

void deletePerson(struct Person personen[], int *anzahl) {
    char name[MAX_NAME_LENGTH];
    printf("Geben Sie den Namen der Person ein, die gelöscht werden soll: ");
    fgets(name, MAX_NAME_LENGTH, stdin);
    name[strcspn(name, "\n")] = '\0';

    int found = 0;
    for (int i = 0; i < *anzahl; i++) {
        if (strcmp(personen[i].name, name) == 0) {
            found = 1;
            // Verschiebe alle folgenden Einträge nach vorne
            for (int j = i; j < *anzahl - 1; j++) {
                personen[j] = personen[j + 1];
            }
            (*anzahl)--;
            printf("Person '%s' wurde erfolgreich gelöscht.\n", name);
            break;
        }
    }

    if (!found) {
        printf("Person mit dem Namen '%s' wurde nicht gefunden.\n", name);
    } else {
        // Aktualisiere die Datei nach dem Löschen
        FILE *file = fopen(FILE_NAME, "w");
        if (file == NULL) {
            printf("Fehler beim Öffnen der Datei!\n");
            return;
        }
        for (int i = 0; i < *anzahl; i++) {
            fprintf(file, "%s;%s;%s\n", personen[i].name, personen[i].address, personen[i].phone);
        }
        fclose(file);
    }
}

// Funktion zum Laden der Personen aus der Datei

int loadPersons(struct Person personen[]) {
    FILE *file = fopen(FILE_NAME, "r");
    if (file == NULL) {
        printf("Keine gespeicherten Adressen gefunden.\n");
        return 0;
    }

    int anzahl = 0;
    while (fscanf(file, "%49[^;];%99[^;];%14[^\n]\n", 
                  personen[anzahl].name, 
                  personen[anzahl].address, 
                  personen[anzahl].phone) == 3) {
        anzahl++;
    }

    fclose(file);
    return anzahl;
}

// Hauptprogramm

int main() {
    struct Person personen[MAX_PERSONEN];
    int anzahl = loadPersons(personen);
    int auswahl;

system("clear");  // Bildschirm löschen unter Linux/macOS

    while (1) {
        printf("\n--- Adressverwaltung ---\n");
        printf("\n");
        printf("1. Person hinzufügen\n");
        printf("2. Alle Personen anzeigen\n");
        printf("3. Person suchen\n");
        printf("4. Person löschen\n");
        printf("5. Beenden\n");
        printf("\n");
        printf("Auswahl: ");
        scanf("%d", &auswahl);
        getchar(); // Liest das newline-Zeichen nach scanf ein

        switch (auswahl) {
            case 1:
                addPerson(personen, &anzahl);
                break;
            case 2:
                listPersons(personen, anzahl);
                break;
            case 3:
                searchPerson(personen, anzahl);
                break;
            case 4:
                deletePerson(personen, &anzahl);
                break;
            case 5:
                printf("Programm beendet.\n");
                return 0;
            default:
                printf("Ungültige Auswahl!\n");
        }
    }

    return 0;
}
Compiliert wird das ganze so:

Code: Alles auswählen

gcc adress.c -o adress
und gestartet in der Konsole mit:

Code: Alles auswählen

./adress
Natürlich kann auch clang genommen werden.

Gruß ralli

Huo
Beiträge: 783
Registriert: 26.11.2017 14:03:31
Wohnort: Freiburg

Re: C lernen

Beitrag von Huo » 31.10.2024 10:13:39

MSfree hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 09:39:17
Nunja, eigentlich ist die Zuweisung schon in der Mathematik mit "=" definiert und die meisten Programmiersprachen (z.B. Fortran, Basic, Java, C, C++, C#...) verwenden diese Definition. Pascal sticht da mit ":=" eigentlich wie ein Fremdkörper heraus.
In der (akademischen) Mathematik ist ":=" durchaus allgemein gebräuchlich und zu lesen als "ist definiert als" [1]. Pascal ist auch nicht die einzige Programmiersprache, die das aus der Mathematik übernommen hat. Ada wäre ein weiteres Beispiel.

Nachtrag: Sogar Python hat in Version 3.8 ":=" eingeführt: https://docs.python.org/3/whatsnew/3.8. ... xpressions, im Volksmund auch Walrus Operator :D genannt.

[1] siehe z.B. https://mathematik-studium-tipps.de/mat ... e-symbole/
Zuletzt geändert von Huo am 31.10.2024 11:06:10, insgesamt 4-mal geändert.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C lernen

Beitrag von Meillo » 31.10.2024 10:15:04

MSfree hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 09:39:17
Meillo hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 09:20:33
Ich persoenlich finde die zwei Operatoren in Pascal eigentlich auch sinnvoller als = bzw. == in C.
Nunja, eigentlich ist die Zuweisung schon in der Mathematik mit "=" definiert und die meisten Programmiersprachen (z.B. Fortran, Basic, Java, C, C++, C#...) verwenden diese Definition. Pascal sticht da mit ":=" eigentlich wie ein Fremdkörper heraus.
Hmm ... Ich bin kein richtiger Mathematiker, aber gibt es in der Mathematik ueberhaupt Zuweisungen? Eine Zuweisung ist ja eine Aktion zu einem bestimmten Zeitpunkt. In der Mathematik ist ein Gleichheitszeichen doch eher eine Feststellung (von globaler Aussage), was etwas sehr anderes ist als eine Zuweisung, bei der man sowas machen kann, was mathematisch Unsinn ist: `x = 5; x = 1'. So gesehen hat aus meiner Sicht das mathematische Gleichheitszeichen mehr Gemeinsamkeit mit dem Vergleich als mit der Zuweisung.

Das `:=' in Pascal und das `<-' in R stehen fuer etwas, das es in der Mathematik nicht gibt. Dort gaebe es nur sowas wie `#define', also das einmalige Festlegen einer Konstanten.

Aber, wie gesagt, ich bin kein richtiger Mathematiker, darum duerft ihr mich gerne korrigieren.

Allerdings hast du recht, dass fast alle Programmiersprachen `=' fuer die Zuweisung verwenden.
Use ed once in a while!

mampfi
Beiträge: 1981
Registriert: 16.08.2005 18:15:29
Lizenz eigener Beiträge: GNU General Public License
Wohnort: münchen

Re: C lernen

Beitrag von mampfi » 31.10.2024 10:30:36

also, es gab mal Zeiten, da war die beste Lehrsprache gleih die beste "Berufssprache", (Turbo-)Pascall.

Das war aber unter MS-DOS, mit Textmodus usw., war aber eine andere Welt.

Zum Verständnis von objektorientierter Programmierung möchte ich sagen:

Stellt Euch eine Prozedur vor, mit ungefähr einem halben Dutzend Parametern

Fenste(x,y,breite, hoehe, ...)

Dann kann man eine Klasse, Objekt mit Standard-Parametern definieren, wo man nur die Parameter, übergibt, die sich ändern.

Desweiteren gab´s natürlich die klassisches Windows-Programmierung, wo da Hello-World-Programm drei Seiten lang war.

Da war die erste Erholung Turbo-Pascal für Windows und engültig Visual Basic. :THX:

Ach ja: Pascal-Zuweisung: a := b
und C a=c.

Was mir jetzt wieder alles einfällt ;-)

Also nicht schreiben: if (a=c) ...
Es gibt viele Foren und eine Welt ausserhalb

Benutzeravatar
MSfree
Beiträge: 11605
Registriert: 25.09.2007 19:59:30

Re: C lernen

Beitrag von MSfree » 31.10.2024 11:25:08

mampfi hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 10:30:36
Also nicht schreiben: if (a=c) ...
Das Statement ist ein legales Konstrukt in C, so daß der Compiler es nicht als Fehler werten darf. So etwas ist aber problematisch, weil nicht offensichtlich klar ist, ob der Programmierer eine Zuweisung vornehmen wollte, die hinterher auf Nicht-Null geprüft werden soll, oder ob das ein Vergleich sein sollte, bei dem das zweite "=" vergessen wurde.

Moderne Compiler geben in so einem Fall eine Warnung aus.

Die bessere und somit auch eindeutige Schreibweise wäre im Fall der Korrekten Zuweisung kombiniert mit dem Vergleich:

Code: Alles auswählen

if( (a=c) != 0 )
was moderne Compiler ohne Warnung akzeptieren.
Zuletzt geändert von MSfree am 31.10.2024 13:37:23, insgesamt 1-mal geändert.

mampfi
Beiträge: 1981
Registriert: 16.08.2005 18:15:29
Lizenz eigener Beiträge: GNU General Public License
Wohnort: münchen

Re: C lernen

Beitrag von mampfi » 31.10.2024 12:47:09

Ich sollte ergänzen, das nur schreiben, wenns tatsächlich so beabsichtigt ist ;-)


Ich hätte so eine Art C-Rätsel parat, weiß aber nicht ob ich die Erklärung noch zusammenbringe.

(Hab ich einem Mitglied dieses Forums per Mail geschickt.)
Es gibt viele Foren und eine Welt ausserhalb

mampfi
Beiträge: 1981
Registriert: 16.08.2005 18:15:29
Lizenz eigener Beiträge: GNU General Public License
Wohnort: münchen

Re: C lernen

Beitrag von mampfi » 31.10.2024 13:04:37

Ach ich schicks mal, wurde ohne Warnung kompiliert
schreibt bei der Ausgabe nicht
vektor[ i]
sondern
i[vektor]


Da würde PASCAL schimpfen, in C geht´s aber. :twisted:
---------------------------------------------------------------------------

#include <stdio.h>

int main(void)

{
unsigned char i;

char vektor[10];

for (i=0; i <= 9; i++) vektor=i;

for (i=0; i <= 9; i++) printf("%d\n", i[vektor]); //i und vektor vertauscht, wieso geht das?

puts("Hauptprogramm Fertig");
}
Es gibt viele Foren und eine Welt ausserhalb

Benutzeravatar
MSfree
Beiträge: 11605
Registriert: 25.09.2007 19:59:30

Re: C lernen

Beitrag von MSfree » 31.10.2024 13:44:19

mampfi hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 13:04:37

Code: Alles auswählen

 for (i=0; i <= 9; i++) printf("%d\n", i[vektor]); //i und vektor vertauscht, wieso geht das?
Nein, geht nicht. Da kommt beim Compilieren der Fehler "error: incompatible types in assignment".

mampfi
Beiträge: 1981
Registriert: 16.08.2005 18:15:29
Lizenz eigener Beiträge: GNU General Public License
Wohnort: münchen

Re: C lernen

Beitrag von mampfi » 31.10.2024 14:05:17

Dann werd ich´s nochmal kompilieren,

sicher ist sicher.
Es gibt viele Foren und eine Welt ausserhalb

Benutzeravatar
GregorS
Beiträge: 3144
Registriert: 05.06.2008 09:36:37
Wohnort: Freiburg
Kontaktdaten:

Re: C lernen

Beitrag von GregorS » 31.10.2024 14:08:00

mampfi hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 13:04:37
... in C geht´s aber. ...
Nein: g++ meldet

Code: Alles auswählen

tmp.c:10:32: error: incompatible types in assignment of ‘unsigned char’ to ‘char [10]’
Und sowas geht in Pascal?! Was'n Glück, dass ich das nie gelernt habe.
Wenn man keine Probleme hat, kann man sich welche machen. ("Großes Lötauge", Medizinmann der M3-Hopi [und sog. Maker])

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C lernen

Beitrag von Meillo » 31.10.2024 14:09:13

MSfree hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 13:44:19
mampfi hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 13:04:37

Code: Alles auswählen

 for (i=0; i <= 9; i++) printf("%d\n", i[vektor]); //i und vektor vertauscht, wieso geht das?
Nein, geht nicht. Da kommt beim Compilieren der Fehler "error: incompatible types in assignment".
Du hast die falsche Codestelle Codestelle zitiert. Diese Ausgabeschleife funktioniert schon und das Vertauschen von `vektor' und `i' ist auch valide ... was ich gerne erklaeren kann, wenn genug Zeit zum Raetseln gewesen ist.

Falsch am Code ist die Initialisierungsschleife, die `vektor = i;' statt `vektor[ i] = i;' enthaelt. Das liegt daran, dass [ i ] als BB-Code interpretiert worden ist, weil keine [ code ]-Tags verwendet worden sind. Das zeigt nochmal, dass es sinnvoll ist, Code in Code-Tags zu packen. ;-)
Use ed once in a while!

mampfi
Beiträge: 1981
Registriert: 16.08.2005 18:15:29
Lizenz eigener Beiträge: GNU General Public License
Wohnort: münchen

Re: C lernen

Beitrag von mampfi » 31.10.2024 14:15:20

Ich gebe zu,ich poste hier meist von Win aus.
-----------------------------------------------------------
Installierter gcc:

ii gcc 4:12.2.0-3 amd64 GNU C compiler
ii gcc-12 12.2.0-14 amd64 GNU C compiler
ii gcc-12-base:amd64 12.2.0-14 amd64 GCC, the GNU Compiler Collection (base package)
ii libgcc-12-dev:amd64 12.2.0-14 amd64 GCC support library (development files)
ii libgcc-s1:amd64 12.2.0-14 amd64 GCC support library
ii libuno-cppuhelpergcc3-3 4:7.4.7-1+deb12u1 amd64 LibreOffice UNO runtime environment -- CPPU helper library
ii libuno-purpenvhelpergcc3-3 4:7.4.7-1+deb12u1 amd64 LibreOffice UNO runtime environment -- "purpose environment" helper
ii libuno-salhelpergcc3-3 4:7.4.7-1+deb12u1 amd64 LibreOffice UNO runtime environment -- SAL helpers for C++ library

Zur Sicherheit nochmal der Quellcode, der funktioniert (direkt vom LInux-Rechner aus):
------------------------------------------------------------
#include <stdio.h>

int main(void)

{
unsigned char i;

char vektor[10];

for (i=0; i <= 9; i++) vektor=i;

for (i=0; i <= 9; i++) printf("%d\n", i[vektor]); //i und vektor vertauscht, wieso geht das?




puts("Hauptprogramm Fertig");

}
Es gibt viele Foren und eine Welt ausserhalb

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C lernen

Beitrag von Meillo » 31.10.2024 14:46:44

Nochmals den Hinweis, den Code in [ code]-Tags zu packen. Das Problem ist nicht, der Code, wie du ihn hier ins Forum postest, sondern dass das Forum das im Code enthaltene als BB-Code interpretiert (darum wird der Text auch irgendwann ploetzlich kursiv). Wenn du den Code in [ code]-Tags packst, dann passiert das nicht. (Zudem ist er dann auch besser lesbar und einfacher kopierbar.)
Use ed once in a while!

Benutzeravatar
GregorS
Beiträge: 3144
Registriert: 05.06.2008 09:36:37
Wohnort: Freiburg
Kontaktdaten:

Re: C lernen

Beitrag von GregorS » 31.10.2024 14:48:32

mampfi hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 14:15:20
Ich gebe zu,ich poste hier meist von Win aus. ...
Dass der von Dir gepostete Code nicht funktioniert, hat nichts mit Windows zu tun. Das code-Tag funktioniert auch da. Und Du bist schon lange genug hier aktiv, um zu wissen, wozu code-Tags da sind. Außerdem hat Meillo das Problem benannt. Hast Du sein Posting nicht gelesen?
Wenn man keine Probleme hat, kann man sich welche machen. ("Großes Lötauge", Medizinmann der M3-Hopi [und sog. Maker])

mampfi
Beiträge: 1981
Registriert: 16.08.2005 18:15:29
Lizenz eigener Beiträge: GNU General Public License
Wohnort: münchen

Re: C lernen

Beitrag von mampfi » 31.10.2024 15:53:24

Das mit dem Posten von Win7 aus war eher humorvoll gemeint, ich surfe mit einem veralteten Windows im debian-forum. ;-)

Dann probier ichs nochmal mit g++ aus, der Vollständigkeit halber.

Ergebnis:

Funktioniert auch, der erzeugte Binärcode von gcc und ist laut "cmp " identisch
Es gibt viele Foren und eine Welt ausserhalb

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C lernen

Beitrag von Meillo » 31.10.2024 16:45:31

ralli hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 10:12:23
Da ich auch lieber aufgabenorientiert arbeite, hier der C Code für ein kleines Adressverwaltungsprogramm.
Schoenes Programm. :THX:

Wenn ich mir ein paar Kommentare erlauben darf:
ralli hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 10:12:23

Code: Alles auswählen

struct Person {
    char name[MAX_NAME_LENGTH];
    char address[MAX_ADDRESS_LENGTH];
    char phone[15];
};
Wieso verwendest du fuer die Telefonnummer nicht auch eine Laengenkonstante wie fuer den Namen und die Adresse?
ralli hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 10:12:23

Code: Alles auswählen

    fgets(p.name, MAX_NAME_LENGTH, stdin);
    p.name[strcspn(p.name, "\n")] = '\0';
Die strspn(3)-Funktionen habe ich erst vor 1-2 Jahren kennengelernt. In so einem Fall wie hier sind sie wirklich praktisch, um sich ein `if' zu sparen. Wie bist du denn auf diese Codezeile gekommen?

ralli hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 10:12:23

Code: Alles auswählen

    while (fscanf(file, "%49[^;];%99[^;];%14[^\n]\n", 
Hier waere es natuerlich schoen, auch die Langenkonstanten von oben zu verwenden.

Ich finde es besser, die Konstanten ohne abschliessendes Null-Byte zu definieren, also die reale Inhaltslaenge. Das Null-Byte gibt man dann an den relevanten Stellen immer explizit mit an. Also:

Code: Alles auswählen

		
#define MAX_NAME_LENGTH 49
struct Person {
    char name[MAX_NAME_LENGTH + 1];
    ...
};
Die Vorteile sind, dass man dann den passenden Laengenwert in der Konstanten hat, wo wie man ihn auch an anderen Stellen im Programm brauchen kann (wie hier die 49 statt der 50), und dass man explizit sieht, dass an das Null-Byte gedacht worden ist.

Den fscanf-String muss man ueber einen Pufferstring mit snprintf(3) zusammenbauen, wenn man hierfuer das Define nutzen will. Da weiss ich keine bessere Moeglichkeit. Dann koennte man aber die ganzen Magic Numbers im Code loswerden.

ralli hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 10:12:23
printf("Auswahl: ");
scanf("%d", &auswahl);
getchar(); // Liest das newline-Zeichen nach scanf ein
Hast du mal probiert, wenn der User etwas eingibt, das nicht den Erwartungen entspricht? Wie robust ist der Code, wenn man z.B. ``q'' (fuer quit) eingibt oder ``exit''?

Vielleicht waere es besser, die Eingabe mit fgets(3) einzulesen und dann die Zahl mit atoi(3) zu extrahieren.
ralli hat geschrieben: ↑ zum Beitrag ↑
31.10.2024 10:12:23
Compiliert wird das ganze so:

Code: Alles auswählen

gcc adress.c -o adress
Wenn du make(1) installiert hast, geht es so auch ganz bequem:

Code: Alles auswählen

make adress
Das funktioniert ueber implizite Regeln. In diesem einfachen Fall brauchst du kein Makefile dafuer. ;-)

Insgesamt ein schoenes Programm. Und auch eine tolle Ausgangsbasis fuer Folgeaufgaben:
- auf dynamische Speicherverwaltung umstellen, so dass die Anzahl der Adresseintraege nicht beschraenkt ist und auch nur soviel Speicher verbraucht wird wie Adresseintraege vorhanden sind
- beliebig lange Namen, Adressen und Telefonnummern erlauben
- aus dem Adressarray eine lineare Liste machen
- die Liste sortierbar machen (dazu qsort(3) mit einer eigenen Sortierfunktion nutzen -- das ist dann aber schon deutlich fortgeschritten)
Use ed once in a while!

Antworten