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.
You can use stringstream or ostringstreamfrom 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;
}
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):
stick with the C APIs you're already using
Use the the C++ std::stringstream, which is part the iostreams section of the standard library
use Boost.Format
The 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.
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.
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();
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();
Related
I've been using std::ofstream for writing purposes quite a bit. I open the file, do some operations based on certain conditions and close it.
Let's say that later I want to check if anything is really written into the file or not. There is not is_emtpy() kind of simple check available with std::ofstream.
One way I thought is of using the stat way which is independent of std::ofstream.
Wonder how do everyone else do it?
Standard output streams provide a tellp() method which can be used to determine the current write position. The type and meaning of the return value is implementation-defined, but for it to be useful, it must return distinct values.
#include <iostream>
#include <fstream>
int main()
{
std::ofstream out{"/tmp/test"};
auto const empty_pos = out.tellp();
std::clog.setf(std::ios_base::boolalpha);
std::clog << "At start: " << (out.tellp() != empty_pos) << '\n';
out << 'c';
std::clog << "After writing 1 char: " << (out.tellp() != empty_pos) << '\n';
}
In principle, empty_pos may be different for each stream, so a truly portable program will take that into account.
Note also that this doesn't necessarily mean that the output is visible to other programs - use std::flush if that's important.
I have the following code:
char szBuf[256] = "";
std::string szFmt = "You have recieved %s item."
string szName = "Fork";
snprintf(szBuf, sizeof(szBuf), szFmt.c_str(), szName);
I'm trying to combine szFmt with szBuf while combining szFmt with szName according to.However, when I execute this code in win10, I getting such an weird output:
You've received the LÃý item.
And when I try to execute the code in OSX El Capitan, I'm getting the following error
cannot pass object of non-trivial type 'string' throgh variadic function;
call will about at runtime
So what is the problem, and how can I solve this?
Note: I checked this question, but in the answer, they are passing directly "Fork", which also works in me; however it doesn't work when I pass it as szName.
Better solutions were mentioned in the comments (ostringstream) but for further educational value, I'll address the immediate problem here.
Varargs (the mechanism through which the printf family of functions can accept a variable number of arguments) are not as strictly type checked as the rest. In this case, snprintf is expecting a char* to the string, but you're passing szName which is a string object. So you need to call .c_str() on that as well:
snprintf(szBuf, sizeof(szBuf), szFmt.c_str(), szName.c_str());
Using std::ostringstream will simplify things, especially since it's more type-safe than the printf functions inherited from C, but also since it can handle all standard types and with proper overloading of the output operator << you can also use it very easily for custom classes.
The important thing to remember with std::ostringstream is that it is an ordinary output stream, just like std::cout, and if you can use std::cout then you can also use std::ostringstream (or any other standard output stream).
Now for how to use it:
std::ostringstream ostr; // Define the stream object
ostr << "You have recieved " << szName << " item.";
And that's about it.
To access the string you use the str function:
std::cout << "The output is " << ostr.str() << '\n';
And if you want to copy it into a char buffer for some reason:
// Use `strncpy` to not overflow the destination buffer
std::strncpy(szBuf, ostr.str().c_str(), sizeof szBuf - 1);
// Remember that `strncpy` might not terminate the destination, so do it explicitly
szBuf[sizeof szBuf - 1] = '\0';
I am relatively new to the C++ world.
I know std::cout is used for console output in C++. But consider the following code in C :
#include<stdio.h>
int main(){
double dNum=99.6678;
printf("%.02lf",dNum);
//output: 99.67
return 0;
}
How do I achieve the similar formatting of a double type value upto 2 decimal places using cout in C++ ?
I know C++ is backward compatible with C. But is there a printf() equivalent in C++ if so, then where is it defined ?
This is what you want:
std::cout << std::fixed << std::setprecision(2);
std::cout << dNum;
and don't forget to :
#include <iostream>
#include <iomanip>
There is no equivalent. It is a pain using cout for formatted output.
All suggested solutions calling setprecision and similar are awfull when using long formats.
boost::format does not support some very nice features. Incompatibilities with printf. I still use printf because it is unbeatable.
If you want to use printf like formatting you should probably use snprintf (or build an allocating variant of that on top of that). Note that sprintf requires you to be able to guarantee that the result will not overrun the buffer you have to keep defined behaviour. With snprintf on the other hand can guarantee that it will not overrun the buffer since you specifiy the maximal number of characters that will be written to the string (it will instead truncate the output).
You could even build something that can directly be fed to an ostream on top of snprintf by automatically allocate the buffer and place in an object that on destruction free that memory. This in addition with a method to feed the object to an ostream would finish it off. Something like (with room for improvements):
struct Format {
char buf[999];
Format(fmt, ...) {
va_list ap;
va_start(fmt, ap);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
}
}
ostream& operator<< (ostream& os, Format const& str);
then you use this as:
cout << Format("The answer is %d", 42) << endl;
If you're using the GNU libraries you could of course use printf directly since cout and stdout are the same object then. Otherwise you should probably avoid mixing stdio and iostreams as there is no guarantee that these are synchronized with each other.
If you really want to reuse the same formatting techniques as in C, you may use Boost::format, which does exactly that:
cout << boost::format("%.02lf") % dNum;
But is there a printf() equivalent in C++ if so, then where is it defined?
There is a standards proposal P0645 to add a similar formatting facility to C++. In the meantime you can use the {fmt} library that implements this proposal and more:
#include <fmt/core.h>
int main()
fmt::print("{:.02f}", 99.6678);
}
P0645 and {fmt} use Python-like format string syntax which is similar to printf's but uses {} as delimiters instead of %.
Also the type information is preserved so you don't need l or other noisy specifiers.
Save your program as CPP and run it.
It runs and prints the answer.
Because C++ also has the printf() and scanf() like C.
You can also use sprintf in C++ to 'print' into a string and then cout that string. This strategy leverages your experience with printf-style formatting.
To output a value to the console using C++, you need the global ostream object cout and the << operator. endl is another global ostream object used as line break.
All are defined in the <iostream> header file. You can also use various formatting flags to control the presentation of the output...
#include<iostream>
using namespace std;
int main() {
double dNum = 99.6678;
cout << dNum;
cout.setf(ios::scientific, ios::floatfield); // format into scientific notation
cout << dNum;
cout.precision(8); // change precision
cout << dNum;
system("pause");
return 0;
}
The functional equivalent of your printf() call, using std::cout, is
std::cout << fixed << setprecision(2) << dNum;
It is necessary to #include <iomanip> and <iostream>.
The printf() equivalent in C++ is std::printf(), declared in <cstdio>.
Also, thanks to backward compatibility to C - specifically C++98 was required to maximise backward compatiblility to C89 - C's printf() declared in <stdio.h> is also available in C++. Note, however, that <stdio.h> is deprecated (tagged for removal from a future version of the C++ standard). Also, not all features of printf() introduced in C99 (the 1999 C standard) or later are necessarily supported in C++.
I have been working in Java since I started programming and decided to learn c++.
What I wrote in Java looked like this:
showMessage("Hello world" + randomNumber);
And it showed text + integer or float or whatever. But it wont work in c++.
Error message by xCode: Invalid operands to binary expression ('const char *' and 'float')
Cheers!
You can do a sprintf according to Anton, or to be more c++:
std::stringstream ss;
ss << "Hello, world " << randomNumber;
showmessage(ss.str());
(there's nothing wrong with sprintf, especially if you use snprintf instead).
ostringstream os;
os<<"HelloWorld"<<randomnumber;
string s;
s = os.str();
string s now contains the string you want as a string object.
Also you can use boost::lexical_cast to cast numbers into strings which is fastest method in most cases:
showMessage("Hello world" + boost::lexical_cast<std::string>(randomNumber));
showMessage declaration is
void showMessage(cosnt std::string& message)
Consider adding a new function that is able to convert several types to std::string:
template<typename ty>
string to_str(ty t)
{
stringstream ss; ss << t;
return ss.str();
}
Usage:
"Hello World " + to_str(123)
Define a class S. Then write
showMessage( S() << "Hello world" << randomNumber );
I've coded up the S class too many times for SO, and it's a good exercise to create it, hence, not providing the source code.
Note that you can reasonably call it StringWriter or something like that, and then just use a typedef for more concise code in function calls.
I am not sure if c-style answer is fine, but I have already answer it here in a cocos2d-x question.
Trying to set up a CCLabelTTF with an integer as part of it's string in Cocos2d-X C++
With C++11:
showMessage("Hello world" + std::to_string(randomNumber));
you should print into the char* instead.
You could do something like
char* tempBuffer = new char[256];
sprintf_s(tempBuffer, 256, "Hello world %d", randomNumber);
showMessage(tempBuffer);
In C++ the standard way to concatenate strings and primitives is to use stringstream. Which fulfils the same functionality (and a little bit more) as StringBuilder in Java (of course its API differs). However, if you are comfortable using cout then you should be fine.
eg.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main () {
stringstream ss;
ss << "Some string - " << 124; // build string
string str = ss.str(); // extract string
cout << str << endl;
return 0;
}
Quick reference for stringstream http://www.cplusplus.com/reference/iostream/stringstream/stringstream/
I use to write code like this:
void fun(char *buff, unsigned size)
{
std::strstream str(buff, size);
str << "hello world: " << 5;
}
so I can use stream output over an arbitrary buffer. I've found this technique both efficient (no allocations) and useful (streams!). Now that std::strstream is deprecated, how can I get the same speed+flexibility that I can get with this code?
The standard library doesn't provide that functionality. However, Boost does with its generic streams and array sources/sinks.
Boost Generic Stream
Boost Array Devices
char buff[size];
boost::stream<boost::array_sink> out(buff, size);
out << "Hello, world!";
(Code untested)
try:
#include <sstream>
std::stringstream str;
str << "hello world: " << 5;
Edit: Sorry, I think I over simplified your question. That functionality is one of the things removed when changing to sstream. Here is something similar (I think this works...):
#include <sstream>
void fun(char *buff, unsigned size)
{
std::stringstream str;
str << "hello world: " << 5;
memcpy(buff, str.str().c_str(), size);
}
Now that std::strstream is deprecated,
how can I get the same
speed+flexibility that I can get with
this code?
I think it was deprecated for a reason. I had numerous portability problems in past when dealing with case of stream reaching the end of the buffer. Lack of the unity probably triggered the deprecation in favor std::string using version.
Otherwise, it amuses me that you mention "speed" in context of iostreams and the "<<" operators. I did bunch of tests in past and iostreams simply cannot catch up with good ol' snprintf(). Making a function call for every element - the effect of "<<" operators - is taxing anyhow you look at it and would be always slower. That's the cost of strict type checks.