从 std::basic_istream
中提取特定数量的字符并将其存储在 std::string
中的安全好方法是什么?
在下面的程序中,我使用 char[]
最终获得 result
,但我想避免 POD 类型并确保更安全和更易于维护:
#include <sstream>
#include <string>
#include <iostream>
#include <exception>
int main()
{
std::stringstream inss{std::string{R"(some/path/to/a/file/is/stored/in/50/chars Other data starts here.)"}};
char arr[50]{};
if (!inss.read(arr,50))
throw std::runtime_error("Could not read enough characters.\n");
//std::string result{arr}; // Will probably copy past the end of arr
std::string result{arr,arr+50};
std::cout << "Path is: " << result << '\n';
std::cout << "stringstream still has: " << inss.str() << '\n';
return 0;
}
备选方案:
- 预先将整个流转换为字符串:
std::string{inss.c_str()}
- 这看起来很浪费,因为它会复制整个流。
- 编写一个模板函数来接受
char[]
- 这仍将使用中间 POD 阵列。
- 在循环中使用
std::basic_istream::get
与std::basic_string::push_back
一起读取所需数量的字符- 循环看起来有点笨拙,但它确实避开了数组。
最佳答案
只需将其直接读入result
字符串即可。
#include <sstream>
#include <string>
#include <iostream>
#include <exception>
int main()
{
std::stringstream inss{std::string{R"(some/path/to/a/file/is/stored/in/50/chars Other data starts here.)"}};
std::string result(50, '\0');
if (!inss.read(&result[0], result.size()))
throw std::runtime_error("Could not read enough characters.\n");
std::cout << "Path is: " << result << '\n';
std::cout << "stringstream still has: " << inss.str() << '\n';
return 0;
}
自 C++11 起,以下关于 std::string
( from cppreference ) 内存布局的保证。
The elements of a
basic_string
are stored contiguously, that is, for abasic_string s
,&*(s.begin() + n) == &*s.begin() + n
for anyn
in[0, s.size())
, or, equivalently, a pointer tos[0]
can be passed to functions that expect a pointer to the first element of aCharT[]
array. (since C++11)
关于c++ - 将特定数量的字符从 std::basic_istream 复制到 std::string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38226121/