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

时间:2016-07-06 14:08:54

标签: c++ string stringstream

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::getstd::basic_string::push_back一起阅读所需的字符数
    • 循环似乎有点笨拙,但确实避免了数组。

1 个答案:

答案 0 :(得分:2)

只需将其直接读入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::stringfrom cppreference)的内存布局。

  

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