2016-07-06 76 views
3

什么是从std::basic_istream中提取特定数量字符并将其存储在std::string中的好方法?从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()}
    • 这似乎是浪费,因为它无线ld制作整个流的副本。
  • 写模板函数接受char[]
    • 这仍然使用中间POD阵列。
  • 使用std::basic_istream::get在循环中读取所需的字符数与std::basic_string::push_back
    • 循环似乎有点笨拙起来,但它避免了阵列。
+0

可能的重复:[如何从字符串流中取出字符而不进行复制?](http://stackoverflow.com/questions/28663075/how-to-get-characters-out -of-stringstream-without-copy) – NathanOliver

+0

你保证文件名是50个字符或更少? –

+0

@QPaysTaxes文件格式具有分配给文件名的前50个字符。所以只要文件格式保持不变,就可以保证。风险在于文件格式发生变化,然后代码必须更改。 – wally

回答

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开始)

+2

@jaggedSpire这就是说,如果你在'size'函数返回的值相等时访问'pos'。在这个例子中,'0'用于'pos',而'50'由'size'返回,并且没有未定义的行为。 –

+0

这正是我正在寻找的答案。现在看起来如此明显...... :) – wally

+0

@JamesAdkison是的,在我发布之后发现。抱歉。 – jaggedSpire

相关问题