Odpowiedzi:
C nie obsługuje ciągów znaków, które mają niektóre inne języki. Łańcuch w C jest po prostu wskaźnikiem do tablicy, charktóra jest zakończona pierwszym znakiem null. W języku C. nie ma operatora konkatenacji ciągów.
Służy strcatdo łączenia dwóch ciągów. Aby to zrobić, możesz użyć następującej funkcji:
#include <stdlib.h>
#include <string.h>
char* concat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
Nie jest to najszybszy sposób, aby to zrobić, ale nie powinieneś się tym teraz martwić. Należy zauważyć, że funkcja zwraca wywołującemu blok pamięci przydzielonej na stosie i przekazuje na własność tę pamięć. Wzywający jest odpowiedzialny freeza pamięć, gdy nie jest już potrzebna.
Wywołaj funkcję w ten sposób:
char* s = concat("derp", "herp");
// do things with s
free(s); // deallocate the string
Jeśli zdarzyło ci się przeszkadzać wydajnością, chciałbyś uniknąć wielokrotnego skanowania buforów wejściowych w poszukiwaniu terminatora zerowego.
char* concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1); // +1 to copy the null-terminator
return result;
}
Jeśli planujesz dużo pracy ze łańcuchami, być może lepiej będzie, jeśli użyjesz innego języka, który ma obsługę łańcuchów pierwszej klasy.
stpcpy, która zwraca wskaźnik do końca pierwszego ciągu:strcpy(stpcpy(result, s1), s2);
David Heffernan wyjaśnił problem w swojej odpowiedzi, a ja napisałem ulepszony kod. Zobacz poniżej.
Możemy napisać użyteczną funkcję wariadyczną do konkatenacji dowolnej liczby ciągów:
#include <stdlib.h> // calloc
#include <stdarg.h> // va_*
#include <string.h> // strlen, strcpy
char* concat(int count, ...)
{
va_list ap;
int i;
// Find required length to store merged string
int len = 1; // room for NULL
va_start(ap, count);
for(i=0 ; i<count ; i++)
len += strlen(va_arg(ap, char*));
va_end(ap);
// Allocate memory to concat strings
char *merged = calloc(sizeof(char),len);
int null_pos = 0;
// Actually concatenate strings
va_start(ap, count);
for(i=0 ; i<count ; i++)
{
char *s = va_arg(ap, char*);
strcpy(merged+null_pos, s);
null_pos += strlen(s);
}
va_end(ap);
return merged;
}
#include <stdio.h> // printf
void println(char *line)
{
printf("%s\n", line);
}
int main(int argc, char* argv[])
{
char *str;
str = concat(0); println(str); free(str);
str = concat(1,"a"); println(str); free(str);
str = concat(2,"a","b"); println(str); free(str);
str = concat(3,"a","b","c"); println(str); free(str);
return 0;
}
Wynik:
// Empty line
a
ab
abc
Pamiętaj, że powinieneś zwolnić przydzieloną pamięć, gdy stanie się niepotrzebna, aby uniknąć wycieków pamięci:
char *str = concat(2,"a","b");
println(str);
free(str);
int len-> size_t lentak jak size_tjest to właściwy typ kodu „rozmiaru”. Ponadto // room for NULL-> // room for null character NULLimplikuje pusty wskaźnik.
Zakładam, że potrzebujesz go do jednorazowych rzeczy. Zakładam, że jesteś programistą PC.
Użyj stosu, Luke. Używaj go wszędzie. Nie używaj malloc / free dla małych przydziałów, kiedykolwiek .
#include <string.h>
#include <stdio.h>
#define STR_SIZE 10000
int main()
{
char s1[] = "oppa";
char s2[] = "gangnam";
char s3[] = "style";
{
char result[STR_SIZE] = {0};
snprintf(result, sizeof(result), "%s %s %s", s1, s2, s3);
printf("%s\n", result);
}
}
Jeśli 10 KB na ciąg nie wystarczy, dodaj zero do rozmiaru i nie przejmuj się - i tak zwolnią pamięć stosu na końcu zakresów.
snprintf(result, sizeof result, "%s %s %s", s1, s2, s3);
Powinieneś użyć strcatlub lepiej strncat. Google it (słowo kluczowe to „konkatenacja”).
strncat()to piekielnie trudna funkcja w prawidłowym użyciu. Szybko, bez zaglądania do instrukcji, jaką długość określasz strncat()? Jeśli powiedziałeś „długość bufora”, po prostu ładnie pokazałeś mój punkt widzenia. Ma sprzeczny z intuicją interfejs, a gdy masz wystarczająco dużo danych, aby bezpiecznie z niego korzystać, nie musisz w pierwszej kolejności korzystać z funkcji - istnieją inne, szybsze i bardziej wydajne alternatywy (takie jak strcpy()lub memmove()), które można wykorzystać zamiast. Niemal bez względu na pytanie „czego powinienem użyć” strncat()nie jest odpowiedzią.
Nie można dodać literałów łańcuchowych takich jak w C. Musisz utworzyć bufor o rozmiarze literału ciągu 1 + literał ciągu 2 + bajt dla znaku kończącego wartość null i skopiować odpowiednie literały do tego bufora, a także upewnić się, że jest zakończony wartością null . Lub możesz użyć funkcji bibliotecznych, takich jak strcat.
Bez rozszerzenia GNU:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
res = malloc(strlen(str1) + strlen(str2) + 1);
if (!res) {
fprintf(stderr, "malloc() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
strcpy(res, str1);
strcat(res, str2);
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
Alternatywnie z rozszerzeniem GNU:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
if (-1 == asprintf(&res, "%s%s", str1, str2)) {
fprintf(stderr, "asprintf() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
Zobacz malloc , free i asprintf, aby uzyskać więcej informacji.
#include <string.h>
#include <stdio.h>
int main()
{
int a,l;
char str[50],str1[50],str3[100];
printf("\nEnter a string: ");
scanf("%s",str);
str3[0]='\0';
printf("\nEnter the string which you want to concat with string one: ");
scanf("%s",str1);
strcat(str3,str);
strcat(str3,str1);
printf("\nThe string is %s\n",str3);
}
Łączenie dowolnych dwóch ciągów w C można wykonać na co najmniej 3 sposoby: -
1) Kopiując ciąg 2 na koniec łańcucha 1
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
int i,j=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=strlen(str1);str2[j]!='\0';i++) //Copying string 2 to the end of string 1
{
str1[i]=str2[j];
j++;
}
str1[i]='\0';
printf("\nConcatenated string: ");
puts(str1);
return 0;
}
2) Kopiując ciąg 1 i ciąg 2 do ciągu 3
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX],str3[MAX];
int i,j=0,count=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=0;str1[i]!='\0';i++) //Copying string 1 to string 3
{
str3[i]=str1[i];
count++;
}
for(i=count;str2[j]!='\0';i++) //Copying string 2 to the end of string 3
{
str3[i]=str2[j];
j++;
}
str3[i]='\0';
printf("\nConcatenated string : ");
puts(str3);
return 0;
}
3) Używając funkcji strcat ()
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
strcat(str1,str2); //strcat() function
printf("\nConcatenated string : ");
puts(str1);
return 0;
}
W C tak naprawdę nie masz łańcuchów, jako ogólnego obiektu pierwszej klasy. Musisz zarządzać nimi jako tablicami znaków, co oznacza, że musisz określić, jak chcesz zarządzać swoimi tablicami. Jednym ze sposobów jest zwykłe zmienne, np. Umieszczane na stosie. Innym sposobem jest przydzielanie ich dynamicznie za pomocą malloc.
Po posortowaniu możesz skopiować zawartość jednej tablicy do drugiej, aby połączyć dwa ciągi za pomocą strcpylub strcat.
Powiedziawszy to, C ma pojęcie „literałów łańcuchowych”, które są ciągami znaków znanymi w czasie kompilacji. Kiedy zostaną użyte, będą tablicą znaków umieszczoną w pamięci tylko do odczytu. Możliwe jest jednak konkatenowanie dwóch literałów łańcuchowych, zapisując je obok siebie, tak jak w programie "foo" "bar", co spowoduje utworzenie literału ciągu „foobar”.
używając memcpy
char *str1="hello";
char *str2=" world";
char *str3;
str3=(char *) malloc (11 *sizeof(char));
memcpy(str3,str1,5);
memcpy(str3+strlen(str1),str2,6);
printf("%s + %s = %s",str1,str2,str3);
free(str3);
return memcpy(result, s1, len1);. Chociaż mikro-optymalizacja lub przynajmniej trochę kodowania w golfa, takie potencjalne ulepszenia podstawowych operacji na strunach mogą mieć wartość, biorąc pod uwagę ich duże wykorzystanie.