Удаление всех символов строки 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", то получим "123456789

6789

". Никак не могу сообразить, как с этим справиться, не разводя писанину... Если не трудно - подскажите плз!

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;
}

Объяснение кода листинга программы

  1. Включаем файл стандартного ввода/вывода
  2. Функция squeeze принимает два аргумента типа char: s1 и s2.
  3. Внутри функции объявляем четыре переменные: i, j, k и sovp.
  4. Переменная i используется для индексации строки s1, а переменная j - для индексации строки s2.
  5. Переменная k используется для индексации результирующей строки s1.
  6. Переменная sovp используется для проверки, был ли найден символ из строки s2 в строке s1.
  7. Используя два вложенных цикла, проходим по каждому символу строки s1.
  8. Для каждого символа проверяем, есть ли такой же символ в строке s2.
  9. Если символ найден, то переменной sovp присваивается значение 1.
  10. Если после прохода по всем символам строки s2 символ не был найден, то он добавляется в результирующую строку s1.
  11. После прохода по всем символам строки s1 добавляется символ '\0' для завершения строки.
  12. В функции main создаем две строки: line1 и line2.
  13. Строка line1 содержит 12345ggggg6789, а строка line2 содержит gg.
  14. Вызываем функцию squeeze, передавая ей строку line1 и строку line2.
  15. После выполнения функции squeeze выводим на экран результат, используя функцию printf.
  16. Результатом будет строка 123456789, так как все вхождения символа g были удалены из строки line1.
  17. Возвращаем 0, чтобы указать, что программа успешно завершилась.
  18. Если бы в функции main мы передали другие строки, например, abracadabra и ab, то результатом было бы aracadabra, так как все вхождения символа ab были удалены из исходной строки.

Оцени полезность:

11   голосов , оценка 4.364 из 5
Похожие ответы