How to move std::ostringstream's underlying string object? - c++

#include <sstream>
#include <string>
using namespace std;
template<typename T>
string ToString(const T& obj)
{
ostringstream oss;
oss << obj;
//
// oss will never be used again, so I should
// MOVE its underlying string.
//
// However, below will COPY, rather than MOVE,
// oss' underlying string object!
//
return oss.str();
}
How to move std::ostringstream's underlying string object?

The standard says that std::ostringstream::str() returns a copy.
One way to avoid this copy is to implement another std::streambuf derived-class that exposes the string buffer directly. Boost.IOStreams makes this pretty trivial:
#include <boost/iostreams/stream_buffer.hpp>
#include <iostream>
#include <string>
namespace io = boost::iostreams;
struct StringSink
{
std::string string;
using char_type = char;
using category = io::sink_tag;
std::streamsize write(char const* s, std::streamsize n) {
string.append(s, n);
return n;
}
};
template<typename T>
std::string ToString(T const& obj) {
io::stream_buffer<StringSink> buffer{{}};
std::ostream stream(&buffer);
stream << obj;
stream.flush();
return std::move(buffer->string); // <--- Access the string buffer directly here and move it.
}
int main() {
std::cout << ToString(3.14) << '\n';
}

Since C++20 you can.
std::move(oss).str()

Related

Swapping a stringstream for cout

With glibc's stdio, I can swap a memstream for stdout, thereby capturing the output of a piece of code compiled to output to stdout:
#include <stdio.h>
void swapfiles(FILE* f0, FILE* f1){ FILE tmp; tmp = *f0; *f0 = *f1; *f1 = tmp; }
void hw_c(){ puts("hello c world"); }
int c_capt(){
FILE* my_memstream;
char* buf = NULL;
size_t bufsiz = 0;
if( (my_memstream = open_memstream(&buf, &bufsiz)) == NULL) return 1;
FILE * oldstdout = stdout;
swapfiles(stdout, my_memstream);
hw_c();
swapfiles(stdout, my_memstream);
fclose(my_memstream);
printf("Captured: %s\n", buf);
}
I'm curious if the same is possible for iostreams.
My naive attempt won't compile:
#include <iostream>
#include <string>
#include <sstream>
void hw_cc(){ std::cout<<"hello c++ world\n"; }
int cc_capt(){
using namespace std;
stringstream ss;
string capt;
//std::swap(ss,cout); //<- the compiler doesn't like this
hw_cc();
//std::swap(ss,cout);
cout<<"Captured: "<<capt<<'\n';
}
int main(int argc, char** argv){
c_capt();
puts("---------------------------------");
cc_capt();
return 0;
}
You can, but you don't swap the whole stream--just the stream buffer.
void cc_capt() {
using namespace std;
stringstream ss;
auto orig = std::cout.rdbuf(ss.rdbuf());
hw_cc();
std::cout.rdbuf(orig);
std::cout << "captured: " << ss.str() << "\n";
}
Note that in this case, we're not really using the stringstream itself at all, just the stringbuf it contains. If we wanted, we could just define a basic_stringbuf<char> and use that directly instead of defining a stringstream and then only use the stringbuf it contains.
Based on Jerry's samples, I wrote a template which has one great advantage, it's safe (i.e. if an exception occurs, your buffer gets restored automatically.)
Use this way:
{
ostream_to_buf<char> buf(std::cout);
... run code which `std::cout << "data"` ...
std::string const output(buf.str());
... do something with `output` ...
} // <-- here the buffer is restored
Here is the functional template which I think follows the STL pretty closely. The template is itself an std::stringbuf which inserts itself in the constructor. The destructor restores the original buffer so it is exception safe.
template<
class CharT
, class Traits = std::char_traits<CharT>
, class Allocator = std::allocator<CharT>
>
class ostream_to_buf
: public std::basic_stringbuf<CharT, Traits, Allocator>
{
public:
typedef CharT char_type;
typedef Traits traits_type;
typedef typename Traits::int_type int_type;
typedef typename Traits::pos_type pos_type;
typedef typename Traits::off_type off_type;
typedef Allocator allocator_type;
typedef std::basic_stringbuf<char_type, traits_type, allocator_type> stringbuf_type;
typedef std::basic_ostream<char_type, traits_type> stream_type;
typedef std::basic_streambuf<char_type, traits_type> streambuf_type;
typedef std::basic_string<char_type, traits_type, allocator_type> string_type;
ostream_to_buf<char_type, traits_type, allocator_type>(stream_type & out)
: f_stream(out)
, f_original(f_stream.rdbuf(this))
{
}
ostream_to_buf<char_type, traits_type, allocator_type>(ostream_to_buf<char_type, traits_type, allocator_type> const & rhs) = delete;
ostream_to_buf<char_type, traits_type, allocator_type> & operator = (ostream_to_buf<char_type, traits_type, allocator_type> const & rhs) = delete;
~ostream_to_buf()
{
f_stream.rdbuf(f_original);
}
private:
stream_type & f_stream;
streambuf_type * f_original = nullptr;
};
The copy constructor and assignment operator are deleted because these do not work in this case.
You probably can make it work with C++11 or even C++03. I have C++14 but I don't think any of these require C++14.

C++: string operator overload

Can I overload existing function/operator in existing class?
I was trying to do:
#include <iostream>
#include <string>
using namespace std;
string& string::operator<<(const string& str) {
this->append(str);
}
But this gives me error:
test.cpp:5: error: too few template-parameter-lists
How can I do this? Or I can't?
You can't add member functions to a class unless you modify that class' definition. Use a free function instead:
string& operator<<(string & lhs, const string & rhs) {
return lhs += rhs;
}
I defer to Benjamin's answer for creating a stream-like interface on a string object. However, you could use a stringstream instead.
#include <sstream>
std::istringstream ss;
ss << anything_you_want;
std::string s = ss.str(); // get the resulting string
ss.str(std::string()); // clear the string buffer in the stringstream.
This gives you the stream-like interface you want on a string without needing to define a new function.
This technique can be used generally to extend the functionality of a string. That is, defining a wrapper class that provides the extended functionality, and the wrapper class also provides access to the underlying string.
Use
std::ostringstream
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
std::ostringstream ss;
ss << "Hello" << " " << "world";
std::string s = ss.str();
ss.str(std::string());
cout << s << endl;
return 0;
}
https://onlinegdb.com/rkanzeniI

C++: Wrapping vector<char> with istream

I want to wrap a vector<char> with std::istream (so reading the vector would be done through the istream interface)
What's the way to do it?
You'd define a streambuf subclass wrapping the vector, and pass an instance of that to the istream constructor.
If the data does not change after construction, it is sufficient to set up the data pointers using streambuf::setg(); the default implementation for the other members does the right thing:
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
vectorwrapbuf(std::vector<CharT> &vec) {
setg(vec.data(), vec.data(), vec.data() + vec.size());
}
};
std::vector<char> data;
// ...
vectorwrapbuf<char> databuf(data)
std::istream is(&databuf);
If you need anything more advanced than that, override the streambuf::underflow method.
using Boost:
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/array.hpp>
using namespace boost::iostreams;
basic_array_source<char> input_source(&my_vector[0], my_vector.size());
stream<basic_array_source<char> > input_stream(input_source);
or even simpler:
#include <boost/interprocess/streams/bufferstream.hpp>
using namespace boost::interprocess;
bufferstream input_stream(&my_vector[0], my_vector.size());
Adapting the answer from Get an istream from a char* and assuming this is what you're trying to do:
// Forward declarations
std::vector<char> my_create_buffer();
void my_consume_buffer( std::istream & is );
// What you want to be able to write
std::vector<char> buffer = my_create_buffer();
my_consume_buffer( wrap_vector_as_istream(buffer) );
You can then create the wrap_vector_as_istream like this (untested though) :
#include <iostream>
#include <istream>
#include <streambuf>
#include <string>
struct wrap_vector_as_istream : std::streambuf
{
wrap_vector_as_istream(std::vector<char> & vec ) {
this->setg(&vec[0], &vec[0], &vec[0]+vec.size() );
}
};
One thing to be aware of though. The object you've created contains pointers into the vectors memory. So if you add or remove values to the vector while having this wrapper floating around, then you're heading for a crash.
(Oh and if you up vote me, please up vote the post I've adapted this from.)
You'd could get away with simply building a class that implements the >> operator like a stream, something like this:
template<class _ITy>
class RangeStreamLite
{
private:
_ITy Begin;
_ITy End;
_ITy Next;
public:
RangeStreamLite(_ITy begin, _ITy end) :
Begin(begin),
End(end),
Next(begin)
{
// Do nothing.
}
template<class _OTy>
RangeStreamLite& operator>>(_OTy& out)
{
out = *Next;
++Next;
return *this;
}
void reset()
{
Next = Begin;
}
};
This is a 'quick and dirty' solution, a 'stream lite', it isn't really a stream in the proper sense but it works when all you require is a superficial stream-like device. To properly create a custom stream is a little more complicated, and would require you to inherit from std::streambuf and implement the necessary features. Here are a few links worth a look:
Inheriting std::istream or equivalent
Deriving the C++ Stream Buffer
If you are fine with swapping your vector<char> you can use Boost Interprocess' vectorstream. Example:
#include <boost/interprocess/streams/vectorstream.hpp>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
static const char inp[] = "123 45 666";
vector<char> v(inp, inp + sizeof inp - 1);
using ivectorstream =
boost::interprocess::basic_ivectorstream<std::vector<char>>;
ivectorstream is;
is.swap_vector(v);
while (!is.eof()) {
int i = 0;
is >> i;
cout << i << '\n';
}
is.swap_vector(v);
cout << string(v.begin(), v.end()) << '\n';
return 0;
}
Alternatively, if you can't or don't want to mutate your vector<char>, you can use Boost Interprocess' bufferstream. With bufferstream, you don't have to swap your vector into it. Example:
#include <boost/interprocess/streams/bufferstream.hpp>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
static const char inp[] = "123 45 666";
vector<char> v(inp, inp + sizeof inp - 1);
boost::interprocess::ibufferstream is(v.data(), v.size());
while (!is.eof()) {
int i = 0;
is >> i;
cout << i << '\n';
}
return 0;
}
You will have to write a custom stream-implementation that inherits from istream. This can easily be done using Boost.Iostreams - all you'd have to do is implement a simple Source.

Data Type Convert

Is there any function in C++ which converts all data types (double, int, short, etc) to string?
Usually you'll use the << operator, in conjunction with (for example) a std::stringstream.
http://www.boost.org/doc/libs/1_43_0/libs/conversion/lexical_cast.htm
If boost is not an option (it should always be, but just in case):
#include <sstream>
#include <string>
template<class T1, class T2>
T1 lexical_cast(const T2& value)
{
std::stringstream stream;
T1 retval;
stream << value;
stream >> retval;
return retval;
}
template<class T>
std::string to_str(const T& value)
{
return lexical_cast<std::string>(value);
}
Boost has a similar idea, but the implementation is much more efficient.
There is no built-in universal function, but boost::lexical_cast<> will do this.
Why do you need this conversion? A lot of languages have variant types which auto-convert, and this can lead to wanting that behavior in C++ even though there may be a more canonical way of implementing it.
For example if you're trying to do output, using a (string)stream of some sort is probably the way to go. If you really need to generate and manipulate a string, you can use boost::lexical_cast http://www.boost.org/doc/libs/1_43_0/libs/conversion/lexical_cast.htm.
Here is the one I use from my utility library. This was condensed from other posts here on stackoverflow, I am not claiming this as my own original code.
#include <string>
#include <sstream>
using namespace std;
template <class T>
string ToString(const T& Value) {
stringstream ss;
ss << Value;
string s = ss.str();
return s;
}
also, another handy string formatting utility I use:
#include <string>
#include <stdarg.h> /* we need va_list */
// Usage: string myString = FormatString("%s %d", "My Number =", num);
string FormatString(const char *fmt, ...) {
string retStr;
if (NULL != fmt) {
va_list marker = NULL;
va_start(marker, fmt);
size_t len = 256 + 1; // hard size set to 256
vector <char> buffer(len, '\0');
if (vsnprintf(&buffer[0], buffer.size(), fmt, marker) > 0) {
retStr = &buffer[0]; // Copy vector contents to the string
}
va_end(marker);
}
return retStr;
}
For this use stringstream.
First include the header file as #include .
Then create an object of stringstream and using stream insertion operator (<<) pass the contents you want to convert as string.
Ex:
#include <iostream>
#include <sstream>
int main(){
std::string name = "Ram";
float salary = 400.56;
std::stringstream obj;
obj << name << " salary: " << salary;
std::string s = obj.str();
std::cout << s;
}

Is there a C++ iterator that can iterate over a file line by line?

I would like to get an istream_iterator-style iterator that returns each line of the file as a string rather than each word. Is this possible?
EDIT: This same trick was already posted by someone else in a previous thread.
It is easy to have std::istream_iterator do what you want:
namespace detail
{
class Line : std::string
{
friend std::istream & operator>>(std::istream & is, Line & line)
{
return std::getline(is, line);
}
};
}
template<class OutIt>
void read_lines(std::istream& is, OutIt dest)
{
typedef std::istream_iterator<detail::Line> InIt;
std::copy(InIt(is), InIt(), dest);
}
int main()
{
std::vector<std::string> v;
read_lines(std::cin, std::back_inserter(v));
return 0;
}
The standard library does not provide iterators to do this (although you can implement something like that on your own), but you can simply use the getline function (not the istream method) to read a whole line from an input stream to a C++ string.
Example:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
ifstream is("test.txt");
string str;
while(getline(is, str))
{
cout<<str<<endl;
}
return 0;
}
Here is a solution. The exemple print the input file with ## at the end of each line.
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
using namespace std;
class line : public string {};
std::istream &operator>>(std::istream &is, line &l)
{
std::getline(is, l);
return is;
}
int main()
{
std::ifstream inputFile("input.txt");
istream_iterator<line> begin(inputFile);
istream_iterator<line> end;
for(istream_iterator<line> it = begin; it != end; ++it)
{
cout << *it << "##\n";
}
getchar();
}
Edit : Manuel has been faster.
You could write your own iterator. It's not that hard.
An iterator is just a class on which (simply speaking) the increment and * operators are defined.
Look at http://www.drdobbs.com/cpp/184401417 to get started writing your own iterators.
It is also possible to use range-based for loop:
// Read from file.
std::ifstream f("test.txt");
for (auto& line : lines(f))
std::cout << "=> " << line << std::endl;
// Read from string.
std::stringstream s("line1\nline2\nline3\n\n\nline4\n\n\n");
for (auto& line : lines(s))
std::cout << "=> " << line << std::endl;
where lines is defined in the following way:
#include <string>
#include <iterator>
#include <istream>
struct line_iterator {
using iterator_category = std::input_iterator_tag;
using value_type = std::string;
using difference_type = std::ptrdiff_t;
using reference = const value_type&;
using pointer = const value_type*;
line_iterator(): input_(nullptr) {}
line_iterator(std::istream& input): input_(&input) { ++*this; }
reference operator*() const { return s_; }
pointer operator->() const { return &**this; }
line_iterator& operator++() {
if (!std::getline(*input_, s_)) input_ = nullptr;
return *this;
}
line_iterator operator++(int) {
auto copy(*this);
++*this;
return copy;
}
friend bool operator==(const line_iterator& x, const line_iterator& y) {
return x.input_ == y.input_;
}
friend bool operator!=(const line_iterator& x, const line_iterator& y) {
return !(x == y);
}
private:
std::istream* input_;
std::string s_;
};
struct lines {
lines(std::istream& input): input_(input) {}
line_iterator begin() const { return line_iterator(input_); }
line_iterator end() const { return line_iterator(); }
private:
std::istream& input_;
};
You can use istreambuf_iterator instead of istream_iterator. It doesn't ignore control characters like istream_iterator.
code.cpp:
#include <iterator>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream file("input.txt");
istreambuf_iterator<char> i_file(file);
istreambuf_iterator<char> eof;
std::string buffer;
while(i_file != eof)
{
buffer += *i_file;
if(*i_file == '\n')
{
std::cout << buffer;
buffer.clear();
}
++i_file;
}
return 0;
}
input.txt:
ahhhh test *<-- There is a line feed here*
bhhhh second test *<-- There is a line feed here*
output:
ahhhh test
bhhhh second test
In a related thread iterate-over-cin-line-by-line quoted above, Jerry Coffin described "another possibility (which) uses a part of the standard library most people barely even know exists." The following applies that method (which was what I was looking for) to solve the iterate-over-file-line-by-line problem as requested in the current thread.
First a snippet copied directly from Jerry's answer in the related thread:
struct line_reader: std::ctype<char> {
line_reader(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
rc['\n'] = std::ctype_base::space;
return &rc[0];
}};
And now, imbue the ifstream with the custom locale as described by Jerry, and copy from infstream to ofstream.
ifstream is {"fox.txt"};
is.imbue(locale(locale(), new line_reader()));
istream_iterator<string> ii {is};
istream_iterator<string> eos {};
ofstream os {"out.txt"};
ostream_iterator<string> oi {os,"\n"};
vector<string> lines {ii,eos};
copy(lines.begin(), lines.end(), oi);
The output file ("out.txt") will be exactly the same as the input file ("fox.txt").
Here is a pretty clean approach that uses boost::tokenizer. This returns an object providing begin() and end() member functions; for a complete interface, see the documentation of the tokenizer class.
#include <boost/tokenizer.hpp>
#include <iostream>
#include <iterator>
using istream_tokenizer = boost::tokenizer<boost::char_separator<char>,
std::istreambuf_iterator<char>>;
istream_tokenizer line_range(std::istream& is);
{
using separator = boost::char_separator<char>;
return istream_tokenizer{std::istreambuf_iterator<char>{is},
std::istreambuf_iterator<char>{},
separator{"\n", "", boost::keep_empty_tokens}};
}
This hardcodes char as the stream's character type, but this could be templatized.
The function can be used as follows:
#include <sstream>
std::istringstream is{"A\nBB\n\nCCC"};
auto lines = line_range(is);
std::vector<std::string> line_vec{lines.begin(), lines.end()};
assert(line_vec == (std::vector<std::string>{{"A", "BB", "", "CCC"}}));
Naturally, it can also be used with an std::ifstream created by opening a file:
std::ifstream ifs{"filename.txt"};
auto lines = line_range(ifs);