107 lines
3.3 KiB
Markdown
107 lines
3.3 KiB
Markdown
|
---
|
|||
|
title: "➕ Конкатенация строк в Си"
|
|||
|
date: 2023-03-27T23:02:00+03:00
|
|||
|
draft: false
|
|||
|
tags: [c, tutorial, development]
|
|||
|
---
|
|||
|
|
|||
|
## Введение
|
|||
|
|
|||
|
В этом руководстве а нескольких примерах покажу,
|
|||
|
как в Си конкатенировать строки.
|
|||
|
|
|||
|
## Пример №1
|
|||
|
|
|||
|
Если содержимое строк известно на этапе компиляции,
|
|||
|
то и склеивание можно организовать на этапе компиляции.
|
|||
|
|
|||
|
```c
|
|||
|
#define FIRST "first"
|
|||
|
#define SECOND "second"
|
|||
|
|
|||
|
int main(void)
|
|||
|
{
|
|||
|
const char *first = FIRST;
|
|||
|
const char *second = SECOND;
|
|||
|
const char *third = FIRST SECOND;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## Пример №2
|
|||
|
|
|||
|
Для склеивания строк во время выполнения программы
|
|||
|
можно использовать функцию `strcat()` из библиотеки `string.h`.
|
|||
|
([Прочитать](https://ru.wikipedia.org/wiki/String.h) описание на Wikipedia)
|
|||
|
|
|||
|
```c
|
|||
|
char *strcat(char *dest, const char *src);
|
|||
|
```
|
|||
|
|
|||
|
Но испольованиие `strcat()` — не самая лучшая идея из-за того,
|
|||
|
что при каждом склеивании функция снова и снова выполняет сканирование
|
|||
|
уже построенной части строки.
|
|||
|
|
|||
|
По этой причине `strcat()` - фактически бесполезная функция.
|
|||
|
|
|||
|
Лучше уж воспользоваться для этих целей обычным `snprintf`.
|
|||
|
|
|||
|
```c
|
|||
|
#include <stdio.h>
|
|||
|
|
|||
|
int main(void)
|
|||
|
{
|
|||
|
const char *first = "first";
|
|||
|
const char *second = "second";
|
|||
|
|
|||
|
char third[512];
|
|||
|
snprintf(third, sizeof third, "%s%s", first, second);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
А уж какой способ резервирования памяти для строки больше подходит
|
|||
|
— зависит от конкретных обстоятельств и требований.
|
|||
|
|
|||
|
## Пример №3
|
|||
|
|
|||
|
При помощи функции `malloc` выделить блок памяти (`result`),
|
|||
|
достаточный для сохранения в него обеих строк
|
|||
|
(и не забыть про место, для завершающего нуля).
|
|||
|
|
|||
|
При помощи функции `memcpy` скопировать
|
|||
|
первую строку `s1` в начало выделенного блока.
|
|||
|
|
|||
|
При помощи всё той же функции `memcpy`
|
|||
|
скопировать вторую строку `s2`, вместе с её нулём,
|
|||
|
в выделенный блок, со смещением на размер первой строки.
|
|||
|
|
|||
|
После того, как совершены какие-то манипуляции с полученной строкой,
|
|||
|
её нужно освободить, при помощи функции `free`.
|
|||
|
|
|||
|
```c
|
|||
|
char* concat(char *s1, char *s2) {
|
|||
|
|
|||
|
size_t len1 = strlen(s1);
|
|||
|
size_t len2 = strlen(s2);
|
|||
|
|
|||
|
char *result = malloc(len1 + len2 + 1);
|
|||
|
|
|||
|
if (!result) {
|
|||
|
fprintf(stderr, "malloc() failed: insufficient memory!\n");
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
memcpy(result, s1, len1);
|
|||
|
memcpy(result + len1, s2, len2 + 1);
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Как использовать:
|
|||
|
|
|||
|
```c
|
|||
|
char *s = concat("first", "second");
|
|||
|
printf("%s\n", s);
|
|||
|
free(s);
|
|||
|
```
|