Sigmentation fault C при попытке перезаписать элемент массива

Я пытаюсь решить задание из книжки. Вот текст задания:

Напишите версию функции squeeze(s1, s2), которая удаляет из s1 все символы, встречающиеся в строке s2.

Вот мой код:

#include <stdio.h>

void squeeze(char s1[], char s2[]);

void main() {
        squeeze("hellodk", "hell");

        return;
}

void squeeze(char s1[], char s2[]) {
        int i, j, k;

        for (i = 0; s1[i] != '\0'; i++) {
                for (j = 0; s2[j] != '\0'; j++) {
                        if (s1[i] == s2[j])
                                s1[i] = '\0';
                }
        }

        for (i = 0; s1[i] != '\0'; i++)
                printf("%c", s1[i]);
        printf("\n");

        return;
}

При запуске программа выводит Sigmentation fault, а должна odk. Заранее спасибо :)


Ответы (2 шт):

Автор решения: Max I

Дело в том, что строки "hellodk" и "hell", которые вы передаете в функцию squeeze() являются строковыми литералами. Строковые литералы хранятся в памяти в Read-only режиме, а попытка их изменить в squeeze() является неопределённым поведением и может привести (как в вашем случае) к Segfault. При работе со строками я рекомендую выделять память на куче, как в данном примере:

#define STR1 "hellodk"
#define STR2 "hell"

void squeeze(char *s1, char *s2);

int main(void) {
        char *s1 = (char*)malloc(sizeof(char) * (strlen(STR1) + 1));
        char *s2 = (char*)malloc(sizeof(char) * (strlen(STR2) + 1));

        strcpy(s1, STR1);
        strcpy(s2, STR2);

        squeeze(s1, s2);

        free(s1);
        free(s2);

        return 0;
}
→ Ссылка
Автор решения: Harry

Ну, в общем, как я уже говорил, не стоит пытаться менять что-то в литералах, особенно если это VC++ :)

А кроме того, вам надо изменить сам алгоритм, потому что в вашем примере сразу же строка s1 зануляется...

Вот вам ваш исправленный вариант:

#include <stdio.h>

void squeeze(char s1[], char s2[]);

void main()
{
    char s1[] = "hellodk";
    char s2[] = "leh";
    squeeze(s1,s2);
}

void squeeze(char s1[], char s2[])
{
    int L = strlen(s1), k = 0;
    for (int i = 0; i < L; i++)
    {
        for (int j = 0; s2[j] != '\0'; j++)
            if (s1[i] == s2[j])
            {
                s1[i] = '\0';
                break;
            }
    }

    for (int i = 0; i < L; i++)
        if (s1[i]) s1[k++] = s1[i];
    s1[k] = 0;
    printf("%s\n", s1);
    return;
}
→ Ссылка