如何将char*数组转换为std::string

3

我声明了一个char *数组 char *excluded_string[50] = { 0 };

稍后,excluded_string数组的每个元素都得到一个单词。现在我想将其转换为字符串,以便我可以通过空格分隔所有单词。

std::string ss(excluded_string); 报错:

`server.cpp:171:32: error: no matching function for call to ‘std::basic_string::basic_string(char* [50])’ and large tricky explaination!


我对C++不是很熟悉,但它不应该是将字符数组转换为字符串吗?否则,在添加到字符串之前,您必须在循环或某种操作中取消引用每个字符,难道不是吗?! - dhein
2
@Zaibis 他有一个 char * 数组,基本上是一个字符串数组。 - Matthew Mcveigh
是的,如果想保留处理方式进行转换,他应该将其转换为std::string *。如果这是可能的话,他不得不这样做,对吧? - dhein
std::string可以从char *构造,因此M M.的解决方案可以做到这一点,其中char *隐式构造为std::string并附加到单个std::string中。 - Matthew Mcveigh
如果您可以使用boost,请查看https://dev59.com/MnI-5IYBdhLWcg3weoTR。 - indeterminately sequenced
4个回答

12
我声明了一个 char * 数组 char *excluded_string[50] = { 0 };
之后,ex_str 数组的每个元素都得到了一个单词。现在我想将它转换为字符串,以便我可以将所有单词用空格分隔开。
要将它转换为单个字符串:
char *excluded_string[50] = { 0 };
// excluded_string filled in the meantime
std::ostringstream buffer;  // add #include <sstream> at the top of 
                            // the file for this
for(int i = 0; i < 50; ++i)
    buffer << excluded_string[i] << " ";
std::string result = buffer.str();

编辑:几点注意事项:

  • 如果可能,请勿直接连接字符串:这将创建和销毁大量对象,并执行许多不必要的分配。

  • 如果您的代码具有严格的效率要求,请考虑预先分配/保留结果,以确保单个分配而不是重复分配。

  • 如果要连接字符串,请考虑使用 operator += 而不是 + 和 =。

编辑2:(回答评论)

如果使用 + 和 = 而不是 += 呢?

下面是连接字符串的两种方案 (s += s1 + s2 vs s += s1; s += s2) 的解决方案:

  • 使用 = 和 +:

代码:

std::string ss;
for (int i=0; i<50; i++)
    ss += std::string(excluded_string[i]) + " ";

等价的代码(根据构造的对象和分配来衡量):

std::string ss;
for (int i=0; i<50; i++)
{
    // ss += std::string(excluded_string[i]) + " ";
    std::string temp1(excluded_string[i]); // "std::string(excluded_string[i])"
    std::string temp2 = temp1 + " "; // call std::string operator+(std::string, char*)
    ss += temp2; // call std::string::operator +=(std::string)
}
  • 每次迭代都会创建temp1;
  • 为连接运算符创建temp2
  • 第二个临时变量被附加到ss。

这两个临时变量都会创建数据的副本(分配缓冲区,复制数据,释放缓冲区)。

  • 使用 += 两次:

代码:

std::string ss;
for (int i=0; i<50; i++)
{
    ss += excluded_string[i]; // call std::string::operator +=(char*)
    ss += " "; // same as above
}
  • 调用了两次std::string::operator +=;如果需要,它会分配空间,将字符串的当前内容复制到新分配的空间中,然后将新数据复制到已分配缓冲区的末尾。

  • 单个预分配空间:

预先分配/保留结果,以确保单个分配。

std::size_t total_length = 0;
for(int i = 0; i < 50; ++i)
    total_length += std::strlen(excluded_strings[i]); // assumes argument is not null
std::string ss;
ss.reserve(total_length + 51); // reserve space for the strings and spaces between
for (int i=0; i<50; i++)
{
    ss += excluded_string[i]; // calls std::string::operator +=
    ss += " "; // same as above
}
在这种情况下,operator+= 不会在内部分配空间,只是在开头进行一次操作。这仍然有点慢,因为您需要两次迭代字符串(0->49),并且需要两次迭代每个字符串(一次计算长度,一次将其复制到ss)。
如果您的 excluded_string 改为 std::vector,则会更高效,因为计算字符串长度时不需要迭代每个字符串,只需要迭代向量本身。

非常感谢!如果使用“+”和“=”代替“+=”会怎么样?你想表达的意思是:“事先分配/保留结果以确保单个分配而不是重复分配。” - user123
@utnamistim:你很棒! - user123

3

可能的解决方案

由于您注意到将指向c_str的指针数组初始化为0,因此我们可以利用这一知识仅添加实际分配的单词:

此外,在使用连接运算符operator+之前,您需要先基于原始c_str构建一个std::string。

std::string stringResult;

for (int i=0; i!=50; ++i)
    if(excluded_string[i])
    {
        stringResult.append(std::string(excluded_string[i]) + " ");
    }

原始错误的详细信息

excluded_string对象的类型是50个指向char的静态数组。你的代码已将所有指针初始化为0。
指向char的指针可以称为C字符串,更简洁地称为c_str

C++ STL提供了std::string类,其中定义了多个构造函数。其中一个构造函数使用c_str(即指向char的指针)来初始化字符串(严格来说,它将其转换为指向const char的指针,在此表达式中进行了隐式转换)。
在解决方案中,我们使用该构造函数编写以下代码:

std::string(excluded_string[i])

但是正如你所看到的,没有接受数组的构造函数,这正是你编译器错误告诉你的。

2
c_str是std::string的成员函数,而不是C字符串的名称。 - Jonathan Wakely
1
严谨地说,"隐式转换" 这个概念是不存在的。 - Lightness Races in Orbit

2
#include <iostream>
#include <string.h>
#include <algorithm>
#include <vector>
#include <sstream>
#include <iterator>
using namespace std;

int main()
{
char *arr[10] = {0};
for(int i = 0; i < 10; i++)
    arr[i] = "wang";

ostringstream str;
copy(arr, arr+10, ostream_iterator<string>(str, " "));
cout<<str.str()<<endl;
}

1
尝试使用循环:
std::string ss;

for (int i=0; i < 50; i++)
    ss += std::string(excluded_string[i]) + " ";

在最理想的情况下,您的代码将把第一个字符串放入ss中。

我认为更优化的做法是先找到 C 字符串的长度,预分配 std 字符串,并进行第二次遍历,这样就可以在不重新分配内存的情况下追加字符串。由于使用了 strlen 函数,内存已经被缓存,因此效率更高。 - dtech

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