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])' 和大的棘手解释!

4

4 回答 4

12

我声明了 char * array 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();

编辑:一些注意事项:

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

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

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

编辑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)。

如果您的 exclude_string 是一个 std::vector ,它会更有效,因为计算字符串长度不会迭代每个字符串,只是向量)。

于 2013-08-23T10:44:22.917 回答
3

可能的解决方案

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

此外,您需要先基于原始 c_str 构建一个 std::string ,然后才能使用 concatenation operator+

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 的指针的静态数组。您的代码将所有指向 char 的指针初始化为 0。指向 char 的指针可以称为C 字符串,或者更简洁地称为c_str

C++ STL 为您提供了定义了多个构造函数std::string的类。其中一个采用c_str(即指向 char 的指针)来初始化字符串(迂回地,将其转换为指向 const char 的指针,这是此表达式中的隐式转换)。 这个构造函数是我们在编写时在解决方案中使用的构造函数:

std::string(excluded_string[i])

但正如您所看到的,没有构造函数采用c_str数组,这正是编译器错误告诉您的内容。

编辑:措辞,感谢轨道评论中的Lightness Races 。强制转换的意思实际上是显式转换)。

于 2013-08-23T10:43:42.703 回答
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;
}
于 2013-08-25T09:24:00.983 回答
1

尝试循环:

std::string ss;

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

您的代码在最佳情况下会将第一个字符串放入ss.

于 2013-08-23T10:29:11.587 回答