Delete NULLs from std::string - c++

I'm using a third party code which has its own implementation for std::ostream operator<<, to handle the third party's type.
I'm using stringstream for this output - like:
string ToString(const thrdPartyType& structure)
{
stringstream outputStream;
outputStream<<structure;
return outputStream.str();
}
...
string str = ToString(structure);
...
This structure contains pointer members, which are set to NULL. When using the operator<< and the assignment of str() into a string, I see (via gdb - print str) that there are many leading '\000' characters, then the string data I need.
How can I trim those NULLs in order to get only the real, not empty data?
P.S. The exact code works fine in Windows VC++...
Thank you.

Are you looking for a workoround like this?
string ToString(const thrdPartyType& structure)
{
stringstream outputStream;
outputStream << structure;
stringstream workaround;
while(! outputStream.eof ) {
char t;
outputStream >> t;
if(t != '\0')
workaround << t;
}
return workaround .str();
}

If you have boost available, something like the following will replace all instances of null in a string with another value.
boost::replace_all(str,boost::as_array(""),"NULL");
For example
char buf[10] = "hello";
string str(buf,buf+10);
boost::replace_all(str,boost::as_array(""),"NULL");
cout << str << endl;
Produces the following output
helloNULLNULLNULLNULLNULL

Related

C++ reading char from stack to string results in "Unrecognized enum"

I am new to C++ and there must be something that I am missing. My code is this:
std::stack<char> operators;
std::stringstream stream;
stream.str("5.2 + 3");
while(stream.peek() != -1){
char token = static_cast<char>(stream.get());
//some code checking if the token is valid
operators.push(token);
auto tmp = operators.top(); //there I can still see the char (for example '+')
std::string tmpStr = "" + tmp; //But when put into string, there is "Unrecognized enum"
}
The variable tmpStr is filled with "Unrecognized enum" instead of the contents of tmp.
I couldn't find any solution but I believe it must be something very simple.
Thanks for any help.
Edit:
So if I use tmpStr.push_back(tmp) it works. But then I use it like this:
std::queue<std::string> outQueue;
outQueue.push(" " + operators.top());
//some code
std::string result = "";
while(!outQueue.empty()){
result.append(outQueue.front() + " ");
outQueue.pop();
}
//result then has for example something like "5.2 own enum 3 own enum"
There on the positions that are appended from the operators stack, there is "own enum" and not what was actually saved there.
Stop doing "" + something!
This is C++ and it will not magically make a string object out of a string literal.
If the above code actually compiles, it means that somethign is of some integral type and you are taking a stack pointer (const char*) of the location that "" points to and adding a pointer offset onto that. You are not reading some random data until the next NULL.
If you want to convert something to a string you need to convert it. The standard way to this is though a output stream operator.
enum OP
{
OP_ADD,
OP_SUB,
OP_DIV,
OP_MUL
};
std::ostream& operator << (std::ostream& os, OP op)
{
switch (op)
{
case OP_ADD:
os << "ADD";
break;
case OP_SUB:
os << "SUB";
break;
case OP_DIV:
os << "DIV";
break;
case OP_MUL:
os << "MUL";
break;
default:
throw std::logic_error("Invalid OP");
}
}
This can then be used like so:
OP op = OP_ADD;
std::stringstream buff;
buff << op;
std::string sop = buff.str();
But since the above code it quite stupid, I have a shorthand for the object to string conversion:
template <typename T>
std::string to_string(T value)
{
std::stringstream buff;
buff << value;
return buff.str();
}
This can then be used like so:
OP op = OP_ADD;
std::string sop = to_string(op);

How do I concatenate "constant strings" and chars?

What is the "proper way" to do the following? (Note, I don't want to output the message to the screen (yet), the data needs to be stored in a variable.)
std::cout << "Enter a letter: ";
char input;
std::cin >> input;
std::string message = "Today's program was brought to you by the letter '" + input + "'.";
The code gives me the error message invalid operands of types const char* and const char [3] to binary operator+.
I understand why this message is occurring. When Googling for a solution, the results that come up recommend casting each item into a string in turn. However, this becomes impractical if you have to concatenate a dozen items:
std::string("x:") + x + std::string(", y:") + y + std::string(", width:") + width + std::string(", height:") + height + ...;
What is the "proper way" in c++ to concatenate strings, chars, char arrays, and any other data that is convertible, into a single string? Is there anything like Python's beautiful string formatting features in c++?
What you are trying to do won't work because C++ views your concatenation as an attempt to add several char pointers. If you explicitly cast the first element in the series to an std::string it should work.
Change your original code
string message = "Today's program was brought to you by the letter '" + input + "'.";
to this:
string message = std::string("Today's program was brought to you by the letter '")
+ input + "'.";
q.v. this SO post which discusses this problem in greater detail (though I don't know why it got closed as not being a real question).
There's several ways to do this, but one way that's a good balance between simplicity of implementation and convenience is to use a "formatter" class which wraps std::stringstream like so:
string message = formatter() << "Today's program was brought to you by the letter '" << input << "'.";
Where formatter can be defined very simply in a header file as follows:
#include <sstream>
class formatter {
public:
template <typename T>
formatter & operator<<(const T & o) {
stream_ << o;
return *this;
}
const std::string str() const { return stream_.str(); }
operator std::string() {
return stream_.str();
}
private:
std::ostringstream stream_;
};
What's going on there: If you try to use a temporary std::stringstream() instead of formatter() above, it doesn't work because
std::stringstream is not implicitly convertible to std::string
You can't even do it like this
std::string message = (std::stringstream() << "foo" << input << "bar").str(); because, std::stringstream returns std::ostream & from its stream operations (rather than std::stringstream &), and you cannot convert an ostream to a string in general.
The formatter class just lets you construct and use a stringstream all in one line with a minimum of boiler plate.

Different values on the function implementation

I'm kind of new with programming and I have wired problem.
I tried to search and read about it, but without success.
I have main file and one class (on windows)
main:
main()
{
LogOut x();
x.WriteToDelayFile(1.2, 3);
}
LogOut class:
void LogOut::WriteToDelayFile(double simTime, int nodeNum)
{
string fileName = "Delay" + nodeNum;
FILE* pFile = OpenFile(fileName);
fputs ("something\n",pFile);
}
I can't figure it out but when I call to WriteToDelayFile(2, 3) with values, I get garbage values edit: (for example, on debug- nodeNum=321546 instead of nodeNum=3) on the LogOut::WriteToDelayFile(double simTime, int nodeNum) implementation
Why does it happen?
Thanks.
As user657267 pointed out in his comment, you may not concatenate a string literal and an int string fileName = "Delay" + nodeNum;. Here you are getting a pointer into the literal, that may even be out of range:
string s = "hello"+1; // leads to "ello" in s
The probably intended concatenation can be done using a stringstream:
#include <sstream>
#include <assert>
void concat_check()
{
std::stringstream ss;
ss << "hello" << 1;
assert(ss.str() == "hello1");
}
Wolf you are a little bit wrong
string s = "hello"+3;
gives "lo" in s data
and
string si = string("hello")+3;
is incorrect you need to use stringstream instead
std::stringstream ss;
ss << "hello" << 3;
std::string s = ss.str();
Dudi Reuveni how can you tell that nodeNum has wrong data?

What exactly does stringstream do?

I am trying to learn C++ since yesterday and I am using this document: http://www.cplusplus.com/files/tutorial.pdf (page 32). I found a code in the document and I ran it. I tried inputting Rs 5.5 for price and an integer for quantity and the output was 0.
I tried inputting 5.5 and 6 and the output was correct.
// stringstreams
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main ()
{
string mystr;
float price = 0;
int quantity = 0;
cout << "Enter price: ";
getline (cin,mystr);
stringstream(mystr) >> price;
cout << "Enter quantity: ";
getline (cin,mystr);
stringstream(mystr) >> quantity;
cout << "Total price: " << price*quantity << endl;
return 0;
}
What exactly does the mystring command do? Quoting from the document:
"In this example, we acquire numeric values from the standard input
indirectly. Instead of extracting numeric values directly from the
standard input, we get lines from the standard input (cin) into a
string object (mystr), and then we extract the integer values from
this string into a variable of type int (quantity)."
My impression was that the function will take an integral part of a string and use that as input.
Sometimes it is very convenient to use stringstream to convert between strings and other numerical types. The usage of stringstream is similar to the usage of iostream, so it is not a burden to learn.
Stringstreams can be used to both read strings and write data into strings. It mainly functions with a string buffer, but without a real I/O channel.
The basic member functions of stringstream class are
str(), which returns the contents of its buffer in string type.
str(string), which set the contents of the buffer to the string argument.
Here is an example of how to use string streams.
ostringstream os;
os << "dec: " << 15 << " hex: " << std::hex << 15 << endl;
cout << os.str() << endl;
The result is dec: 15 hex: f.
istringstream is of more or less the same usage.
To summarize, stringstream is a convenient way to manipulate strings like an independent I/O device.
FYI, the inheritance relationships between the classes are:
From C++ Primer:
The istringstream type reads a string, ostringstream writes a string, and stringstream reads and writes the string.
I come across some cases where it is both convenient and concise to use stringstream.
case 1
It is from one of the solutions for this leetcode problem. It demonstrates a very suitable case where the use of stringstream is efficient and concise.
Suppose a and b are complex numbers expressed in string format, we want to get the result of multiplication of a and b also in string format. The code is as follows:
string a = "1+2i", b = "1+3i";
istringstream sa(a), sb(b);
ostringstream out;
int ra, ia, rb, ib;
char buff;
// only read integer values to get the real and imaginary part of
// of the original complex number
sa >> ra >> buff >> ia >> buff;
sb >> rb >> buff >> ib >> buff;
out << ra*rb-ia*ib << '+' << ra*ib+ia*rb << 'i';
// final result in string format
string result = out.str()
case 2
It is also from a leetcode problem that requires you to simplify the given path string, one of the solutions using stringstream is the most elegant that I have seen:
string simplifyPath(string path) {
string res, tmp;
vector<string> stk;
stringstream ss(path);
while(getline(ss,tmp,'/')) {
if (tmp == "" or tmp == ".") continue;
if (tmp == ".." and !stk.empty()) stk.pop_back();
else if (tmp != "..") stk.push_back(tmp);
}
for(auto str : stk) res += "/"+str;
return res.empty() ? "/" : res;
}
Without the use of stringstream, it would be difficult to write such concise code.
To answer the question. stringstream basically allows you to treat a string object like a stream, and use all stream functions and operators on it.
I saw it used mainly for the formatted output/input goodness.
One good example would be c++ implementation of converting number to stream object.
Possible example:
template <class T>
string num2str(const T& num, unsigned int prec = 12) {
string ret;
stringstream ss;
ios_base::fmtflags ff = ss.flags();
ff |= ios_base::floatfield;
ff |= ios_base::fixed;
ss.flags(ff);
ss.precision(prec);
ss << num;
ret = ss.str();
return ret;
};
Maybe it's a bit complicated but it is quite complex. You create stringstream object ss, modify its flags, put a number into it with operator<<, and extract it via str(). I guess that operator>> could be used.
Also in this example the string buffer is hidden and not used explicitly. But it would be too long of a post to write about every possible aspect and use-case.
Note: I probably stole it from someone on SO and refined, but I don't have original author noted.
You entered an alphanumeric and int, blank delimited in mystr.
You then tried to convert the first token (blank delimited) into an int.
The first token was RS which failed to convert to int, leaving a zero for myprice, and we all know what zero times anything yields.
When you only entered int values the second time, everything worked as you expected.
It was the spurious RS that caused your code to fail.

String concatenation in C++ problem

everybody I have problem with string concatenation in C++, here is my code
map<double, string> fracs;
for(int d=1; d<=N; d++)
for(int n=0; n<=d; n++)
if(gcd(n, d)==1){
string s = n+"/"+d;// this does not work in C++ but works in Java
fracs.insert(make_pair((double)(n/d), s));
}
How can I fix my code?
Try like this.
stringstream os;
os << n << "/" << d;
string s =os.str();
In C++ you have to convert an int to a string before you can concatenate it with another string using the + operator.
See Easiest way to convert int to string in C++.
Use streams, in your case, a stringstream:
#include <sstream>
...
std::stringstream ss;
ss << n << '/' << d;
Later, when done with your work, you can store it as an ordinary string:
const std::string s = ss.str();
Important (side-) note: Never do
const char *s = ss.str().c_str();
stringstream::str() produces a temporary std::string, and according to the standard, temporaries live until the end of the expression. Then, std::string::c_str() gives you a pointer to a null-terminated string, but according to The Holy Law, that C-style-string becomes invalid once the std::string (from which you receved it) changes.
It might work this time, and next time, and even on QA, but explodes right in the face of your most valuable customer.
The std::string must survive until the battle is over:
const std::string s = ss.str(); // must exist as long as sz is being used
const char *sz = s.c_str();
n and d are integers. Here is how you can convert integer to string:
std::string s;
std::stringstream out;
out << n << "/" << d;
s = out.str();
You could use a stringstream.
stringstream s;
s << n << "/" << d;
fracs.insert(make_pair((double)n/d, s.str()));
No one has suggested it yet but you can also take a look at boost::lexical_cast<>.
While this method is sometimes criticized because of performance issues, it might be ok in your situation, and it surely makes the code more readable.
Unlike in Java, in C++ there is no operator+ that explicitly converts a number to a string. What is usually done in C++ in cases like this is...
#include <sstream>
stringstream ss;
ss << n << '/' << d; // Just like you'd do with cout
string s = ss.str(); // Convert the stringstream to a string
I think sprintf(), which is a function used to send formatted data to strings, would be a much clearer way to do it. Just the way you would use printf, but with the c-style string type char* as a first(additional) argument:
char* temp;
sprint(temp, "%d/%d", n, d);
std::string g(temp);
You could check it out at http://www.cplusplus.com/reference/cstdio/sprintf/