Pracuję w C i muszę połączyć kilka rzeczy.
Teraz mam to:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
Teraz, jeśli masz doświadczenie w C, jestem pewien, że zdajesz sobie sprawę, że to powoduje błąd segmentacji, gdy próbujesz go uruchomić. Jak mam to obejść?
c
string
concatenation
The.Anti.9
źródło
źródło
Odpowiedzi:
W C „ciągi” są zwykłymi
char
tablicami. Dlatego nie można bezpośrednio łączyć ich z innymi „ciągami”.Możesz użyć
strcat
funkcji, która dodaje ciąg wskazany przezsrc
na końcu ciągu wskazanego przezdest
:Oto przykład z cplusplus.com :
W przypadku pierwszego parametru musisz podać sam bufor docelowy. Bufor docelowy musi być buforem tablicy znaków. Na przykład:
char buffer[1024];
Upewnij się, że pierwszy parametr ma wystarczającą ilość miejsca do zapisania w nim tego, co próbujesz skopiować. Jeśli jest to dostępne, bezpieczniej jest używać funkcji takich jak:
strcpy_s
istrcat_s
gdzie wyraźnie musisz określić rozmiar bufora docelowego.Uwaga : Literału łańcuchowego nie można użyć jako bufora, ponieważ jest on stałą. Dlatego zawsze musisz przydzielić tablicę char dla bufora.
Zwracaną wartość
strcat
można po prostu zignorować, po prostu zwraca ten sam wskaźnik, który został przekazany jako pierwszy argument. Jest tam dla wygody i pozwala łączyć połączenia w jedną linię kodu:Twój problem można rozwiązać w następujący sposób:
źródło
Unikaj używania
strcat
w kodzie C. Najczystszym i, co najważniejsze, najbezpieczniejszym sposobem jest użyciesnprintf
:Niektórzy komentatorzy podnieśli problem, że liczba argumentów może nie pasować do ciągu formatu, a kod nadal będzie się kompilował, ale większość kompilatorów już wydaje ostrzeżenie, jeśli tak jest.
źródło
snprintf()
jest BIG no no.sizeof(x)
isizeof x
. Notacja w nawiasach zawsze działa, a notacja w nawiasach działa tylko czasami, dlatego zawsze używaj notacji w nawiasach; jest to prosta zasada do zapamiętania i jest bezpieczna. Wchodzi to w argument religijny - byłem zaangażowany w dyskusje z tymi, którzy sprzeciwiają się wcześniej - ale prostota „zawsze używaj nawiasów” przeważa nad wszelką zasługą, by ich nie używać (IMNSHO, oczywiście). Przedstawiono to dla zachowania równowagi.Ludzie, użyj str n cpy (), str n cat () lub s n printf ().
Przekroczenie przestrzeni bufora spowoduje usunięcie wszystkiego, co nastąpi w pamięci!
(I pamiętaj, aby pozostawić miejsce na końcowy znak zerowy „\ 0”!)
źródło
strncpy()
. To nie jest „bezpieczniejsza” wersjastrcpy()
. Docelowa tablica znaków może być niepotrzebnie wypełniona dodatkowymi'\0'
znakami lub, co gorsza, może pozostać nieokreślona (tj. Nie ciąg znaków). (Został zaprojektowany do użytku z rzadko używaną strukturą danych, tablicą znaków wypełnioną do końca zerowymi lub więcej'\0'
znakami.)Ciągi można także łączyć w czasie kompilacji.
źródło
Również malloc i realloc są przydatne, jeśli nie wiesz z góry, ile łańcuchów jest konkatenowanych.
źródło
num_words>INT_MAX
, być może powinieneś użyćsize_t
doi
Nie zapomnij zainicjować bufora wyjściowego. Pierwszym argumentem dla strcat musi być łańcuch zakończony znakiem null z wystarczającą ilością miejsca przeznaczonego dla łańcucha wynikowego:
źródło
Jak zauważyli ludzie, znacznie poprawiła się obsługa łańcuchów. Możesz więc chcieć nauczyć się korzystać z biblioteki ciągów C ++ zamiast ciągów w stylu C. Jednak tutaj jest rozwiązanie w czystym C.
Nie jestem pewien, czy jest to poprawne / bezpieczne, ale w tej chwili nie mogłem znaleźć lepszego sposobu na zrobienie tego w ANSI C.
źródło
<string.h>
jest w stylu C ++. Chcesz"string.h"
. Obliczasz takżestrlen(s1)
dwa razy, co nie jest potrzebne.s3
powinno byćtotalLenght+1
długie."string.h"
to nonsens.#include <string.h>
jest poprawny C. Użyj nawiasów kątowych dla nagłówków standardowych i systemowych (w tym<string.h>
), cudzysłowów dla nagłówków, które są częścią twojego programu. (#include "string.h"
będzie działać, jeśli nie masz własnego pliku nagłówka o tej nazwie, ale<string.h>
mimo to użyj .)Niezdefiniowanym zachowaniem jest próba modyfikacji literałów łańcuchowych, co jest coś takiego:
spróbuje to zrobić. Spróbuje przyczepić
name
ciąg do końca dosłownego ciągu"Hello, "
, który nie jest dobrze zdefiniowany.Spróbuj czegoś takiego. Osiąga to, co próbujesz zrobić:
To tworzy obszar buforowy, który jest dozwolony zostać zmodyfikowane, a następnie kopiuje zarówno ciągiem znaków i inne teksty do niego. Uważaj tylko na przepełnienia bufora. Jeśli kontrolujesz dane wejściowe (lub sprawdzasz je wcześniej), możesz użyć buforów o stałej długości, takich jak ja.
W przeciwnym razie należy zastosować strategie ograniczania ryzyka, takie jak przydzielenie wystarczającej ilości pamięci ze sterty, aby mieć pewność, że można ją obsłużyć. Innymi słowy, coś takiego:
źródło
Pierwszy argument strcat () musi być w stanie pomieścić wystarczającą ilość miejsca na połączony ciąg. Przydziel więc bufor z wystarczającą ilością miejsca, aby otrzymać wynik.
strcat () połączy drugi argument z pierwszym argumentem i zapisze wynik w pierwszym argumencie, zwrócony char * jest po prostu pierwszym argumentem i tylko dla twojej wygody.
Nie otrzymujesz nowo przydzielonego ciągu z połączonym pierwszym i drugim argumentem, który, jak sądzę, oczekiwałeś na podstawie twojego kodu.
źródło
Najlepszym sposobem na to bez ograniczonego rozmiaru bufora jest użycie asprintf ()
źródło
char *
, nieconst char *
. Wartość zwrotna będzie musiała zostać przekazana dofree
.asprintf
jest tylko rozszerzeniem GNU.Jeśli masz doświadczenie w C, zauważysz, że ciągi znaków są tylko tablicami znaków, w których ostatni znak jest znakiem pustym.
Jest to dość niewygodne, ponieważ musisz znaleźć ostatnią postać, aby coś dodać.
strcat
zrobi to za ciebie.Zatem strcat przeszukuje pierwszy argument pod kątem znaku zerowego. Następnie zastąpi to treścią drugiego argumentu (dopóki nie zakończy się na null).
Teraz przejdźmy do twojego kodu:
Tutaj dodajesz coś do wskaźnika do tekstu „TEKST” (typ „TEKST” to const char *. Wskaźnik.).
To zwykle nie zadziała. Również modyfikacja tablicy „TEKST” nie będzie działać, ponieważ zwykle jest umieszczana w stałym segmencie.
To może działać lepiej, z tym wyjątkiem, że ponownie próbujesz zmodyfikować teksty statyczne. strcat nie przydziela nowej pamięci dla wyniku.
Zamiast tego zaproponowałbym coś takiego:
Przeczytaj dokumentację,
sprintf
aby sprawdzić dostępne opcje.A teraz ważny punkt:
Upewnij się, że bufor ma wystarczającą ilość miejsca do przechowywania tekstu ORAZ znaku null. Istnieje kilka funkcji, które mogą ci pomóc, np. Strncat i specjalne wersje printf, które przydzielają ci bufor. Brak zapewnienia rozmiaru bufora spowoduje uszkodzenie pamięci i zdalne błędy, które można wykorzystać.
źródło
"TEXT"
jestchar[5]
, nieconst char*
. Rozkłada sięchar*
w większości kontekstów. Ze względu na kompatybilność wsteczną literały łańcuchowe nie sąconst
, ale próba ich modyfikacji skutkuje niezdefiniowanym zachowaniem. (W C ++ literały łańcuchowe toconst
.)Możesz napisać własną funkcję, która robi to samo,
strcat()
ale nic nie zmienia:Jeśli oba łańcuchy razem mają więcej niż 1000 znaków, spowoduje to odcięcie łańcucha na 1000 znaków. Możesz zmienić wartość według
MAX_STRING_LENGTH
własnych potrzeb.źródło
strlen(str1) + strlen(str2)
, ale piszeszstrlen(str1) + strlen(str2) + 1
znaki. Czy naprawdę możesz napisać własną funkcję?return buffer; free(buffer);
sizeof(char) == 1
(poza tym są jeszcze inne subtelniejsze błędy ...) Czy rozumiesz teraz, dlaczego nie musisz pisać własnej funkcji?free(buffer);
.free(buffer);
poreturn buffer;
nigdy nie jest wykonywany, zobacz to w debuggerze;) Widzę teraz: tak, musisz zwolnić pamięć wmain
funkcjiZakładając, że masz char [fixed_size] zamiast char *, możesz użyć pojedynczego, kreatywnego makra, aby zrobić to wszystko jednocześnie z
<<cout<<like
zamówieniem („raczej% s rozłączony% s \ n”, „niż”, „printf format stylu ”). Jeśli pracujesz z systemami wbudowanymi, ta metoda pozwoli ci również pominąć malloc i dużą*printf
rodzinę funkcji takich jaksnprintf()
(To powstrzymuje dietlibc przed narzekaniem na * printf też)źródło
źródło
Próbujesz skopiować ciąg na adres przydzielony statycznie. Musisz kot w buforze.
Konkretnie:
...fantastyczna okazja...
Miejsce docelowe
...fantastyczna okazja...
http://www.cplusplus.com/reference/clibrary/cstring/strcat.html
Jest tu także przykład.
źródło
To było moje rozwiązanie
ale musisz określić, ile ciągów chcesz połączyć
źródło
Spróbuj czegoś podobnego do tego:
źródło