Замена подстроки в строке
Найти в строке определенную последовательность символов (подстроку) и заменить ее другой.
- s , s_old , s_new — исходная строка, заменяемая подстрока, вставляемая подстрока;
- i – номер символа строки, с которого начинается подстрока;
- l_old – длина заменяемой подстроки.
Алгоритм решения задачи:
- Ввести строку, подстроку, которую требуется заменить, и подстроку, которую требуется вставить на место прежней.
- Найти место вхождения подстроки в строку с помощью функции pos().
- Удалить старую подстроку с помощью процедуры delete().
- Вставить новую подстроку, используя процедуру insert().
Программа на языке Паскаль:
var s,s_old,s_new: string; i,l_old: byte; begin write('Insert string: '); readln(s); write('What change? '); readln(s_old); l_old := length(s_old); write('What to replace? '); readln(s_new); i := pos(s_old,s); delete(s,i,l_old); insert(s_new,s,i); writeln(s); end.
Функция pos(subs, s) ищет вхождение подстроки subs в строке s и возвращает номер первого символа subs в s или нуль, если subs не содержится в s .
Процедура delete(s, start, len) удаляет из строки s , начиная с позиции start , подстроку длиной len .
Процедура insert(subs, s, start) вставляет в строку s подстроку subs , начиная с позиции start .
Если в строке несколько одинаковых подстрок, которые требуется заменить на новую подстроку, то следует воспользоваться циклом:
var s, s_old, s_new: string; i, l_old: byte; begin write('Введите строку: '); readln(s); write('Введите подстроку, которую требуется заменить: '); readln(s_old); l_old := length(s_old); write('Введите новую подстроку: '); readln(s_new); i := 1; while i <> 0 do begin i := pos(s_old, s); if i <> 0 then begin delete(s, i, l_old); insert(s_new, s, i); end; end; writeln(s); end.
Пример работы программы:
Введите строку: wsfgw sfkjsfii sf . Введите подстроку, которую требуется заменить: sf Введите новую подстроку: 0000 w0000gw 0000kj0000ii 0000 .
Пример решения похожей задачи в сообществе VK: Заменить в тексте сочетания букв «abc» на «klm»
Как заменить подстроку в строке с
Если надо добавить в конец строки другую строку, применяется метод append() , в который передается добавляемая строка:
#include #include int main() < std::string message< "hello">; message.append(" "); // добавляем пробел message.append("world"); // можно добавить по цепочке // message.append(" ").append("world"); std::cout
Вставка строки
Для вставки одной строки в другую применяется функция insert() . Она имеет несколько различных версий. Самая простая версия принимет индекс вставки и вставляемую строку:
#include #include int main() < std::string text ; std::string str ; text.insert(7, str); std::cout
В данном случае в строку text начиная с 7-го индекса вставляем строку str. В итоге переменная text будет равна "insert a string into a text".
Также можно вставлять строковый литерал:
std::string text ; text.insert(6, "C/"); // Hello C/C++
Можно вставлять часть подстроки:
std::string text ; std::string langs ; text.insert(6, langs, 5, 3); // Langs: C, C++
Здесь в text вставляем из переменной langs 3 символа с 5-го индекса, то есть подстроку " C,".
Среди других версий функции insert() также следует отметить версию, которая позволяет вставить определенный символ определенное число раз:
std::string text ; text.insert(8, 5, '*'); // Number: *****5678
В данном случае вставляем в строку text символ * 5 раз начиная с 8 индекса.
Замена подстроки
Для замены в строке некоторой части применяется функция replace() . Эта функция также имеет много версий, поэтому рассмотрим самые распространенные.
Самая простая версия принимает три параметра:
std::string &std::string::replace(size_t _Off, size_t _Nx, const char *_Ptr)
Первый параметр - представляет индекс, с которого надо заменять подстроку. Второй параметр - количество заменяемых символов. Третий параметр - на какую строку надо заменить. Пример:
#include #include int main() < std::string text ; text.replace(6, 4, "C++"); // Lang: C++ std::cout
Здесь в строке text заменяем 4 символа с 6-го индекса на строку "C++". Таким образом, из строки "Lang: Java" мы получим строку "Lang: C++".
В предыдущем примере символы заменялись на строковый литерал. Но также можно заменять на объект string:
std::string text ; std::string lang <"C++">; text.replace(6, 4, lang); // Lang: C++
Нередко стоит задача заменить какой-то определенную подстроку, индекс которой может быть не известен. В этом случае мы можем воспользоваться поиском в строке, чтобы найти индекс подстроки и ее размер. Например, возьмем текст "Hello, Tom!" и заменим подстроку "Tom" на "Bob":
#include #include int main() < std::string text ; const std::string separators ; // разделители слова size_t start ; // находим позицию подстроки size_t end; // Находим конец подстроки if(end == std::string::npos) // если разделители слова не найдены < end = text.length(); >text.replace(start, end - start, "Alice"); // заменяем подстроку std::cout
Здесь находим позицию первого символа подстроки "Tom" в тексте и сохраняем ее в переменную start. Символ, следующий за последним символом подстроки "Tom", находится путем поиска символа разделителя из строки separators с помощью функции find_first_of() . Далее используем найденные позиции индекса в replace() .
Однако в тексте может быть множество вхождений определенной подстроки (в нашем случае строки "Tom"), и может встать задача заменить все эти вхождения. Для этого мы можем использовать циклы:
#include #include int main() < std::string text ; std::string old_str; // какую подстроку заменить std::string new_str; // на какую строку заменить size_t start ; // находим позицию подстроки while (start != std::string::npos) // находим и заменяем все вхождения строки old_str < text.replace(start, old_str.length(), new_str); // Замена old_str на new_str start = text.find(old_str, start + new_str.length()); >std::cout
Здесь сначала находим индекс первого вхождения подстроки, которую надо заменить, и сохраняем этот индекс в переменную start. В цикле заменяем последовательно все вхождения подстроки. После каждой замены находим индекс следующего вхождения, сохраняем его в переменную start и повторяем цикл. Когда больше нет вхождений подстроки в текст, start будет содержать значение std::string::npos , что завершает цикл.
Из других версий функции replace() можно выделить функцию, которая заменяет подстроку определенным символом, который повторяется определенное количество раз:
std::string text ; text.replace(9, 6, 5, '*'); // Phone: +1*****8901
Здесь заменяет в строке text 6 символов начиная с 9-го индекса на 5 символов *.
Удаление символов
Если надо не просто заменить символы, а удалить их из текста, также можно использовать функцию replace() - в этом случае удаляемые символы фактически заменяются на пустую строку:
#include #include int main() < std::string text ; const std::string empty; text.replace(5, 4, empty); // Замена "Tom" на пустую строку std::cout
Однако С++ также предоставляет для удаления символов специальную функцию - erase() . В качестве параметров она принимает начальный индекс удаления и количество удаляемых символов:
#include #include int main() < std::string text ; text.erase(5, 4); // удаляем 4 символа с 5-го индекса std::cout
Аналогично можно удалить все вхождения определенной подстроки:
#include #include int main() < std::string text ; std::string to_delete; // какую подстроку удалить size_t start ; // находим позицию подстроки while (start != std::string::npos) // находим и удаляем все вхождения to_delete < text.erase(start, to_delete.length()); start = text.find(to_delete, start + to_delete.length()); >std::cout
Функция erase() имеет ряд дополнительных версий. Так, можно оставить определенное количество символов с начала строки, а остальные удалить:
std::string text ; text.erase(5); // удаляем все кроме первых 5 символов - остается "Hello"
Если в функцию не передается никаких параметров, то она удаляет все символы, и в результате получаем пустую строку:
std::string text ; text.erase(); // пустая строка
Стоит отметить, что в стандарт С++20 была добавлена функция std::erase() , которая удаляет все вхождения определенного символа в строке:
#include #include int main() < std::string text ; std::erase(text, 'T'); // Удаляем символ T std::cout
В данном случае удаляем из строки text символ T.
Заменить подстроку в строке.Си
Где p[M] - это длина подстрока s[N] - это сама строка И ,например, в строке есть int i = 0; Написанным выше алгоритмом нахожу перво попавшуюся i .Как можно сделать так , чтобы заменить найденную подстроку на иные символы ?
Отслеживать
задан 27 фев 2018 в 17:49
1,790 1 1 золотой знак 19 19 серебряных знаков 35 35 бронзовых знаков
Вроде есть еще strstr ,которая возвращает указатель на найденный элемент , вот только не понятно, как им тут воспользоваться
27 фев 2018 в 18:05
Если заменяющая строка такой же длины, что и подстрока, найденная strstr() , то очень просто. Используйте memcpy. if ((p = strstr(string, substring))) memcpy(p, newsubstring, strlen(substring)); Конечно, все это более эффективно, если вы заранее знаете длину substring (тогда для поиска можно использовать memmem)
27 фев 2018 в 20:07
Пример? Смотрите в ответе.
27 фев 2018 в 21:46
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
avp@avp-ubu1:hashcode$ uname -a; gcc --vers Linux avp-ubu1 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux gcc.real (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. avp@avp-ubu1:hashcode$ #include #include #include int main (int ac, char *av[]) < char str[1000], subs[1000], repl[1000]; puts("enter main string"); if (!fgets(str, 1000, stdin)) return 1; str[strlen(str) - 1] = 0; // kill \n while ((puts("enter substring and replace"), scanf("%s %s", subs, repl)) == 2) < size_t ssl = strlen(subs), rpl = strlen(repl), l = rpl < ssl ? rpl : ssl; if (rpl != ssl) < repl[l] = 0; subs[l] = 0; printf("warning, lenths are different:" " search and replace it to \n", subs, repl); > char *p = strstr(str, subs); if (p) memcpy(p, repl, l); printf("now str is: \n", str); > return 0; >
Что непонятно, спрашивайте.
Отслеживать
ответ дан 27 фев 2018 в 21:49
45.8k 6 6 золотых знаков 45 45 серебряных знаков 115 115 бронзовых знаков
да-да , я уже сам догнал тоже вот , что у меня вышло for(;;) < if ((p = strstr(A,"pass"))) < memcpy(p,"O4gh", strlen("pass")); >if(p==NULL) < break; >>
27 фев 2018 в 22:15
@Elvin, молодец! Всегда лучше самому разобраться, а сюда заходить, чтобы посоветоваться, как сделать получше и т.п.
Как заменить подстроку в строке с
Требуется заменить в строке подстроку на другую строку на С, то есть используя символьные массивы.
Найти строку знаю можно с помощью функции strstr(), которая возвращает указатель на первое совпадение.
А как заменить?
Придется сдвигать все элементы массива?
Что-то никак не разберусь!
Помогите, пожалуйста.
Re: Заменить в строке подстроку на другу строку на С
От: | Чили | |
Дата: | 24.01.08 10:09 | |
Оценка: | -1 |
Здравствуйте, m.victor, Вы писали:
MV>Требуется заменить в строке подстроку на другую строку на С, то есть используя символьные массивы.
source — строка для замены, pos — позиция начала замены, len — сколько заменить, insert — строка для вставки
char* substr(char *source, int pos, int len, char *insert)
Re[2]: Заменить в строке подстроку на другу строку на С
От: | Аноним |
Дата: | 24.01.08 11:09 |
Оценка: |
Здравствуйте, Чили, Вы писали:
MV>>Требуется заменить в строке подстроку на другую строку на С, то есть используя символьные массивы.
Ч>source — строка для замены, pos — позиция начала замены, len — сколько заменить, insert — строка для вставки
Ч>[ccode]char* substr(char *source, int pos, int len, char *insert)
Ч> <
Ч> menmove(&source[pos+strlen(insert)], &source[pos+len], strlen(insert)-len);
Наверное это функция memmove?
Ч> memcpy(&source[pos], insert, strlen(insert));
Еще можно сначала вычислить int ins_len=strlen(insert); и потом использовать это значение в функциях memmove и memcpy.
Re[2]: Заменить в строке подстроку на другу строку на С
От: | dotidot |
Дата: | 24.01.08 16:56 |
Оценка: |
Здравствуйте, Чили, Вы писали:
Ч>source — строка для замены, pos — позиция начала замены, len — сколько заменить, insert — строка для вставки
Ч>
char* substr(char *source, int pos, int len, char *insert) Ч> < Ч>menmove(&source[pos+strlen(insert)], &source[pos+len], strlen(insert)-len); Ч> memcpy(&source[pos], insert, strlen(insert)); Ч>>
а поясните пожалуйста что у нас тут с памятью происходит?
Re[2]: Заменить в строке подстроку на другу строку на С
От: | dotidot |
Дата: | 24.01.08 16:59 |
Оценка: |
Здравствуйте, Чили, Вы писали:
Ч>source — строка для замены, pos — позиция начала замены, len — сколько заменить, insert — строка для вставки
Ч>
char* substr(char *source, int pos, int len, char *insert) Ч> < Ч>menmove(&source[pos+strlen(insert)], &source[pos+len], strlen(insert)-len); Ч> memcpy(&source[pos], insert, strlen(insert)); Ч>>
а зачем несколько раз считать strlen и почему нет проверок для pos и len?
Re[2]: Заменить в строке подстроку на другу строку на С
От: | dotidot |
Дата: | 24.01.08 17:00 |
Оценка: |
Здравствуйте, Чили, Вы писали:
Ч>
char* substr(char *source, int pos, int len, char *insert) Ч> < Ч>menmove(&source[pos+strlen(insert)], &source[pos+len], strlen(insert)-len); Ч> memcpy(&source[pos], insert, strlen(insert)); Ч>>
и вообще где return?
Re: Заменить в строке подстроку на другу строку на С
От: | dotidot |
Дата: | 24.01.08 17:33 |
Оценка: |
Здравствуйте, m.victor, Вы писали:
вот реализация получше, но её надо тщательно проверить!
/// Return new c-string eq. source[pos..pos+len) + substring + source[pos+len..end] /// Don't forget to free it. /// char* replace_substring(const char* source, int pos, int len, const char* new_substring) < int source_len = 0, sub_len = 0, res_len = 0; char* res = NULL; source_len = strlen(source); sub_len = strlen(new_substring); if (len < 1 || pos < 0 || pos >source_len || (pos + len) > source_len) return NULL; res_len = sub_len + source_len - len + 1; res = calloc(res_len, sizeof(char)); memcpy(res, source, pos); memcpy(res + pos, new_substring, sub_len); memcpy(res + pos + sub_len, source + pos + len, source_len - (pos + len)); res[res_len] = 0; return res; >
Re[2]: Заменить в строке подстроку на другу строку на С
От: | Аноним |
Дата: | 26.01.08 14:17 |
Оценка: |
Здравствуйте, dotidot, Вы писали:
еще один вариант
int string_replace(char *string, const char *delimiter, const char *replacement)
int bret = 0;
char *ret;
int length_del, length_rep, i, j;
if (string == NULL || delimiter == NULL || replacement == NULL)
return 0;
length_del = strlen(delimiter);
length_rep = strlen(replacement);
/* Count how many times the delimiter appears */
i = 0; /* position in the source string */
j = 0; /* number of occurrences of "delimiter" */
while (string[i] != '\0') if (!strncmp(&string[i], delimiter, length_del)) i += length_del;
j += length_rep;
bret = 1;
> else i++;
j++;
>
>
if (!bret)
return bret;
ret = malloc(j+1);
if (!ret)
return 0;
i = 0; /* position in the source string */
j = 0; /* position in the destination string */
while (string[i] != '\0') if (!strncmp(&string[i], delimiter, length_del)) strncpy(&ret[j], replacement, length_rep);
i += length_del;
j += length_rep;
> else ret[j] = string[i];
i++;
j++;
>
>
strcpy(string, ret);
free(ret);