将特定数量的字符从 std::basic_istream 复制到 std::string

Copy specific number of characters from std::basic_istream to std::string

本文关键字:std basic 复制 string istream 字符      更新时间:2023-10-16

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, '');
    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的内存布局(来自 cpp首选项)。

basic_string的元素是连续存储的,也就是说,对于basic_string s&*(s.begin() + n) == &*s.begin() + n [0, s.size())中的任何n,或者,等价地,指向s[0]的指针可以传递给期望指向CharT[]数组的第一个元素的指针的函数。 (自C++11起)