英文:
How to construct a `std::string` from a buffer that may or may not contain a null?
问题
以下是翻译好的部分:
我有一个缓冲区(为简单起见,假设是一个固定大小的字符数组),我想要从中构造一个std::string
。该缓冲区可能是以null结尾的,或者其内容可能延伸到并包括最后一个字符。如果缓冲区包含一个或多个null字符,它们不应该出现在生成的string
中。复制应该在第一个null字符或缓冲区的末尾,以先到者为止。
这似乎是一个常见的需求,但在查看std::string
API时,解决方案并不立即明显。
std::string
有一个通过const char *
和长度接受范围的构造函数,但愉快地继续复制null字符并将它们复制到字符串中。- 在构造
string
之前在缓冲区上调用std::strlen()
不是一个选项,因为strlen
首先要求字符串以null结尾。 - 我们可以使用上述构造函数来创建一个包含null字符的
string
,然后将其调整大小为第一个null字符之前,但这会浪费内存,因为string
将被过度分配。
什么是最佳和/或惯用的方法来做到这一点?
英文:
I have a buffer (for simplicity, let's say a fixed-sized array) of char
that I would like to construct a std::string
from. Said buffer may be null-terminated or its contents may run up to and include the very last character. If the buffer does contain one or more nulls, they should not end up in the resulting string
. Copying should stop at the first null or the end of the buffer, whichever comes first.
This seems like a common enough thing to want to do, but the solution is not immediately obvious to me while looking at the std::string
API.
std::string
has a constructor taking a range viaconst char *
and a length, but happily continues past nulls and copies them into the string.- Calling
std::strlen()
on the buffer before constructing thestring
isn't an option asstrlen
requires the string to be null terminated in the first place. - We could use the above constructor to make a
string
containing nulls and then resize it down to just before the first null, but that wastes memory as thestring
will be over-allocated.
What is the best and/or idiomatic way to do this?
答案1
得分: 14
The answer, as with so many questions regarding the C++ standard library, is to think about the problem in terms of iterators.
std::string stringFromBuffer(const auto & buffer)
{
return std::string(std::begin(buffer),
std::find(std::begin(buffer), std::end(buffer), 'std::string stringFromBuffer(const auto & buffer)
{
return std::string(std::begin(buffer),
std::find(std::begin(buffer), std::end(buffer), '\0'));
}
'));
}
std::string
has a constructor taking two iterators, first
and last
. The string
will be created by copying from first
up until but not including last
.
So first
should obviously be the beginning of our buffer, while last
should either be the first null in our buffer or one past the end of the buffer. Conveniently, that is exactly what a call to std::find
searching the buffer for '\0' will return.
英文:
The answer, as with so many questions regarding the C++ standard library, is to think about the problem in terms of iterators.
std::string stringFromBuffer(const auto & buffer)
{
return std::string(std::begin(buffer),
std::find(std::begin(buffer), std::end(buffer), 'std::string stringFromBuffer(const auto & buffer)
{
return std::string(std::begin(buffer),
std::find(std::begin(buffer), std::end(buffer), '\0'));
}
'));
}
std::string
has a constructor taking two iterators, first
and last
. The string
will be created by copying from first
up until but not including last
.
So first
should obviously be the beginning of our buffer, while last
should either be the first null in our buffer or one past the end of the buffer. Conveniently, that is exactly what a call to std::find
searching the buffer for '\0'
will return.
答案2
得分: 2
以下是您提供的代码的中文翻译:
这是一个针对已知大小的字符数组的简单方法。它类似于Parker的答案,但是在构造函数参数中完成,并且特定于一个由字符组成的数组的问题。
#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // 输出abcde
// const char c[] = { 'a','b','#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // 输出abcde
// const char c[] = { 'a','b','\0','d','\0' }; // 测试替代方案:输出ab
// const char c[] = { 'a','b','\0','d','e' }; // 测试替代方案:输出ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
','d','#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // 输出abcde
// const char c[] = { 'a','b','\0','d','\0' }; // 测试替代方案:输出ab
// const char c[] = { 'a','b','\0','d','e' }; // 测试替代方案:输出ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
' }; // 测试替代方案:输出ab
// const char c[] = { 'a','b','#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // 输出abcde
// const char c[] = { 'a','b','\0','d','\0' }; // 测试替代方案:输出ab
// const char c[] = { 'a','b','\0','d','e' }; // 测试替代方案:输出ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
','d','e' }; // 测试替代方案:输出ab
std::string s{c, std::find(c, c + sizeof c, '#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // 输出abcde
// const char c[] = { 'a','b','\0','d','\0' }; // 测试替代方案:输出ab
// const char c[] = { 'a','b','\0','d','e' }; // 测试替代方案:输出ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
')};
std::cout << s << '\n';
return 0;
}
请注意,这段代码演示了如何从字符数组中创建一个字符串,以空字符('\0')作为终止符。
英文:
Here is a simple way for an array of chars of known size. It's similar to Parker's answer but is just done in the constructor argument and is specific to the question of an array of chars.
#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // prints abcde
// const char c[] = { 'a','b','#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // prints abcde
// const char c[] = { 'a','b','\0','d','\0' }; // test alternate: prints ab
// const char c[] = { 'a','b','\0','d','e' }; // test alternate: prints ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
','d','#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // prints abcde
// const char c[] = { 'a','b','\0','d','\0' }; // test alternate: prints ab
// const char c[] = { 'a','b','\0','d','e' }; // test alternate: prints ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
' }; // test alternate: prints ab
// const char c[] = { 'a','b','#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // prints abcde
// const char c[] = { 'a','b','\0','d','\0' }; // test alternate: prints ab
// const char c[] = { 'a','b','\0','d','e' }; // test alternate: prints ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
','d','e' }; // test alternate: prints ab
std::string s{c, std::find(c, c + sizeof c, '#include <algorithm> // std::find
#include <iostream>
#include <string>
int main() {
const char c[] = {'a', 'b', 'c', 'd', 'e'}; // prints abcde
// const char c[] = { 'a','b','\0','d','\0' }; // test alternate: prints ab
// const char c[] = { 'a','b','\0','d','e' }; // test alternate: prints ab
std::string s{c, std::find(c, c + sizeof c, '\0')};
std::cout << s << '\n';
return 0;
}
')};
std::cout << s << '\n';
return 0;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论