Reputation: 26150
I have some C++ code which needs to generate an error message when parsing a certain file header fails. In this case, I need to ensure that a certain 4 byte field in the header is "OggS", and if it is not, return an error message like "invalid capture_pattern: 'FooB'; expecting 'OggS'". My code looks something like this:
const string OggPage::parseHeader(void) {
read(fd, capture_pattern, sizeof(capture_pattern)); // error handling omitted
if (strncmp(capture_pattern, CAPTURE_PATTERN, sizeof(capture_pattern)) != 0) {
char err[256];
snprintf(err, sizeof(err), "Failed to read %d bytes from file descriptor %d: %s\n", sizeof(capture_pattern), fd, err);
return err;
}
return "Everything was A-OK!";
}
What is the standard C++ idiom for building a string from other datatypes? I'm not wedded to the printf(3)
-style format here, so feel free to suggest anything that works.
Upvotes: 4
Views: 7405
Reputation: 8253
You can use stringstream
or ostringstream
from C++ Standard library. If further stream will not be used to read values from it (e.g. it's istream
part won't be used) ostringstream
is more suitable.
#include <sstream>
#include <string>
#include <iostream>
int main() {
std::stringstream str_stream;
int number = 5;
str_stream << " String with number " << number << std::endl;;
std::string str = str_stream.str();
std::cout << str;
}
Upvotes: 5
Reputation: 15570
C++ way of doing this is std::stringstream
.
std::stringstream err;
err << "Failed to read " << sizeof(capture_pattern)
<< " bytes from fd " << fd << std::endl;
return err.str();
Upvotes: 1
Reputation: 56976
Using string functions from cstring
is definitely fine for reading. They're fast, convenient and not verbose.
For building your error messages, you can use stringstream
, operators related to the string
class, boost::format
or, as you put it, snprintf
.
You have also boost::lexical_cast
for simple things:
string message = "Failed to read " + lexical_cast<string>(n) +
" bytes from the descriptor " + lexical_cast<string>(fd) + ".";
I recommend having a look at this Gotw for a sane point of view.
I'd recommend boost::format
if you have a lot of formatting to do. Use lexical_cast
for simple isolated things, and use stringstream
if you have requirements which makes you need them (eg. custom operator<<
, cannot use boost
, etc).
To be honest, snprintf
is really fine.
Upvotes: 1
Reputation: 30449
You create a stringstream, write what you want using the '<<' operator and then get the string out of stream with the member function .str().
#include <sstream>
#include <string>
using namespace std;
stringstream err;
err << "Failed to read " << sizeof(capture_pattern) << " bytes from file descriptor: " << fd << endl;
string outstr = err.str();
Upvotes: 0
Reputation: 248129
Just as a note, please don't suggest replacements for the actual reading--there is a reason that I want to use the C standard library for I/O here. :)
You can't really ask for "idiomatic" ways to do something in C++, and then say "but I want to stick to the C standard library...
Anyway, you have three options. I don't believe any of them is idiomatic (because that would imply some kind of consensus about this being the best way):
std::stringstream
, which is part the iostreams section of the standard libraryThe latter has the downside that it relies on a third-party library, but the advantage that it gives you printf
-like syntax, in a typesafe and extensible manner, which interoperates cleanly with C++ streams.
Upvotes: 1