将一个固定长度的字符数组赋值给一个字符串

4

我有一个固定长度的字符数组,想要将其赋值给一个字符串。但是如果字符数组已满,则赋值失败。我考虑使用可以提供n的assign函数,但是这会忽略\0。例如:

std::string str;
char test1[4] = {'T', 'e', 's', 't'};
str.assign(test1);    // BAD "Test2" (or some random extra characters)
str.assign(test1, 4); // GOOD "Test"
size_t len = strlen(test1); // BAD 5

char test2[4] = {'T', 'e', '\0', 't'};
str.assign(test2);    // GOOD "Te"
str.assign(test2, 4); // BAD "Tet"
size_t len = strlen(test2); // GOOD 2

对于两种情况,如何正确地将一个固定长度的字符数组分配给一个字符串?


你能不能在每个数组中加入一个\0呢? - SingerOfTheFall
不过要注意,这个数组是固定大小的序列化数组,因此如果它已经满了就不能再添加元素,就像例子中一样。 - steveo225
1
是的,但我的意思是,如果您事先知道它们的大小,那么您可能知道它们将保存的数据的大小。为什么不将它们中的每一个增加1个字符,并在那里放置\0?我相信重写代码中的几行比每次迭代数组更容易。 - SingerOfTheFall
6个回答

9
使用“迭代器对”形式的赋值(assign)。
str.assign(test1, std::find(test1, test1 + 4, '\0'));

2

C++中的字符缓冲区只有两种:要么它们是以null结尾的,要么它们是固定长度的。因此,不建议以你所做的方式混合使用它们。如果绝对需要这样做,似乎没有其他选择,只能手动复制,直到达到最大长度或null结尾。

for (char const* i = test1; i != test1 + length and *i != '\0'; ++i)
    str += *i;

我本来希望避免这样的事情。目前我为测试代码所使用的是strncpy到另一个比原数组多1个字符(以NULL结尾)的固定数组中,然后再进行赋值。虽然对于两种情况都有效,但我不喜欢做额外的复制。你的循环确实避免了额外的复制,所以我更喜欢它。令人惊讶的是,没有一种方法可以在找到NULL终止符或达到“n”时停止。 - steveo225
在C++11中,您可以安全地调整字符串大小并将strncpy复制到其中(使用&str[0]作为起始指针),因为C++11保证了std::string的连续内部存储。不幸的是,C++03没有提供这样的保证。 - Konrad Rudolph
@steveo225:我不是。当涉及到STL时,你必须自己实现非成员函数来处理特定的使用情况,这很正常。 - eq-
@steveo225 还有一点,它不是一个NULL终止符。空指针在概念上与空字符不同。虽然C++通常将NULL定义为等效于(无符号)整数0字面量,因此它们看起来是等价的。但那是一个错误。 - Konrad Rudolph

0

你想要同时实现NULL终止和固定长度?这是非常不寻常且不建议的。你需要编写自己的函数并push_back每个单独的字符。


1
这并不是非常不寻常。它是序列化消息的一部分,用于套接字传输和文件I/O。当字符数组完全填充时,问题才会显现出来。 - steveo225

0
在第一种情况下,当您执行 str.assign(test1) 和 str.assign(test2) 时,您必须在数组中有 /0,否则这不是一个 "char*" 字符串,您不能像这样将其分配给 std::string。

0
看到了你的序列化评论 -- 可以使用 std::vector<char>std::array<char,4> 或者只是一个 4 字符数组或容器。

-1

你的第二个“坏”示例 - 那个打印出“Tet”的代码实际上是可以工作的,但你必须小心检查它的方式:

str.assign(test2, 4); // BAD "Tet"
cout << "\"" << str << "\"" << endl;

这段代码复制了确切的四个字符。如果你在Linux上通过八进制转储命令(od)运行它,比如使用my.exe | od -c,你会得到:

0000000   "   T   e  \0   t   "  \n
0000007

示例是为了说明 assign 在遇到 \0 时不会停止,而不在意内容,包括不可打印字符。 - steveo225
@steveo225:所以你需要复制到一个固定的限制或\0,以先到者为准?抱歉 - 我没有从问题中理解到这一点。 - Component 10

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