What should I use instead of std::ostrstream? - c++

I like to use std::ostrstream to format text but not print it to stdout but instead write it into an std::string (by accessing the std::ostrstream::str() member). Apparently this is deprecated now. So, how am I supposed to write formatted objects to a string, with the same convenience as when writing to a stream?

You could use std::ostringstream. Similarly, instead of std::istrstream you should use std::istringstream. You need to include the <sstream> header for these classes.
You could also see this question which explains why strstream was deprecated.

As others have already said, std::ostringstream is the replacement.
It's more convenient (and safer) than std::ostrstream because it manages all memory automatically so you don't need to call freeze(false) to ensure the memory gets freed when you're finished with it.

You should use std::stringstream. Also, see boost::lexical_cast.
std::stringstream supports both << and >>. std::ostringstream only supports <<, and std::istringstream only supports >>. Often I find it convenient to be able to use both operators.

You can also use boost::format. Then you can do things like:
int a = 1;
std::string b("foo");
std::string s = boost::str(
boost::format("some text, some vars=%1%, %2%, %1%") % a % b % a);
Then s would contain "some text, some vars=1, foo, 1".
This is, in my opinion, more convenient in some cases than using operator <<.
As a reference, I also include the format specification.

Related

What I can use instead of strstream::freeze?

I am working on some old c++ codes and it has strstream class which is deprecated. I need to replace them with working ones.
In my header file I got this:
ostrstream tokenBuff;
and .c file that uses header:
tokenBuff.freeze(0);
tokenBuff.seekp(0);
I replaced ostrstream with ostringstream. ostringstream has seekp() but not freeze(). How can I deal with this problem. Thanks.
You don't need freeze() in case of std::ostringstream - the necessity of calling this function was actually one of the reasons why strstream got deprecated in the first place. Because of its design (returning char* from str()) it wasn't clear who should clean the buffer that strstream holds and freeze() had to be used to signal that you want strstream itself to do it after every call to str() - in case of std::ostringstream you don't need to worry about this as str() returns a copy of the std::string.
There is no replacement for freeze in ostringsteam since it is no longer needed. In ostrstream freeze() is used to work around the deficiency that str() returns a c-style (char *) string.

Are the methods in the <cstring> applicable for string class too?

I've tried out using memcpy() method to strings but was getting a "no matching function call" although it works perfectly when I use an array of char[].
Can someone explain why?
www.cplusplus.com/reference/cstring/memcpy/
std::string is an object, not a contiguous array of bytes (which is what memcpy expects). std::string is not char*; std::string contains char* (somewhere really deep).
Although you can pull out the std::string inner byte array by using &str[0] (see note), I strongly encourage you not to. Almost anything you need to do already is implemented as a std::string method. Including appending, subtracting, transforming and anything that makes sense with a text object.
So yes, you can do something as stupid as:
std::string str (100,0);
memcpy(&str[0],"hello world", 11);
but you shouldn't.
Even if you do need memcpy behaviuor, try to use std::copy instead.
Note: this is often done with C functions that expects some buffer, while the developer wants to maintain a RAII style in his code. So he or she produces std::string object but passes it as C string. But if you do clean C++ code you don't need to.
Because there's no matching function call. You're trying to use C library functions with C++ types.

Is it OK to use iostreams with int as character-type?

When trying to come up with an answer to this question, I wrote this little test-program:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
void writeFile() {
int data[] = {0,1,2,3,4,5,6,7,8,9,1000};
std::basic_ofstream<int> file("test.data", std::ios::binary);
std::copy(data, data+11, std::ostreambuf_iterator<int>(file));
}
void readFile() {
std::basic_ifstream<int> file("test.data", std::ios::binary);
std::vector<int> data(std::istreambuf_iterator<int>(file),
(std::istreambuf_iterator<int>()));
std::copy(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
int main()
{
writeFile();
readFile();
return 0;
}
It works as expected, writing the data to the file, and after reading the file, it correctly prints:
0 1 2 3 4 5 6 7 8 9 1000
However, I am not sure if there are any pitfalls (endianess issues aside, you always have these when dealing with binary data)? Is this allowed?
It works as expected.
I'm not sure what you are expecting...
Is this allowed?
That's probably not portable. Streams relies on char_traits and on facets which are defined in the standard only for char and wchar_t. An implementation can provides more, but my bet would be that you are relying on a minimal default implementation of those templates and not on a conscious implementation for int. I'd not be surprised that a more in depth use would leads to problems.
Instantiating any of the iostream classes, or basic_string, on anything
but char or wchar_t, without providing a specific custom traits class,
is undefined behavior; most of the libraries I've seen do define it to
do something, but that definition often isn't specified, and is
different between VC++ and g++ (the two cases I've looked at). If you
define and use your own traits class, some of the functionality should
work.
For just about all of the formatted inserters and extractors (the << and
>> operators), istream and ostream delegate to various facets in
the locale; if any of these are used, you'll have to take steps to
ensure that these work as well. (This usually means providing a new
numpunct facet.)
Even if you only use the streambuf (as in your example), filebuf
uses the codecvt facet. And an implementation isn't required to provide
a codecvt, and if it does, can do pretty much whatever it wants in
it. And since filebuf always writes and reads char to and from the
file, this translation must do something. I'm actually rather
surprised that your code worked, because of this. But you still don't
know what was actually on the disk, which means you can't document it,
which means that you won't be able to read it sometime in the future.
If your goal is to write binary data, your first step should be to
define the binary format, then write read and write functions which
implement it. Possibly using the iostream << and >> syntax, and
probably using a basic_streambuf<char> for the actual input and
output; a basic_streambuf<char> that you've carefully imbued with the
"C" locale. Or rather than define your own binary format, just use an
existing one, like XDR. (All of this paragraph supposes that you want
to keep the data, and read it later. If these are just temporary files,
for spilling temporary internal data to disk during a single run, and
will be deleted at the end of the program execution, simpler solutions
are valid.)

Convert from C++ style printing to my_printf()

C++ purists may want to look away now. You will hate this.
I have been given an open source windows console app that I am merging with a pre-existing, very old, very large windows app of my own. My old program started life as pure C though recently has been tweaked so that it can compile as C++. My program makes extensive use of a my_printf() function which prints text to a window.
The old console app does its printing C++ style via streams (I have never used this type of printing mechanism before).
When converting the console app to work under my system I could manually edit all the lines that do printing so that they use my_printf() instead. But before I embarked on that I thought I'd just check with StackOverflow to see if I was missing a trick. For example I could imagine somehow letting the C++ prints be done via the stream and then somehow scooping the final text somewhere and then calling my_printf() with the result. Might that be possible?
EDIT: please note my knowledge of C++ is extremely limited and I may need to look some things up in order to understand your answers so please use language that facilitates this.
There's indeed a trivial trick. But C++ impurists will hate the fact that C++ has a pure solution ;)
std::ostream is responsible for formatting, but not printing itself. That's handled by std::streambuf. std::cout combines a std::ostream formatter with a std::streambuf-derived object that writes to stdout.
However, you can change the streambuf backing an ostream with ostream::rdbuf(newbuf). As std::cout is just another ostream, you can replace its streambuf too. In this case, you only need to come up with a streambuf-derived class that writes already-formatted output to my_printf(). That should be quite trivial.
You might find string streams useful. For example:
std::ostringstream os;
os << "Print " << whatever << data;
my_printf( "%s", os.str().c_str() );
In case you were feeling adventurous, you could write your own streambuf instead that used my_printf underneath, and inject it into the stream object that is currently used in output statements (e.g. std::cout). Be warned that this latter approach might not be trivial, however it would result in almost no changes to existing codebase.
Subclass std::ostream and make operator << call my_print_f(). You can use internal stringstream in your stream to retrieve string representation of operator << arguments.
Then you'd just have to do find&replace, replacing cout (or whatever stream you directed your output to in the console app) with an instance of your stream class.
Something along these lines might be helpful:
http://www.codeproject.com/KB/debug/debugout.aspx
Should be obvious where the meat of it is, so you can make it print via your own systems, or what have you. In theory, you'd need only search for references to std::cout and replace them with references to your own object.
Overloading the global operator<< is probably what will solve your problem:
#include <iostream>
#include <cstdio>
static int
my_printf (const char* s)
{
printf ("my_printf: %s\n", s);
}
namespace std {
std::ostream& operator<< (std::ostream& out, const char* s)
{
my_printf (s);
return out;
}
}
int
main ()
{
std::cout << "hello, world"; // => my_printf: hello, world
return 0;
}

Opening a file with std::string

This should be a fairly trivial problem. I'm trying to open an ofstream using a std::string (or std::wstring) and having problems getting this to work without a messy conversion.
std::string path = ".../file.txt";
ofstream output;
output.open(path);
Ideally I don't want to have to convert this by hand or involve c-style char pointers if there's a nicer way of doing this?
In the path string, use two dots instead of three.
Also you may use 'c_str()' method on string to get the underlying C string.
output.open(path.c_str());
this should work:
output.open(path.c_str())
I'm afraid it's simply not possible. You have to use c_str, and yes, it sucks.
Incidentally, using char* also means fstream has no support for Unicode file names... a shame.