wally
wally

Reputation: 11002

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

What is a good, safe way to extract a specific number of characters from a std::basic_istream and store it in a std::string?

In the following program I use a char[] to eventually obtain result, but I would like to avoid the POD types and ensure something safer and more maintainable:

#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;
}

Alternatives:

Upvotes: 3

Views: 2005

Answers (1)

James Adkison
James Adkison

Reputation: 9602

Just read it directly into the result string.

#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;
}

Since C++11, the following guarantee about the memory layout of the std::string (from cppreference).

The elements of a basic_string are stored contiguously, that is, for a basic_string s, &*(s.begin() + n) == &*s.begin() + n for any n in [0, s.size()), or, equivalently, a pointer to s[0] can be passed to functions that expect a pointer to the first element of a CharT[] array. (since C++11)

Upvotes: 3

Related Questions