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 шт):
Дело в том, что строки "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;
}
Ну, в общем, как я уже говорил, не стоит пытаться менять что-то в литералах, особенно если это 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;
}