如何在C++中连接两个字符串?

144

我有一个私有类变量char name[10],我想要添加.txt扩展名,以便我可以打开目录中的文件。

我该如何处理?

最好创建一个新的字符串变量来保存连接后的字符串。

8个回答

217
首先,不要使用char*char[N]。请使用std::string,然后其他所有事情都会变得非常容易!
例子,
std::string s = "Hello";
std::string greet = s + " World"; //concatenation easy!

简单易懂,不是吗?

现在如果您出于某些原因需要char const *,例如当您想要传递给某个函数时,可以这样做:

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

假设这个函数被声明为:

some_c_api(char const *input, size_t length);

从这里开始探索std::string


5
这个字符串连接的时间复杂度是多少? - d34th4ck3r
1
@d34th4ck3r:它是线性的。 - Nawaz
以内存和性能为代价变得容易。不要过度使用字符串! - Epic Speedy
1
@EpicSpeedy: 你要在O(n)的时间内连接O(n)个字符,这可不容易啊! - undefined

40

既然是C ++,为什么不使用std :: string而不是char *? 连接将变得微不足道:

std::string str = "abc";
str += "another";

3
值得注意的是,虽然使用 operator+= 看似简单,但它会对运行时性能造成不可忽视的影响。最糟糕的情况是,operator+= 会执行一次释放内存和一次申请内存的操作。堆内存分配通常是我们常见的最耗费性能的操作之一。 - IInspectable

23

如果你在使用C语言进行编程,并且假设像你说的那样name是一个固定长度的数组,那么你需要按照以下方式进行操作:

如果您正在使用C进行编程,假设name确实像您所说的那样是一个固定长度的数组,则必须执行以下操作:

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

你现在明白为什么每个人都推荐使用 std::string 了吧?


1
你不觉得这个答案和这个问题无关吗? - IcyFlame
18
我认为这很重要,因为“那个人”使用char而不是std::string。此外,它展示了一种明确的连接方式,这在得票最高的答案中没有展示。至少我从中学到了东西。 - gvegayon
1
这也展示了一种在不使用动态内存分配的情况下进行字符串连接的方法。除非我错了,std::string operator += 需要可能的重新分配。 - Ashley Duncan
截至2023年3月9日,这个答案是绝对相关的。感谢@TonyK!(我正在处理一个主要使用C语言的旧项目。) - Ed Graham

8

有一个从迁移的C库中来的strcat()函数可以为你完成"C风格字符串"的拼接。

顺便说一下,尽管C++有许多处理C风格字符串的函数,但对于你自己编写一个类似以下的函数可能是有益的:

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

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

    // allocate a buffer including terminating null char
    char *result = new char[l1 + l2 + 1];

    // 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;
}

...and then...

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

...其结果为file_name.txt

您可能会想要编写自己的operator +,但是我IRC中指出只允许使用指针作为参数的运算符重载。

此外,请不要忘记,在这种情况下,结果是动态分配的,因此您可能希望调用delete以避免内存泄漏,或者您可以修改函数以使用堆栈分配的字符数组,当然前提是它具有足够的长度。


请看我对IcyFlame答案的评论。 - TonyK
3
还有一个strncat()函数通常是更好的选择。 - nogard
@nogard:strncat在这里是无关紧要的,因为我们已经知道第二个参数““.txt”的长度。所以它只是strncat(name, ".txt", 4),这并没有给我们带来任何好处。 - TonyK

4

C++14

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

对问题的回答:

auto fname = ""s + name + ".txt";

1
谢谢!我不知道在字面上加上 's' 可以将其转换为对象类型的字符串。这非常方便!让我想起了 Python。 - Anchith Acharya
1
只有在声明 using namespace std::string_literals; 的情况下才返回翻译文本。 - masher
@masher 我收到了“错误:std没有成员string_literals”的错误信息。 - john k
2
@johnktejik 请记得按照C++14的标准编译源代码。 - 273K

0

0

使用C++字符串类而不是旧式的C字符串会更好,生活会变得更加轻松。

如果您有现有的旧式字符串,可以将其转换为字符串类。

    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

-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;
}

std::strcat()? - Scheff's Cat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接