[erledigt] "The C-Programming-Language" - Segfaults in ...

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
paedubucher
Beiträge: 940
Registriert: 22.02.2009 16:19:02
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz
Kontaktdaten:

[erledigt] "The C-Programming-Language" - Segfaults in ...

Beitrag von paedubucher » 09.08.2009 22:41:50

Hallo allerseits

Ich möchte mich wieder mal etwas mit C beschäftigen, bzw. mich überhaupt mal ernsthaft mit C beschäftigen. (Bisher habe ich nur ein Jahr an der Berufsschule C programmiert, didaktisch sinnentleert mit Microsoft Visual Studio...) Nun habe ich mir das C-Buch schlechthin geholt: "The C-Programming-Language" von Kernigham/Ritchie. Ich muss sagen, das Buch gefällt mir sehr gut. Wer schon einmal programmiert hat, wird die - doch teils etwas anspruchsvolleren - Aufgaben und die hohe Informationsdichte gut mögen. Bei Aufgabe 2.4 (Seite 48 - vielleicht hat ja das Buch jemand zur Hand), geht es um die Erweiterung einer Funktion namens "squeeze". Ich habe die Aufgabe gelöst und erhalte jeweils einen Segmentation fault. Hier der Code ("squeeze" soll alle Zeichen aus s1 entfernen, die ebenfalls in s2 vorkommen):

Code: Alles auswählen

#include <stdio.h>

void squeeze(char *, char *);

int main(int argc, char *argv[])
{
    char *s1 = "Das ist ein Test!";
    char *s2 = "e";
    squeeze(s1, s2); 
    printf("%s", s1);

    return 0;
}

void squeeze(char s1[], char *s2)
{
    int r1, r2, w, c_ok;
    for (r1 = 0, w = 0; s1[r1] != '\0'; r1++)
    {
        for(r2 = 0, c_ok = 1; s2[r2] != '\0'; r2++)
        {
            if (s1[r1] == s2[r2])
            {
                c_ok = 0;
                break;
            }
        }
        if (c_ok)
            s1[w++] = s1[r1];
    }
    s1[w] = '\0';
}
Ob die Lösung wirklich ganz korrekt ist, konnte ich leider noch nicht überprüfen. Die Grundfunktion "squeeze" wurde auf der vorhergehenden Seite aufgelistet, sie sieht so aus:

Code: Alles auswählen

#include <stdio.h>

void squeeze(char *, char);

int main(int argc, char *argv[])
{
    char *s = "Das ist ein Test!";
    char c = 'c';
    squeeze(s, c);
    return 0;
}

void squeeze(char s[], char c)
{
    int i, j;

    for (i = j = 0; s[i] != '\0'; i++)
        if (s[i] != c)
            s[j++] = s[i];
    s[j] = '\0';
}
Das zweite Programm löst ebenfalls einen Segmentation fault aus. Nun meine Frage: Habe 1) ich den Code falsch abgetippt, 2) ich die Funktion falsch aufgerufen oder 3) Kernigham/Ritchie ein System verwendet, das solche Zuweisungen nicht bemängelt? Muss also einer derartige Funktion zwingend in einen Segfault führen, wie es hier der Fall ist?

Code: Alles auswählen

#include <stdio.h>

int main(int argc, char *argv[])
{
    char *s = "Dilbert";
    s[0] = 'G';
    return 0;
}
Wie sähe eine Lösung für das Problem aus, das auch auf heutigen Systemen funktioniert?

Besten Dank!
Zuletzt geändert von paedubucher am 10.08.2009 10:20:49, insgesamt 1-mal geändert.
Habe nun, ach! Java
Python und C-Sharp,
Und leider auch Visual Basic!
Durchaus programmiert mit heissem Bemühn.
Da steh' ich nun, ich armer Tor!
Und bin so klug als wie zuvor.

Benutzeravatar
Accelerometer
Beiträge: 168
Registriert: 31.01.2009 17:03:13
Lizenz eigener Beiträge: GNU Free Documentation License

Re: "The C-Programming-Language" - Segfaults in Buchform?

Beitrag von Accelerometer » 10.08.2009 05:36:17

Wenn ich das jetzt richtig interpretiere, versuchst du hier, Stringkonstanten zu ändern. Das kann natürlich nicht gutgehen. Du musst malloc (3) verwenden:

Code: Alles auswählen

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

int main(int argc, char *argv[])
{
   char* s = (char *) malloc(8);
   strncpy(s,"Dilbert",8);
   s[0] = 'G';
   printf("%s\n", s);
   return 0;
}
"Ich bin ein Gegner der Religion. Sie lehrt uns, damit zufrieden zu sein, dass wir die Welt nicht verstehen."
-- Richard Dawkins, "Der Gotteswahn"

Benutzeravatar
GoKi
Beiträge: 2068
Registriert: 04.07.2003 23:08:56
Lizenz eigener Beiträge: MIT Lizenz

Re: "The C-Programming-Language" - Segfaults in Buchform?

Beitrag von GoKi » 10.08.2009 09:31:55

Statt malloc und strncpy, kann man auch direkt strdup verwenden.
Zur Übung sollte man danach auch den Pointer mit free wieder freigeben.
MfG GoKi
:wq

paedubucher
Beiträge: 940
Registriert: 22.02.2009 16:19:02
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Schweiz
Kontaktdaten:

Re: "The C-Programming-Language" - Segfaults in Buchform?

Beitrag von paedubucher » 10.08.2009 10:20:09

Accelerometer hat geschrieben:Wenn ich das jetzt richtig interpretiere, versuchst du hier, Stringkonstanten zu ändern. Das kann natürlich nicht gutgehen. Du musst malloc (3) verwenden:
Ah, jetzt dämmert es langsam wieder. Vielen Dank! Pointer und Speichermanagement wurden bisher im Buch noch nicht erwähnt, darum findet sich zu diesem Beispiel auch kein Aufruf der Funktion.

Danke & Gruss,
Pädu
Habe nun, ach! Java
Python und C-Sharp,
Und leider auch Visual Basic!
Durchaus programmiert mit heissem Bemühn.
Da steh' ich nun, ich armer Tor!
Und bin so klug als wie zuvor.

Danielx
Beiträge: 6419
Registriert: 14.08.2003 17:52:23

Re: [erledigt] "The C-Programming-Language" - Segfaults in ...

Beitrag von Danielx » 10.08.2009 11:43:45

Accelerometer hat geschrieben:Du musst malloc (3) verwenden
Nein, muss er nicht:

Code: Alles auswählen

#include <stdio.h>

void squeeze(char *, char);

int main(int argc, char *argv[])
{
    char s[] = "Das ist ein Test!";
    printf("Zeichenkette 1: %s\n", s);
    char c = 'e';
    printf("entfernen: %c\n", c);
    squeeze(s, c);
    printf("Zeichenkette 2: %s\n", s);
    return 0;
}

void squeeze(char s[], char c)
{
    int i, j;

    for (i = j = 0; s[i] != '\0'; i++)
        if (s[i] != c)
            s[j++] = s[i];
    s[j] = '\0';
}
Habe da noch Ausgaben eingefügt und 'c' auf 'e' abgeändert, damit auch etwas entfernt wird. :-)

In dieser Zeile ist übrigens der Fehler:
paedubucher hat geschrieben:

Code: Alles auswählen

    char *s = "Das ist ein Test!";
Aufgabe 2.4:

Code: Alles auswählen

#include <stdio.h>

void squeeze(char *, char *);

int main(int argc, char *argv[])
{
    char s[] = "Das ist ein Test!";
    printf("Zeichenkette 1: %s\n", s);
    char c[] = "sati";
    printf("entfernen: %s\n", c);
    squeeze(s, c);
    printf("Zeichenkette 2: %s\n", s);
    return 0;
}

void squeeze(char s[], char c[])
{
    int i, j, k, match;

    for (i = j = 0; s[i] != '\0'; i++) {
        for (k = 0, match = 0; c[k] != '\0'; k++) {
            if (s[i] == c[k])
                match = 1;
        }
        if (!match)
            s[j++] = s[i];
    }
    s[j] = '\0';
}
paedubucher hat geschrieben:Wie sähe eine Lösung für das Problem aus, das auch auf heutigen Systemen funktioniert?
So:

Code: Alles auswählen

#include <stdio.h>

int main(int argc, char *argv[])
{
    char s[] = "Dilbert";
    printf("%s", s);
    return 0;
}
Gruß,
Daniel

Antworten