Как вставить строку в строку c
Перейти к содержимому

Как вставить строку в строку c

  • автор:

Копирование строки. Функция strcpy.

Строки могут копироваться одна в другую. Для этого можно использовать функцию strcpy , которая имеет прототип:

char* strcpy(char* str1, const char* str2);

Функция выполняет побайтное копирование строки, на которую указывает str1. Копирование прекращается только в случае достижения символа конца строки (\0) str2, поэтому перед копированием необходимо убедиться в том, что длина строки str2 не больше длины строки str1. В противном случае возможны ошибки в программе.

Рассмотрим пример. Следующий фрагмент программы копирует в строку z слово «September».

char z[10]; strcpy(z,"September");

Можно проводить копирование не всей строки, а отдельного ее фрагмента до конца строки. Пример:

char str1[20]="Goodbye world"; char str2[20]; //Указатель на строку с адресом str1: char* ptr=str1; /*Увеличиваем значение адреса на 8 байт. Теперь он указывает на адрес подстроки "world":*/ ptr=ptr+8; /*Копируем в str2 то, на что указывает указатель ptr, т.е. подстроку "world":*/ strcpy(str2,ptr); /*Выводим на экран то, что получилось после копирования:*/ cout

На экран выведется: world

Функция strncpy.

Функция strncpy отличается от функции strcpy тем, что добавляется еще один параметр - номер символа, больше которого не будет скопировано. Эта функция имеет прототип:

char* strncpy(char* str1, const char* str2, size_t num);
char z[10]; strncpy(z,"String",3);
  • Функции на ввод- вывод
  • Сортировки
  • Чтение и запись векторов в файл
  • Чтение и запись
    матриц в файл
  • Транспонирование матрицы
  • Поиск количества нулевых
    элементов в строке
  • Поиск строки, в которой все
    элементы

Особенности работы со строками в языке Си

Неформатированные ввод из стандартного потока и вывод в стандартный поток

С помощью функции printf() можно легко вывести на экран строку, содержащую пробелы:

printf("%s", "Hello world");

Ввести строку с пробелами уже сложнее. Для scanf() любой символ пустого пространства является сигналом завершения ввода очередных данных, если только не производится считывание самого символа. Чтобы ввести строку произвольной длины, содержащую пробелы в неизвестных местах, приходится использовать шаблон:

scanf("%[^'\n']", str);

Также на помощь может прийти функция getchar() , осуществляющая посимвольный ввод данных:

#include int main() { char str[20], i; for (i = 0; (str[i] = getchar()) != '\n'; i++); str[i] = '\0'; printf("%s\n", str); }

В заголовке цикла getchar() возвращает символ, далее записываемый в очередную ячейку массива. После этого элемент массива сравнивается с символом '\n'. Если они равны, то цикл завершается. После цикла символ '\n' в массиве "затирается" символом '\0'. В условии цикла должна быть также предусмотрена проверка на выход за пределы массива; чтобы не усложнять пример, опущена.

Однако в языке программирования C работать со строками можно проще. С помощью функций стандартной библиотеки gets() и puts() получают строку из стандартного потока и выводят в стандартный поток. Буква s в конце слов gets и puts является сокращением от слова string (строка).

В качестве параметров обе функции принимают указатель на массив символов (либо имя массива, либо указатель).

Функция gets() помещает полученные с ввода символы в указанный в качестве аргумента массив. При этом символ перехода на новую строку, который завершает ее работу, игнорируется.

Функция puts() выводит строку на экран и при этом сама добавляет символ перехода на новую строку. Простейший пример использования этих функций выглядит так:

#include int main() { char str[100]; gets(str); puts(str); }

При компиляции данной программы появляется предупреждение об опасности использования gets (но программа скомпилируется и будет работать). Вместо нее рекомендуют использовать функцию fgets . Однако последней кроме указателя на строку также надо передать лимит количества считываемых символов и из какого потока ввода поступают данные. В данном случае ‒ из стандартного ‒ stdin :

#include #define N 100 int main() { char str[N]; fgets(str, N, stdin); puts(str); }

При этом в строку помещается и символ перехода на новую строку ‒ '\n'. И только после него символ конца строки ‒ '\0'. Если переход не нужен, от него можно избавиться так:

str[strcspn(str, "\n" )] = '\0';

Итак, если вы работаете со строками, а не другими типами данных, при этом нет необходимости выполнять их посимвольную обработку, то может быть удобнее пользоваться функциями puts и fgets .

Массив символов и указатель на строку

Как мы знаем, строка представляет собой массив символов, последний элемент которого является нулевым символом по таблице ASCII, обозначаемым '\0'. При работе со строками также как с численными массивами можно использовать указатели. Мы можем объявить в программе массив символов, записать туда строку, потом присвоить указателю адрес на первый или любой другой элемент этого массива и работать со строкой через указатель:

char name[30]; char *p; printf("Введите имя и фамилию: "); fgets(name, sizeof(name), stdin); printf("Имя: "); for (p = name; *p != ' '; p++) putchar(*p); printf("\nФамилия: "); puts(p + 1);

В заголовке цикла указателю сначала присваивается адрес первого элемента массива, его значение увеличивается до тех пор, пока не встретится пробел. В итоге указатель указывает на пробел, и мы можем получить с его помощью вторую часть строки.

Иногда в программах можно видеть такое объявление и определение переменной-указателя:

char *strP = "Hello World!";

Строку, которая была присвоена не массиву, а указателю, также можно получить, обратившись по указателю:

puts(strP);

Но давайте посмотрим, что же все-таки происходит, и чем такая строка, присвоенная указателю, отличается от строки, присвоенной массиву.

Когда в программе определяются данные и объявляются переменные, то под них отводится память. При этом данные, которые не были присвоены переменным, поменять в процессе выполнения программы уже нельзя.

Что происходит в примере? В программе вводится строковый объект, который по сути является строковой константой (литералом). Ссылка на первый элемент этой строки присваивается указателю. Мы можем менять значение указателя сколько угодно, переходить к любому из элементов константного массива символов или даже начать ссылаться на совершенно другую строку. Но вот поменять значение элементов строки не можем. Это можно доказать таким кодом:

char *strP; // работает, но строку нельзя изменить strP = "This is a literal"; puts(strP); printf("%c\n",strP[3]); strP[3] = 'z'; // не получится

В последней строке кода возникнет ошибка (при выполнении программы), т.к. совершается попытка изменить строку-константу.

Тем более нельзя делать так:

char *strP; // ошибка сегментирования scanf("%s",strP); 

В данном случае память не была выделена под массив символов, который мы пытаемся получить функцией scanf() ; память была выделена только под указатель. Поэтому записать строку просто некуда. Другое дело, если память была выделена с помощью объявления массива, после чего указателю был присвоен адрес на этот массив:

char str[12]; char *strP; strP = str; // память резервируется под массив ранее gets(strP); puts(strP);

Итак, если вам требуется в программе неизменяемый массив символов, то можете определить его через указатель.

Передача строки в функцию

Передача строки в функцию ничем не отличается от передачи туда массива чисел:

char name[30]; char *p; printf("Введите имя и фамилию: "); fgets(name, sizeof(name), stdin); printf("Имя: "); for (p = name; *p != ' '; p++) putchar(*p); printf("\nФамилия: "); puts(p + 1);

В этом примере функция change принимает в качестве аргумента указатель на символ. В теле функции значение указателя инкрементируется, указывая на следующий символ массива. В теле цикла инкрементируется значение, которое находится по адресу, который содержит указатель.

Объявите в программе три массива символов. Данные для двух из них получите с помощью вызовов функции fgets() . Третий массив должен содержать результат конкатенации (соединения) двух введенных строк. Напишите функцию, которая выполняет конкатенацию строк.

Массив строк и массив указателей

Рассмотрим более сложный пример. Допустим, у нас есть набор строк. Требуется выполнить сортировку строк по возрастанию по признаку длины: сначала вывести самые короткие строки, затем более длинные.

Набор строк можно представить как двумерный массив, т.е. массив, состоящий из одномерных массивов, где каждый одномерный массив — это строка символов:

char str[][10] = {"Hello", "World", ". ", "&&&"};

Представьте себе, что значит выполнить сортировку строк. Это значит, надо поменять местами содержимое множества ячеек памяти. Это достаточно трудоемкая для компьютера работа, особенно если строк очень много. Однако можно поступить по-иному. Достаточно создать массив указателей, каждый элемент которого будет указывать на соответствующую ему строку первого массива. Далее выполнить сортировку указателей, что несомненно быстрее. Конечно, сам массив строк отсортирован не будет, однако благодаря указателям у нас будет хранится отсортированный "срез" массива:

Сортировка строк через массив указателей

#include #include #define N 6 #define M 30 void sortlen(char *s[]); int main() { char strings[N][M]; char *p[N]; for (int i = 0; i  N; i++) { fgets(strings[i], M, stdin); p[i] = &strings[i][0]; } printf("\n"); sortlen(p); for (int i = 0; i  N; i++) { printf("%s", p[i]); } } // **s == *s[] - массив указателей void sortlen(char **s) { int i, j; char *str; for (i = 0; i  N-1; i++) for (j = 0; j  N-i-1; j++) if (strlen(s[j]) > strlen(s[j+1])) { str = s[j]; s[j] = s[j+1]; s[j+1] = str; } }

Примечания к программе:

  • Функция strlen объявлена в заголовочном файле string.h . Она возвращает длину строки без учета завершающего нулевого символа.
  • Сортировка выполняется методом пузырька: если длина строки, на которую ссылается следующий указатель массива s , меньше длины строки под текущим указателем, то значения указателей меняются.
  • Выражение p[i] = &strings[i][0] означает, что элементу массива указателей присваивается ссылка на первый символ каждой строки.

Напишите программу, которая сортирует строки по алфавиту. Для упрощения задачи пусть сортировка выполняется только по первым буквам строк (если первые буквы слов одинаковы, то вторые и последующие символы проверять не надо).

Курс с решением задач:
pdf-версия

Как вставить строку в строку после определенного символа?

Что значит "вставить"? Требуется модифицировать исходную строку "на месте"? Или требуется создать отдельную новую строку с выполненной вставкой?

31 окт 2018 в 0:23

4 ответа 4

Сортировка: Сброс на вариант по умолчанию

string str = "Rasim, Hello!"; size_t pos = str.find_first_of(','); str.insert(pos + 1, " Misar and Kefal"); cout  

Пусть у вас есть строка str . Затем, чтобы что-то вставить в неё, вам нужно знать позицию внутри строки. .find_first_of возвращает индекс вашего определённого символа. После него вставим новую строку: str.insert(pos + 1, "Misar and Kefal");

Отслеживать
ответ дан 30 окт 2018 в 18:29
Mikhail Leliakin Mikhail Leliakin
493 3 3 серебряных знака 8 8 бронзовых знаков
Но тут используется стринг
30 окт 2018 в 18:42

Когда я набирал ответ Ваш вопрос, у вас не было второго предложения в нём. Вы имеете ввиду массив char-ов?

30 окт 2018 в 18:44
да ,нужно решить задачку через char-ы
30 окт 2018 в 18:46

Без std::string и т.п. можно так

#include #include #include char * insert (char *str, size_t capacity, char *subs, char c, int *uerr) < int dummy, *err = uerr ? uerr : &dummy; *err = 0; char *p = c ? strchr(str, c) : str - 1; if (p) < p++; size_t l2 = strlen(subs); if (l2) < size_t l1 = strlen(str); if (l1 + l2 >capacity) return (*err = 1, (char *)0); memmove(p + l2, p, l1 - (p - str) + 1); memcpy(p, subs, l2); > > return p; > #define CAPACITY 100 int main (int ac, char *av[]) < if (ac < 4) exit((puts("Usage: ./a.out string insert-part char-to-lookup"), 1)); if (strlen(av[1]) >CAPACITY - 1) exit((puts("string too long"), 1)); char res[CAPACITY]; strcpy(res, av[1]); int err; if (!insert(res, sizeof(res), av[2], av[3][0], &err)) puts(err ? "ovefflow" : "not found"); else puts(res); > 

Если далее что-то останется непонятно -- спрашивайте.

Внесем небольшое усовершенствование, позволяющее делать вставку также и в начало строки. Для этого надо передать 4-й аргумент ( char c ) равным 0.

Отслеживать
ответ дан 30 окт 2018 в 22:41
46k 6 6 золотых знаков 47 47 серебряных знаков 115 115 бронзовых знаков

void insert(char* p, const char* m, char delim) < while (*p++ != delim); // после этого цикла указатель указывает на следующий // символ после символа разделителья *p = '\0'; // тут мы ставим завершающий символ strcat(p, m); // чтобы вызвать функцию добавления строки >

p.s. strcat нетрудно написать самому

Отслеживать
ответ дан 30 окт 2018 в 19:14
AR Hovsepyan AR Hovsepyan
15.9k 3 3 золотых знака 14 14 серебряных знаков 30 30 бронзовых знаков
объясните пожалуйста
30 окт 2018 в 19:17
ну если вы такой простой код не понимаете, то что дадут мои обььяснения.
30 окт 2018 в 19:19

Даже если закрыть глаза на то, что delim может вообще отсутствовать, то вы все равно не вставляете m[] в p[] , а перетираете ее хвост (текст после искомого символа)

31 окт 2018 в 20:06

const char str[] = "Rasim - Sehr Gut!"; const char symbol = '-'; const size_t str_length = sizeof(str) / sizeof(char); const char str_to_insert[] = "and Misar"; const size_t str_to_insert_length = sizeof(str_to_insert) / sizeof(char); char str_result[str_length+str_to_insert_length - 1]; int index = 0; for (int i = 0; i < str_length; i++) < str_result[i] = str[i]; if (str[i] == symbol) < index = i; break; >> for (int i = 0; i < str_to_insert_length - 1; i++) < str_result[i + index + 1] = str_to_insert[i]; >for (int i = index + 1; i

Если нельзя использовать string, то придётся реализовывать всё самому. Найдём позицию символа, перебирая посимвольно первую строку, а заодно копируя просмотренные символы во вторую. После того, как в цикле будет найден необходимый символ, выбегаем из цикла и копируем посимвольно строку для вставки с той позиции, на которой мы остановились. Обратим внимание, что мы не копируем последний символ - он означает завершение строки и невидим для нас. Далее закончим махинации, скопировав в результат ещё не просмотренный остаток оригинальной строки.

Как вставить строку в строку c

Если надо добавить в конец строки другую строку, применяется метод 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.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *