在 C++ 中使用字符串数组拆分声明和赋值
Splitting declaration and assignment with string array in C++
可能有一个非常简单的解决方案,但我似乎无法弄清楚。我可以找到无数关于如何在 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]'
您的第一个示例在堆栈上分配数组,这是唯一可能的,因为编译器知道大小(因为所有字符串都是固定长度并在声明期间提供)。
当你将声明和初始化分开时,你的编译器无法知道在堆栈上分配多少内存,所以你需要将你的类型更改为指针(它具有固定大小,无论它指向什么到):
static const char** desc;
然后使用new
为数组分配足够的内存:
desc = new const char*[3]{ "apple", "banana", "orange" };
然而,这意味着您现在还必须 delete[]
desc
指向的数组,否则会发生内存泄漏。
更好的方法是使用像 std::vector
和 std::string
这样的现代容器类型:
static std::vector<std::string> desc;
然后
desc.push_back("apple");
desc.push_back("banana");
desc.push_back("orange");
这些 类 会在后台为您处理所有令人讨厌的内存管理。
另一种选择,如果你真的想要一个原始数组,并且不想依赖 new[]
和 delete[]
是声明一个具有足够 space 的固定大小数组你的字符串是这样的:
static const char desc[3][128];
然后将字符串值复制到该内存块中:
std::strcpy(desc[0], "apple");
std::strcpy(desc[1], "banana");
std::strcpy(desc[2], "orange");
但是我真的不建议这样做,因为当您添加或删除字符串,或更改它们的长度等时,您可能会在长 运行 中遇到错误
您的声明是错误的,因为当您编写 char [3] 时,它会使您的字符数组包含 3 个字符,而不是包含 3 个不同的无限字符的数组。
I currently have a declaration with assignment that looks something like this:
static const char *desc[3] = { "apple", "banana", "orange" };
这不是“作业”。这是初始化。
I can't seem to figure out how to do the assignment.
数组不可赋值。您不能分配给数组。
如果你想在初始化后修改数组的元素,你要么需要遍历每个元素并一一赋值:
const char *arr[] = {"apple", "banana", "orange"};
static_assert(std::size(arr) == std::size(desc));
std::copy_n(arr, std::size(arr), desc);
或者您可以将数组包装成一个class,在这种情况下,将为您生成一个赋值运算符。这种数组包装器有一个标准模板 std::array
:
static std::array<const char*, 3> desc;
// later
desc = {"apple", "banana", "orange"};
Max Vollmer 给出了一些很好的建议,尽管在 "modern C++" (post C++11) 中不鼓励使用 new
和原始指针。参见[1](Sutter是C++标准委员会的成员,所以他知道他的事。
所以如果你想要 "true C++ way" 有一个字符串数组,那么你应该去:
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";
可能有一个非常简单的解决方案,但我似乎无法弄清楚。我可以找到无数关于如何在 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]'
您的第一个示例在堆栈上分配数组,这是唯一可能的,因为编译器知道大小(因为所有字符串都是固定长度并在声明期间提供)。
当你将声明和初始化分开时,你的编译器无法知道在堆栈上分配多少内存,所以你需要将你的类型更改为指针(它具有固定大小,无论它指向什么到):
static const char** desc;
然后使用new
为数组分配足够的内存:
desc = new const char*[3]{ "apple", "banana", "orange" };
然而,这意味着您现在还必须 delete[]
desc
指向的数组,否则会发生内存泄漏。
更好的方法是使用像 std::vector
和 std::string
这样的现代容器类型:
static std::vector<std::string> desc;
然后
desc.push_back("apple");
desc.push_back("banana");
desc.push_back("orange");
这些 类 会在后台为您处理所有令人讨厌的内存管理。
另一种选择,如果你真的想要一个原始数组,并且不想依赖 new[]
和 delete[]
是声明一个具有足够 space 的固定大小数组你的字符串是这样的:
static const char desc[3][128];
然后将字符串值复制到该内存块中:
std::strcpy(desc[0], "apple");
std::strcpy(desc[1], "banana");
std::strcpy(desc[2], "orange");
但是我真的不建议这样做,因为当您添加或删除字符串,或更改它们的长度等时,您可能会在长 运行 中遇到错误
您的声明是错误的,因为当您编写 char [3] 时,它会使您的字符数组包含 3 个字符,而不是包含 3 个不同的无限字符的数组。
I currently have a declaration with assignment that looks something like this:
static const char *desc[3] = { "apple", "banana", "orange" };
这不是“作业”。这是初始化。
I can't seem to figure out how to do the assignment.
数组不可赋值。您不能分配给数组。
如果你想在初始化后修改数组的元素,你要么需要遍历每个元素并一一赋值:
const char *arr[] = {"apple", "banana", "orange"};
static_assert(std::size(arr) == std::size(desc));
std::copy_n(arr, std::size(arr), desc);
或者您可以将数组包装成一个class,在这种情况下,将为您生成一个赋值运算符。这种数组包装器有一个标准模板 std::array
:
static std::array<const char*, 3> desc;
// later
desc = {"apple", "banana", "orange"};
Max Vollmer 给出了一些很好的建议,尽管在 "modern C++" (post C++11) 中不鼓励使用 new
和原始指针。参见[1](Sutter是C++标准委员会的成员,所以他知道他的事。
所以如果你想要 "true C++ way" 有一个字符串数组,那么你应该去:
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";