Удаление всех символов строки s1, встречающихся в s2 - C (СИ)
Формулировка задачи:
Здравствуйте! Пытаюсь решить задание из книги Кернигана и Ричи "Язык программирования Си".
Задание звучит так: "Напишите альтернативную версию ф-ции squeeze(s1,s2), которая бы удаляла из строки s1 все символы, встречающиеся в строке s2". Судя по контексту, речь идёт о массивах (а не о строковых константах)
Вот, что я написал:
Проблема в том, что если ввести во вторую строку более одного символа, то символ конца строки проглатывается, и в результирующем массиве оказываются
// Упражнение 2.4. Напишите squeeze(s1,s2), которая бы удаляла из строки s1 все символы, встречающиеся в строке s2.
#include <stdio.h>
#define STR_LIM 75 // макс. длина строки
void squeeze(char s1[], char s2[]);
void getline(char arr[], int str_length);
int main()
{
char arr1[STR_LIM], arr2[STR_LIM];
printf("\n Программа удаляет из строки №1 все символы, содержащиеся в строке №2.\n");
printf("\n Введите строку№1...\n:>");
getline(arr1, STR_LIM); // получаем первую строку
printf("\n Теперь введите строку№2...\n:>");
getline(arr2, STR_LIM); // получаем вторую строку
// Подытоживая собранные данные...
printf("\nВы ввели:%s и захотели удалить из неё символы: %s\n", arr1, arr2);
squeeze(arr1, arr2);
// Вывод результата
printf("Получилась строка: %s\n", arr1);
return 0;
}
//getline(arr[], limit): Получает из входного потока строку недлинее limit и сохраняет её в массиве-аргументе arr[]
void getline(char arr[], int lim)
{
int x, i;
i = 0;
while ((x = getchar()) != '\n' && i < lim-2)
arr[i++] = x;
arr[i] = '\0';
}
//squeeze(s1,s2): Удаляет из строки s1 все символы. встречающиеся в строке s2.
void squeeze(char s1[], char s2[])
{
int i, m, n;
for (i = 0; s2[i] !='\0'; i++) // перебираем нежелательные символы из 2й строки
for(m = n = 0; s1[m] != '\0'; m++)
if (s1[m] != s2[i] && s1[m] != '\0')
s1[n++] = s1[m];
s1[n] = '\0';
}лишние символы
. Допустим, если ввести в 1ю строку "12345ggggg6789" и во вторую "gg", то получим "1234567896789
". Никак не могу сообразить, как с этим справиться, не разводя писанину... Если не трудно - подскажите плз!p.s.:
в задании говорилось про "альтернативную" версию. Так вот, в изначальной версии squeeze имела в качестве второго (удаляемого) аргумента простой символ. Можно сказать, что тело функции почти не изменилось, только обрело 1 лишнуюю переменную и внешний цикл, перебирающий все символы строки s2, которые не должны оставаться в s1. В связи с этим я думаю, что может надо было вообще по-другому подходить к решению?
Решение задачи: «Удаление всех символов строки s1, встречающихся в s2»
textual
Листинг программы
#include <stdio.h>
//функция удаляет из строки 1 все символы, которые есть в строке 2
void squeeze(char s1[], char s2[])
{
int i, j, k, sovp;
for(i=k=0; s1[i]!='\0'; i++) {
sovp = 0;
for(j=0; s2[j]!='\0'; j++) {
if(s1[i]==s2[j])
sovp = 1;
}
if(!sovp) //если совпадений не было
s1[k++] = s1[i];
}
s1[k] = '\0';
}
int main()
{
char line1[] = "12345ggggg6789",
line2[] = "gg";
squeeze(line1, line2);
printf("%s", line1);
return 0;
}
Объяснение кода листинга программы
- Включаем файл стандартного ввода/вывода
- Функция squeeze принимает два аргумента типа char: s1 и s2.
- Внутри функции объявляем четыре переменные: i, j, k и sovp.
- Переменная i используется для индексации строки s1, а переменная j - для индексации строки s2.
- Переменная k используется для индексации результирующей строки s1.
- Переменная sovp используется для проверки, был ли найден символ из строки s2 в строке s1.
- Используя два вложенных цикла, проходим по каждому символу строки s1.
- Для каждого символа проверяем, есть ли такой же символ в строке s2.
- Если символ найден, то переменной sovp присваивается значение 1.
- Если после прохода по всем символам строки s2 символ не был найден, то он добавляется в результирующую строку s1.
- После прохода по всем символам строки s1 добавляется символ '\0' для завершения строки.
- В функции main создаем две строки: line1 и line2.
- Строка line1 содержит
12345ggggg6789, а строка line2 содержитgg. - Вызываем функцию squeeze, передавая ей строку line1 и строку line2.
- После выполнения функции squeeze выводим на экран результат, используя функцию printf.
- Результатом будет строка
123456789, так как все вхождения символаgбыли удалены из строки line1. - Возвращаем 0, чтобы указать, что программа успешно завершилась.
- Если бы в функции main мы передали другие строки, например,
abracadabraиab, то результатом было быaracadabra, так как все вхождения символаabбыли удалены из исходной строки.