Jak połączyć dwa ciągi w C ++?

100

Mam zmienną klasy prywatnej, char name[10]do której chciałbym dodać .txtrozszerzenie, aby móc otworzyć plik obecny w katalogu.

Jak mam się do tego zabrać?

Byłoby lepiej, gdybyśmy utworzyli nową zmienną łańcuchową, która przechowuje połączony łańcuch.

Slashr
źródło

Odpowiedzi:

160

Przede wszystkim nie używaj char*lub char[N]. Użyj std::string, a wszystko inne stanie się takie proste!

Przykłady,

std::string s = "Hello";
std::string greet = s + " World"; //concatenation easy!

Łatwe, prawda?

Teraz, jeśli potrzebujesz char const *z jakiegoś powodu, na przykład gdy chcesz przejść do jakiejś funkcji, możesz to zrobić:

some_c_api(s.c_str(), s.size()); 

zakładając, że ta funkcja jest zadeklarowana jako:

some_c_api(char const *input, size_t length);

Odkryj std::stringsiebie, zaczynając od tego miejsca:

Mam nadzieję, że to pomoże.

Nawaz
źródło
3
Jaka jest złożoność czasowa tej konkatenacji ciągów?
d34th4ck3r
@ d34th4ck3r: To jest liniowe.
Nawaz,
30

Skoro jest to C ++, to dlaczego nie użyć std::stringzamiast char*? Konkatenacja będzie trywialna:

std::string str = "abc";
str += "another";
nogard
źródło
1
Warto zauważyć, że trywialne użycie wiąże się z nietrywialną ceną w odniesieniu do wydajności środowiska uruchomieniowego. W najgorszym przypadku następuje operator+=zarówno zwolnienie, jak i alokacja. Alokacje stert należą do najdroższych operacji, które często wykonujemy.
Niespodziewane
15

Jeśli programowałeś w C, zakładając, że namenaprawdę jest to tablica o stałej długości, jak mówisz, musisz zrobić coś takiego:

char filename[sizeof(name) + 4];
strcpy (filename, name) ;
strcat (filename, ".txt") ;
FILE* fp = fopen (filename,...

Widzisz teraz, dlaczego wszyscy polecają std::string?

TonyK
źródło
1
Nie widzisz, że facet zadał pytanie w C ++, a nie w C?
IcyFlame,
21
Czy nie widzisz, że powiedziałem „Gdybyś programował…”?
TonyK,
Czy nie uważasz, że ta odpowiedź jest nieistotna w przypadku tego pytania?
IcyFlame,
9
Myślę, że jest to istotne, ponieważ „facet” używa znaku zamiast std :: string. Ponadto pokazuje wyraźny sposób konkatenacji, który nie został pokazany w najczęściej głosowanej odpowiedzi. Przynajmniej czegoś się z tym nauczyłem.
gvegayon
1
Pokazuje również metodę łączenia ciągów bez dynamicznej alokacji pamięci. O ile się nie mylę, operator std :: string + = wymaga możliwej ponownej alokacji.
Ashley Duncan
7

Istnieje funkcja strcat () z przeportowanej biblioteki C, która wykona za Ciebie konkatenację typu „łańcuch w stylu C”.

BTW, mimo że C ++ ma wiele funkcji do obsługi ciągów w stylu C, może być korzystne, jeśli spróbujesz wymyślić własną funkcję, która to robi, na przykład:

char * con(const char * first, const char * second) {
    int l1 = 0, l2 = 0;
    const char * f = first, * l = second;

    // step 1 - find lengths (you can also use strlen)
    while (*f++) ++l1;
    while (*l++) ++l2;

    char *result = new char[l1 + l2];

    // then concatenate
    for (int i = 0; i < l1; i++) result[i] = first[i];
    for (int i = l1; i < l1 + l2; i++) result[i] = second[i - l1];

    // finally, "cap" result with terminating null char
    result[l1+l2] = '\0';
    return result;
}

...i wtedy...

char s1[] = "file_name";
char *c = con(s1, ".txt");

... czego wynikiem jest file_name.txt.

Możesz również ulec pokusie, aby napisać własny, operator +jednak operator IIRC przeciąża tylko wskaźniki jako argumenty.

Nie zapominaj również, że wynik w tym przypadku jest przydzielany dynamicznie, więc możesz chcieć wywołać na nim funkcję delete, aby uniknąć wycieków pamięci, lub możesz zmodyfikować funkcję, aby używała tablicy znaków przydzielonej stosowi, pod warunkiem, że ma ona wystarczającą długość.

dtech
źródło
Zobacz mój komentarz do odpowiedzi IcyFlame.
TonyK,
3
Jest też strncat()funkcja, która zwykle jest lepszą alternatywą
nogard
@nogard: strncatnie ma tu znaczenia, ponieważ znamy już długość drugiego parametru ".txt". Tak by było strncat(name, ".txt", 4), co nam nic nie daje.
TonyK,
0

Lepiej jest używać klas ciągów C ++ zamiast ciągów w starym stylu, życie byłoby znacznie łatwiejsze.

jeśli masz istniejący łańcuch w starym stylu, możesz zamienić go na klasę string

    char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    cout<<greeting + "and there \n"; //will not compile because concat does \n not work on old C style string
    string trueString = string (greeting);
    cout << trueString + "and there \n"; // compiles fine
    cout << trueString + 'c'; // this will be fine too. if one of the operand if C++ string, this will work too
i.AsifNoor
źródło
0

C ++ 14

std::string great = "Hello"s + " World"; // concatenation easy!

Odpowiedź na pytanie:

auto fname = ""s + name + ".txt";
SM
źródło
-2
//String appending
#include <iostream>
using namespace std;

void stringconcat(char *str1, char *str2){
    while (*str1 != '\0'){
        str1++;
    }

    while(*str2 != '\0'){
        *str1 = *str2;
        str1++;
        str2++;
    }
}

int main() {
    char str1[100];
    cin.getline(str1, 100);  
    char str2[100];
    cin.getline(str2, 100);

    stringconcat(str1, str2);

    cout<<str1;
    getchar();
    return 0;
}
Kartik
źródło