При исполнении кода
#include <stdio.h>
#include <string.h>
int main() {
char first = "first";
char second = "second";
char *third = strcat(first, second);
}
происходит ошибка сегментирования.
Если содержимое строк известно на этапе компиляции, то и склеивание можно организовать на этапе компиляции
#define FIRST "first"
#define SECOND "second"
int main(void)
{
const char *first = FIRST;
const char *second = SECOND;
const char *third = FIRST SECOND;
}
Но это уж зависит от того, что именно вам нужно.
Для склеивания во время выполнения использовать функцию strcat - не самая лучшая идея из-за того, что при каждом склеивании функция снова и снова выполняет сканирование уже построенной части строки. (По этой причине strcat - фактически бесполезная функция.) Лучше уж воспользоваться для этих целей обычным snprintf
#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);
}
А уж какой способ резервирования памяти для строки-получателя вам больше подходит - зависит от ваших конкретных обстоятельств и требований.
Чтобы склеить 2 строки в Си, нужно выполнить следующие действия:
При помощи функции malloc выделить блок памяти (result), достаточный для сохранения в него обеих строк (и не забыть про место, для завершающего нуля)
При помощи функции memcpy скопировать первую строку s1 в начало выделенного блока
При помощи всё той же функции memcpy скопировать вторую строку s2, вместе с её нулём, в выделенный блок, со смещением на размер первой строки
После того, как вы совершили какие-то манипуляции с полученной строкой, её нужно освободить, при помощи функции free
Пример:
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;
}
Как использовать:
char *s = concat("first", "second");
printf("%s\n", s);
free(s);
Для strcat первый аргумент должен указывать на буфер достаточной длины, чтобы в него могла поместиться итоговая (склеенная) строка. Переменные first и second являются указателями на строковые литералы, т.е. данные по таким указателям изменять нельзя. Это приводит к неопределенному поведению (UB).
Исходный пример может быть переписан следующим образом:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const char* first = "first"; // const явно указывает, что такие данные менять нельзя
const char* second = "second";
char* buff = calloc(strlen(first) + strlen(second) + 1, 1);
strcat(buff, first);
strcat(buff, second);
printf("%s\n", buff);
free(buff);
}
Самый простой вариант - явно зарезервировать под первую строку (к которой будет "приклеиваться" вторая строка) памяти с запасом:
#include <stdio.h>
#include <string.h>
int main() {
char first[256] = "first";
char second[] = "second";
strcat(first, second);
puts(first);
return 0;
}
Результат выполнения: http://ideone.com/OOXUCV
Раз уж пошло такое массовое отвечание некропоста, то внесу и свою лепту.
В GNU есть очень удобный аналог sprintf -- asprintf, которая размещает результат "вывода" своих аргументов в динамической памяти (использует malloc).
Соответственно, программа может быть такой:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int
main (int ac, char *av[])
{
char first[] = "first",
second[] = "second";
char *third;
if (asprintf(&third, "%s%s", first, second) < 0)
third = strdup(strerror(errno));
return puts(third) == EOF;
}
А если у вас ее (asprintf) нет, то несложно и самому написать
static int
asprintf (char **ps, const char *fmt, ...)
{
// puts("my asprintf");
va_list ap;
va_start(ap, fmt);
int rc = vsnprintf(*ps, 0, fmt, ap);
va_end(ap);
if (rc >= 0) {
if ((*ps = (char *)malloc(rc + 2))) {
va_start(ap, fmt);
rc = vsnprintf(*ps, rc + 1, fmt, ap);
va_end(ap);
} else
rc = -1;
}
return rc;
}
(или скопипастить) и использовать уже без всяких #define _GNU_SOURCE даже в винде (по крайней мере MinGW успешно транслирует).
#include <stdlib.h>
#include <string.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);//+1 нужен для нуль-терминатора строки.
strcpy(result, s1);
strcat(result, s2);
return result;
}
Потому что функция strcat() добавляет
"second") к строке, на которую указывает первый параметр ("first")
и затем вращает первый параметр - указатель на первую строку, но к которой теперь добавлена и вторая строка,
нужно для первого параметра выделить достаточную память для соединенной строки ("firstsecond") - или во время компиляции, или динамически.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void myStrcat(char* des, char* src);
int main () {
char des[100];
char cat[50];
printf("Введите строку 1:");
fgets(des, 100, stdin);
des[strlen(des)-1] = '\0';
printf("Введите строку 2:");
fgets(cat, 50, stdin);
cat[strlen(cat)-1] = '\0';
myStrcat(des, cat);
printf("%s\n", des);
getchar();
return 0;
}
void myStrcat(char *des, char *src)
{
int len1 = strlen(des);
int len2 = strlen(src);
memcpy(des + len1, src, len2 + 1);
return 0;
}
Проблема в том, что функция strcat не выделяет память, а копирует из одной строки в другую. Поскольку длина первой строки меньше, чем длина второй, то память перетирается. Нужно изменить код, например, так.
#include <stdio.h>
#include <string.h>
int main() {
char first[7] = "first";
char second[7] = "second";
char *third = strcat(first, second);
}
strcat. – αλεχολυτ Apr 22 '16 at 20:12memcpyне совершает лишних действий и работает быстрее, чемstrcat. – zed Apr 22 '16 at 20:35strcat, и лишних расходов не будет. – αλεχολυτ Apr 22 '16 at 20:44memcpyвсё равно больше нравится. – zed Apr 22 '16 at 20:58