在C ++中用字符串数组拆分声明和赋值

问题描述 投票:1回答:5

可能有一个非常简单的解决方案,但是我似乎无法弄清楚。我可以找到无数有关如何在C ++中创建字符串数组的示例,但找不到能说明如何使分配分开的示例。

我目前有一个带有赋值的声明,看起来像这样:

static const char *desc[3] = { "apple", "banana", "orange" };

我想做的是将声明和赋值拆分为单独的语句。声明:

static const char *desc[3];

...但是我似乎无法弄清楚如何完成作业。我尝试了以下方法:

desc = { "apple", "banana", "orange" }; // Expression must have a modifiable lvalue. error: assigning to an array from an initializer list
*desc = { "apple", "banana", "orange" }; // Too many initializer values. error: cannot convert '<brace-enclosed initializer list>' to 'const char*' in assignment
desc[3] = { "apple", "banana", "orange" }; // Too many initializer values. error: cannot convert '<brace-enclosed initializer list>' to 'const char*' in assignment
*desc[3] = { "apple", "banana", "orange" }; // Expression must have a modifiable lvalue. error: assignment of read-only location '* desc[3]'
c++ arrays variable-assignment assign variable-declaration
5个回答
2
投票

您的第一个示例在堆栈上分配数组,这仅是可能的,因为编译器知道大小(因为所有字符串都是固定长度,并且在声明期间提供)。>>

当您分开声明和初始化时,编译器无法知道要在堆栈上分配多少内存,因此您需要将类型更改为指针(无论指针指向什么,其大小都是固定的):

static const char** desc;

然后使用new为数组分配足够的内存:

desc = new const char*[3]{ "apple", "banana", "orange" };

但是这意味着您现在还必须delete[]指向desc指向的数组,否则会发生内存泄漏。

更好的方法是使用现代容器类型,例如std::vectorstd::string

static std::vector<std::string> desc;

然后

desc.push_back("apple");
desc.push_back("banana");
desc.push_back("orange");

这些类在后台为您处理所有麻烦的内存管理。


另一种选择,如果您真的想要一个原始数组,并且不想依赖new[]delete[],则声明一个固定大小的数组,该数组具有足够的空间来容纳您的字符串,如下所示:

static const char desc[3][128];

然后将字符串值复制到该内存块中:

std::strcpy(desc[0], "apple");
std::strcpy(desc[1], "banana");
std::strcpy(desc[2], "orange");

但是我真的不建议您这样做,因为从长远来看,当您添加或删除字符串,或更改其长度等时,您可能会遇到错误,因此冒着风险。>>

我目前有一个带有赋值的声明,看起来像这样:

static const char *desc[3] = { "apple", "banana", "orange" };

这不是“任务”。这是初始化。

我似乎无法弄清楚如何完成作业。

数组不可分配。您无法分配给数组。

如果要在初始化数组后修改数组的元素,则需要迭代每个元素并逐个分配它们:

const char *arr[] = {"apple", "banana", "orange"};
static_assert(std::size(arr) == std::size(desc));
std::copy_n(arr, std::size(arr), desc);

或者您可以将数组包装到一个类中,在这种情况下,将为您生成一个赋值运算符。有一个用于此类数组包装器std::array的标准模板:

static std::array<const char*, 3> desc;
// later
desc = {"apple", "banana", "orange"};

Max Vollmer提供了一些极好的建议,尽管在“现代C ++”中不建议使用new和原始指针(在C ++ 11之后)。参见[1](Sutter是C ++标准委员会的成员,所以他知道他的事。

因此,如果您要使用“真正的C ++方式”以包含字符串数组,那么应该使用:

std::vector<std::string> dest_a;
dest_a.push_back("apple");
dest_a.push_back("banana");
// or
std::vector<std::string> dest_b(3);
dest_b[0] = "orange";
dest_b[1] = "pear";
dest_b[2] = "plumb";

如果您需要

原始指针,我想我会选择旧的C strcpy函数。

尽管,您可能只是在寻找它。

  static const char *ptr[2];
  ptr[0] = "orange";
  ptr[1] = "pear";

[1] https://herbsutter.com/elements-of-modern-c-style/

您的声明是错误的,因为当您编写char [3]时,它将使您的字符数组包含3个字符,而不是包含3个不同的无限字符的数组。

您的第一次尝试算作分配(您不能使用const进行,而不是初始化。)>

此定义应该起作用:

const char*[] foo::desc = { "apple", "banana", "orange" };

对于这样的声明:

class foo {
    const static char*[] desc;
};

1
投票

我目前有一个带有赋值的声明,看起来像这样:


0
投票

Max Vollmer提供了一些极好的建议,尽管在“现代C ++”中不建议使用new和原始指针(在C ++ 11之后)。参见[1](Sutter是C ++标准委员会的成员,所以他知道他的事。


-1
投票

您的声明是错误的,因为当您编写char [3]时,它将使您的字符数组包含3个字符,而不是包含3个不同的无限字符的数组。


-2
投票

您的第一次尝试算作分配(您不能使用const进行,而不是初始化。)>

此定义应该起作用:

© www.soinside.com 2019 - 2024. All rights reserved.