Insert values into a string without using sprintf or to_string - c++

Currently I only know of two methods to insert values into a C++ string or C string.
The first method I know of is to use std::sprintf() and a C-string buffer (char array).
The second method is to use something like "value of i: " + to_string(value) + "\n".
However, the first one needs the creation of a buffer, which leads to more code if you just want to pass a string to a function. The second one produces long lines of code, where a string gets interrupted every time a value is inserted, which makes the code harder to read.
From Python I know the format() function, which is used like this:
"Value of i: {}\n".format(i)
The braces are replaced by the value in format, and further .format()'s can be appended.
I really like Python's approach on this, because the string stays readable, and no extra buffer needs to be created. Is there any similar way of doing this in C++?

Idiomatic way of formatting data in C++ is with output streams (std::ostream reference). If you want the formatted output to end up in a std::string, use an output string stream:
ostringstream res;
res << "Value of i: " << i << "\n";
Use str() member function to harvest the resultant string:
std::string s = res.str();
This matches the approach of formatting data for output:
cout << "Value of i: " << i << "\n";

Related

How to get length of shellcode string containing NULL characters

I have string of shellcode with NULL characters in between them and i am unable to detect its length, i tried std::string.length() method but it only counts till NULL character after that it doesn't count.
Here is sample code .
std::string shell_str = "\x55\x48\x89\x00\x00\x00\x00\xC3\x90";
std::cout << "shell : " << shell_str << std::endl;
std::cout << "shell length : " << shell_str.length() << std::endl;
Output :
shell : UH�
shell length : 3
But length of string is 9 and i tried to copy it to vector also but still doesn't get the desired output .
Full code snippet is posted here
The problem isn't with the calculation of the length of shell_str, the problem is with the literal string you use to initialize shell_str. The constructor of std::string will stop at the "terminator".
You need to use another std::string constructor, to explicitly tell it the actual length of the string:
std::string shell_str("\x55\x48\x89\x00\x00\x00\x00\xC3\x90", 9);
Also, since the "string" contains arbitrary data, you can't print it as a string either.
And if you want a "string" of arbitrary bytes I suggest you use std::vector<uint8_t> instead.

String stream output compare

I want to compare output of stringstream with some string.
Problem is when I use fill and width on stringstream I cant compare resulting string with preloaded string.
std::stringstream sstr;
sstr.fill(' ');
sstr.width(4);
sstr << 4 << std::endl;
if(" 4" == sstr.str()){
std::cout << "Equal" << std::endl;
}
It's not equal. My educated guess would be that width somehow use some kind of flag or other kind of indicator to replace bunch of spaces in string. But I am not sure and didn't find anything useful on google. Does anyone know why I cannot compare that (sstream.str() and targeted string)?
Goal is to test what will stringstream (which is heart of my component) print on console.
You also inserted a std::endl into the string. That's going to add a newline character to the string.
Remove the std::endl from your output.

C++ File Input/Output Outputting Numbers Instead of Chars

I have created a program that randomly assigns roles(jobs) to members of a certain house using file input / output.. It builds successfully, but when using cout and I actually see the results, I can see why the program is not working.
Here is the snippet of code I believe something is wrong with :
std::string foo = std::string("Preferences/") + std::to_string(members[random]) + "-Preferences";
cout << foo << endl;
And here is the members[random] array, it is randomly selecting members from this array and reviewing their available times and assigning them jobs based on their Preference input file.
unsigned const char members[22] =
{ 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v' };
I have created a random number picker that goes through 0-21 and assigns the value it creates to variable random. So, in essence, it is members[random] and completely random.
Here is the output I get in my terminal.
Preferences/116-Preferences
But I set the output to do Preferences/ member[random] -Preferences.
It is accessing a number and not my array chars.
I created a cout << members[random]; right below it, and every time I run the program, I get
Preferences/107-Preferences <---- A random number every time
k <---- random letter every time.
So I know it must be accessing my random functions, but assigned it to numbers! How do I fix this so my proper output can be :
Preferences/t-Preferences
Please help me, and thanks!
"The more you overthink the plumbing, the easier it is to stop up
the drain" - Scotty, Star Trek III
Declaring members to be unsigned chars does not accomplish anything useful. A simple char will suffice. std::string already implements an overloaded + operator that takes a char parameter, so it's much easier than you thought it would be:
const char members[22] = {
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v' };
// ...
std::string foo = std::string("Preferences/") + members[random]
+ "-Preferences";
There is no ::std::to_string(char), only (among less close) ::std::to_string(int). So your character is actually converted to its numerical representation and you get your unwanted result.
Try instead
std::string foo("Preferences/");
foo = foo.append(1, members[random]).append("-Preferences");
Variant using string streams:
ostringstream oss;
oss << "Preferences/" << members[random] << "-Preferences";
// get your string via:
oss.str();

Same string to multiple streams [duplicate]

This question already has answers here:
How can I compose output streams, so output goes multiple places at once?
(3 answers)
Closed 4 months ago.
I have to send the same string (e.g. a log message) to multiple streams.
Which of the following solutions is the most efficient?
Rebuild the same string for each stream and send it to the stream itself.
outstr1 << "abc" << 123 << 1.23 << "def" << endl;
outstr2 << "abc" << 123 << 1.23 << "def" << endl;
outstr3 << "abc" << 123 << 1.23 << "def" << endl;
Build the string once with string's operators, and send it to all the streams.
std::string str = "abc" + std::to_string(123) + std::to_string(1.23) + "def";
outstr1 << str;
outstr2 << str;
outstr3 << str;
Build the string once with a stream, and send it to all the streams:
std::stringstream sstm;
sstm << "abc" << 123 << 1.23 << "def" << endl;
std::string str = sstm.str();
outstr1 << str;
outstr2 << str;
outstr3 << str;
Some or all of these output streams could be on a RAM disk.
Any other ways to do the same thing?
I would use a tee output stream. Do something like (pseudocode):
allstreams = tee(outstr1, outstr2, outstr3);
allstreams << "abc" << 123 << 1.23 << "def" << endl;
There doesn't seem to be anything in the standard c++ library to do this, but Boost has one.
See also the answers to How can I compose output streams, so output goes multiple places at once?
Although it is unlikely that you would see much difference either way1, option #3 sounds the most plausible: unlike the first option, it does not convert ints to strings multiple times; unlike the second option, it does not allocate and delete multiple string objects for its intermediate results2. It also looks cleanest from the readability point of view: no code is duplicated, and output looks like an output, not like a concatenation.
1 Insert a mandatory disclaimer about optimization before profiling being evil here.
2 Small String Optimization may help on systems where it is supported (thanks, Prætorian), but the constructor and destructor calls for the intermediate objects are not going away.
The "proper" way to do something like this is to have a stream buffer writing to multiple destinations and use this stream buffer via a std::ostream. This way the code looks as if it writing just once but the characters are sent multiple times. Searching for "teebuf Dietmar" will find a few variations on the same theme.
To also comment on your question: Which one of the three alternatives is the fastest depends on the exact expressions you have:
needs to evaluate the involved expressions and perform the conversions three times. Depending on what you actually do this may still be fairly fast.
actually creates and destroys multiple streams and does multiple allocations for std::string. I'd expect this to be slowest.
still creates a stream (which should actually be a std::ostringstream) and allocates some memory. Out of your options I'd expect it to be fastest.
Using a teebuf is probably fastest, at least, when it does some buffering but uses only fixed suze arrays, both for the buffer and the array of stream buffer pointers. Note, that you'll need to override sync() to deal with the buffer in a timely manner, though.
To determine the actual performance you'll need to measure!

What's the difference between putting std::string and std::string::c_str() into a stringstream?

We're seeing a strange scenario that basically boils down to the following:
std::string something = "someval";
std::stringstream s;
s << something;
std::cout << s.str();
is not equal to:
std::string something = "someval";
std::stringstream s;
s << something.c_str();
std::cout << s.str();
Taking that a step farther - the output is not gibberish in either case. What is happening is the output from case 1 appears to be mapped to another (valid) string in the system whereas the output from case 2 is what is expected.
We see this behavior by simply changing:
s << something;
To:
s << something.c_str();
I know this sounds crazy (or it does to me), and I haven't been able to replicate it out of the larger system - so sorry for no "working" example. But does anyone know how this kind of thing can happen? Can we be stepping on memory somewhere or doing something to a stringtable in some location or anything else like that?
It is different if the string contains nul characters, '\0'.
The .c_str() version will compute the length up to the nul, while the std::string output will know its length and output all its characters.