I'm using boost::format (not std:: as I'm using c++98) to format a string that I'm passing to a system() call.
When getting the c_str() of the string created by format, it seems to terminate halfway along the string. The same sting created with the literal value does not have the same problem. What's going on here?
Using Boost 1.46.1 according to BOOST_VERSION.
#include <boost/format.hpp>
#include <iostream>
#include <string>
int main(int argc, char** argv)
{
const std::string my_str = "echo '/%1%/ some other stuff'";
boost::format fmtr(my_str);
fmtr % "sleep 3"; // should read: echo '/sleep 3/ some other stuff'
std::cout << "1: " << fmtr.str() << "\n"; // 1. echo '/sleep 3/ some other stuff' (OK)
std::cout << "2: " << fmtr.str().c_str() << "\n"; // 2. echo '/sleep 3 (BAD)
// Try the c_str of a string not created through boost::format
const std::string finished = "echo '/sleep 3/ some other stuff'";
std::cout << "3: " << finished.c_str() << "\n"; // 3. echo '/sleep 3/ some other stuff' (OK)
// Try copying the string from format to see if that makes any difference (it doesn't)
std::string copy = fmtr.str();
std::cout << "4: " << copy.c_str() << "\n"; // 4. echo '/sleep 3 (BAD)
return 0;
}
Passing the c_str() to my system() call is resulting in the error:
sh -c: line 0: unexpected EOF while looking for matching `''
Presumably because it is finishing halfway along the string as well.
With proper includes your program works fine: ideone
#include <boost/format.hpp>
#include <iostream>
#include <string>
int main()
{
const std::string my_str = "echo '/%1%/ some other stuff'";
boost::format fmtr(my_str);
fmtr % "sleep 3"; // should read: echo '/sleep 3/ some other stuff'
std::cout << "1: " << fmtr.str() << "\n"; // 1. echo '/sleep 3/ some other stuff' (OK)
std::cout << "2: " << fmtr.str().c_str() << "\n"; // 2. echo '/sleep 3 (BAD)
// Try the c_str of a string not created through boost::format
const std::string finished = "echo '/sleep 3/ some other stuff'";
std::cout << "3: " << finished.c_str() << "\n"; // 3. echo '/sleep 3/ some other stuff' (OK)
// Try copying the string from format to see if that makes any difference (it doesn't)
std::string copy = fmtr.str();
std::cout << "4: " << copy.c_str() << "\n"; // 4. echo '/sleep 3 (BAD)
}
You should fix includes and return type of main and try again. If wrong behavior persist most probably you have broken version of c++ and/or boost library.
Related
Okay so i get this JSON object from my client:
{"command":"BrugerIndtastTF","brugerT":"\"10\"","brugerF":"\"20\""}
Then i need to use the int value from "brugerT", but as you can see it has "\"10\"" around it. When i code this in javascript i dont get this problem. Is there a way to only use the part of "brugerT" that says 10?
the code where *temp only should print the int value 10:
socket_->hub_.onMessage([this](
uWS::WebSocket<uWS::SERVER> *ws,
char* message,
size_t length,
uWS::OpCode opCode
)
{
std::string data = std::string(message,length);
std::cout << "web::Server:\t Data received: " << data << std::endl;
// handle manual settings
std::cout << "Web::Server:\t Received request: manual. Redirecting message." << std::endl;
json test1 = json::parse(data);
auto test2 = test1.json::find("command");
std::cout << "Web::Server:\t Test 1" << test1 << std::endl;
std::cout << "Web::Server:\t Test 2" << *test2 << std::endl;
if (*test2 =="BrugerIndtastTF")
{
std::cout<<"Web::Server:\t BrugerIndtastTF modtaget" << std::endl;
auto temp= test1.json::find("brugerT");
auto humi= test1.json::find("brugerF");
std::cout << "Web::Server:\t temp: " << *temp << "humi: " << *humi << std::endl;
}
});
EDIT:
Here you can see the terminal
it should just say: temp: 10 humi: 20
You can try to get the string value of brugerT and strip the \" out of the string and then convert the resulting string into a int with stoi. You could even use a regular expression to find the integer inside the string and let that library figure out what is the best matching method. A regular expression for that would be something like: ([0-9]+)
ps string literal type 6 might be of some use when manually filtering out \"
#include <iostream>
#include <regex>
#include <string>
using namespace std;
int main() {
string inputStr(R"("\"10\"")");
regex matchStr(R"(([0-9]+))");
auto matchesBegin = sregex_iterator(inputStr.begin(), inputStr.end(), matchStr);
auto matchesEnd = sregex_iterator();
for (sregex_iterator i = matchesBegin; i != matchesEnd; ++i) {
cout << i->str() << endl;
}
return 0;
}
I want to read a chunk of data from file into stringstream, which later will be used to parse the data (using getline, >>, etc). After reading the bytes, I set the buffer of the stringstream, but I cant make it to set the p pointer.
I tested the code on some online services, such as onlinegdb.com and cppreference.com and it works. However, on microsoft, I get an error - the pointers get out of order.
Here's the code, I replaced the file-read with a char array.
#include <sstream>
#include <iostream>
int main()
{
char* a = new char [30];
for (int i=0;i<30;i++)
a[i]='-';
std::stringstream os;
std::cout << "g " << os.tellg() << " p " << os.tellp() << std::endl;
os.rdbuf()->pubsetbuf(a,30);
os.seekp(7);
std::cout << "g " << os.tellg() << " p " << os.tellp() << std::endl;
}
the output I get when it works
g 0 p 0
g 0 p 7
the output I get on visual studio 2015
g 0 p 0
g -1 p -1
any ides?
thanks
std::sstream::setbuf may do nothing:
If s is a null pointer and n is zero, this function has no effect.
Otherwise, the effect is implementation-defined: some implementations do nothing, while some implementations clear the std::string member currently used as the buffer and begin using the user-supplied character array of size n, whose first element is pointed to by s, as the buffer and the input/output character sequence.
You are better off using the std::stringstream constructor to set the data or call str():
#include <sstream>
#include <iostream>
int main()
{
std::string str( 30, '-' );
std::stringstream os;
std::cout << "g " << os.tellg() << " p " << os.tellp() << std::endl;
os.str( str );
os.seekp(7);
std::cout << "g " << os.tellg() << " p " << os.tellp() << std::endl;
}
Consider:
std::string s_a, s_b;
std::stringstream ss_1, ss_2;
// at this stage:
// ss_1 and ss_2 have been used and are now in some strange state
// s_a and s_b contain non-white space words
ss_1.str( std::string() );
ss_1.clear();
ss_1 << s_a;
ss_1 << s_b;
// ss_1.str().c_str() is now the concatenation of s_a and s_b,
// <strike>with</strike> without space between them
ss_2.str( s_a );
ss_2.clear();
// ss_2.str().c_str() is now s_a
ss_2 << s_b; // line ***
// ss_2.str().c_str() the value of s_a is over-written by s_b
//
// Replacing line *** above with "ss_2 << ss_2.str() << " " << s_b;"
// results in ss_2 having the same content as ss_1.
Questions:
What is the difference between stringstream.str( a_value ); and
stringstream << a_value; and, specifically, why does the first not
allow concatenation via << but the second does?
Why did ss_1 automatically get white-space between s_a and s_b, but
do we need to explicitly add white space in the line that could
replace line ***: ss_2 << ss_2.str() << " " << s_b;?
The problem you're experiencing is because std::stringstream is constructed by default with ios_base::openmode mode = ios_base::in|ios_base::out which is a non-appending mode.
You're interested in the output mode here (ie: ios_base::openmode mode = ios_base::out)
std::basic_stringbuf::str(const std::basic_string<CharT, Traits, Allocator>& s) operates in two different ways, depending on the openmode:
mode & ios_base::ate == false: (ie: non-appending output streams):
str will set pptr() == pbase(), so that subsequent output will overwrite the characters copied from s
mode & ios_base::ate == true: (ie: appending output streams):
str will set pptr() == pbase() + s.size(), so that subsequent output will be appended to the last character copied from s
(Note that this appending mode is new since c++11)
More details can be found here.
If you want the appending behaviour, create your stringstream with ios_base::ate:
std::stringstream ss(std::ios_base::out | std::ios_base::ate)
Simple example app here:
#include <iostream>
#include <sstream>
void non_appending()
{
std::stringstream ss;
std::string s = "hello world";
ss.str(s);
std::cout << ss.str() << std::endl;
ss << "how are you?";
std::cout << ss.str() << std::endl;
}
void appending()
{
std::stringstream ss(std::ios_base::out | std::ios_base::ate);
std::string s = "hello world";
ss.str(s);
std::cout << ss.str() << std::endl;
ss << "how are you?";
std::cout << ss.str() << std::endl;
}
int main()
{
non_appending();
appending();
exit(0);
}
This will output in the 2 different ways as explained above:
hello world
how are you?
hello world
hello worldhow are you?
Suggest you read stringstream reference: http://en.cppreference.com/w/cpp/io/basic_stringstream
std::stringstream::str() Replaces the contents of the underlying string
operator<< Inserts data into the stream.
I have the following cout statement. I use char arrays because I have to pass to vsnprintf to convert variable argument list and store in Msg.
Is there any way we can get cout output to C++ std::string?
char Msg[100];
char appname1[100];
char appname2[100];
char appname3[100];
// I have some logic in function which some string is assigned to Msg.
std::cout << Msg << " "<< appname1 <<":"<< appname2 << ":" << appname3 << " " << "!" << getpid() <<" " << "~" << pthread_self() << endl;
You can replace cout by a stringstream.
std::stringstream buffer;
buffer << "Text" << std::endl;
You can access the string using buffer.str().
To use stringstream you need to use the following libraries:
#include <string>
#include <iostream>
#include <sstream>
You can use std::stringstream
http://www.cplusplus.com/reference/iostream/stringstream/
If you can change the code then use ostringstream (or stringstream) instead of cout.
If you cannot change the code and want to "capture" what is being output you can redirect your output or pipe it.
It may then be possible for your process to read the file or get the piped information through shared memory.
#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
// This way we won't have to say std::ostringstream or std::cout or std::string...
using namespace std;
/** Simulates system specific method getpid()... */
int faux_getpid(){
return 1234;
}
/** Simulates system specific method pthread_self()... */
int faux_pthread_self(){
return 1111;
}
int main(int argc, char** argv){
// Create a char[] array of 100 characters...
// this is the old-fashioned "C" way of storing a "string"
// of characters..
char Msg[100];
// Try using C++-style std::string rather than char[],
// which can be overrun, leading to
// a segmentation fault.
string s_appname1;
// Create old-fashioned char[] array of 100 characters...
char appname2[100];
// Create old-fashioned char[] array of 100 characters...
char appname3[100];
// Old-fashioned "C" way of copying "Hello" into Msg[] char buffer...
strcpy(Msg, "Hello");
// C++ way of setting std::string s_appname equal to "Moe"...
s_appname1 = "Moe";
// Old-fashioned "C" way of copying "Larry" into appname2[] char buffer...
strcpy(appname2, "Larry");
// Old-fashioned "C" way of copying "Shemp" into appname3[] char buffer...
strcpy(appname3, "Shemp");
// Declare le_msg to be a std::ostringstream...
// this allows you to use the C++ "put-to" operator <<
// but it will "put-to" the string-stream rather than
// to the terminal or to a file...
ostringstream le_msg;
// Use put-to operator << to "write" Msg, s_appname1, s_appname2, etc...
// to the ostringstream...not to the terminal...
le_msg << Msg << " "<< s_appname1 <<":"<< appname2 << ":" << appname3 << " " << "!" << faux_getpid() <<" " << "~" << faux_pthread_self();
// Print the contents of le_msg to the terminal -- std::cout --
// using the put-to operator << and using le_msg.str(),
// which returns a std::string.
cout << "ONE: le_msg = \"" << le_msg.str() << "\"..." << endl;
// Change contents of appname3 char[] buffer to "Curly"...
strcpy(appname3, "Curly");
// Clear the contents of std::ostringstream le_msg
// -- by setting it equal to "" -- so you can re-use it.
le_msg.str("");
// Use put-to operator << to "write" Msg, s_appname1, s_appname2, etc...
// to the newly cleared ostringstream...not to the terminal...
// but this time appname3 has been set equal to "Curly"...
le_msg << Msg << " "<< s_appname1 <<":"<< appname2 << ":" << appname3 << " " << "!" << faux_getpid() <<" " << "~" << faux_pthread_self();
// Print the new contents of le_msg to the terminal using the
// put-to operator << and using le_msg.str(),
// which returns a std::string.
cout << "TWO: le_msg = \"" << le_msg.str() << "\"..." << endl;
// This time, rather than using put-to operator << to "write"
// to std::ostringstream le_msg, we'll explicitly set it equal
// to "That's all Folks!"
le_msg.str("That's all Folks!");
// Print the new contents of le_msg "That's all Folks!" to
// the terminal via le_msg.str()
cout << "THREE: le_msg = \"" << le_msg.str() << "\"..." << endl;
// Exit main() with system exit value of zero (0), indicating
// success...
return 0;
}/* main() */
OUTPUT:
ONE: le_msg = "Hello Moe:Larry:Shemp !1234 ~1111"...
TWO: le_msg = "Hello Moe:Larry:Curly !1234 ~1111"...
THREE: le_msg = "That's all, folks!"...
Hi below is my function:
string Employee::get_print(void) {
string out_string;
stringstream ss;
ss << e_id << " " << type << endl;
out_string = ss.str();
return out_string;
}
e_id and type are int and they contain values from the class Employee. But when I pass them into the stringstream they just clear the string when I try to out put it. But if I don't have a int in the ss << "Some text" << endl; this output fine. What am I doing wrong =S
//Edit
Ok;
This is the calling code:
tmp = cur->get_print();
Where tmp is a string and cur is an Employee Object.
This code...
stringstream out;
out << "Test " << e_id << " " << e_type;
return out.str();
Retruns "Test " and nothing else. If I take out "Test " << my returned string is ""
I'm using GCC 4.2 on Mac OS/X 10.6.2 if that makes any difference.
I too am unable to reproduce this error. As has been mentioned, don't include the endl, as this actually appends a \n and is supposed to flush the write buffer. For this use, it is completely unnecessary and may actually lead to undesirable results...However, the code in your edit/update works just fine for me.
int main(int argc, char* argv[])
{
int e_id = 5;
int e_type = 123456;
stringstream out;
out << "Test " << e_id << " " << e_type;
cout << out.str();
return 0;
}
Produces:
Test 5 123456
My suggestions would be to double check that e_id and e_type are really just native int.
For further testing, you may want to force a cast on the values to see if it helps as such:
out << "Test " << (int)e_id << " " << (int)e_type;
Since I'm unable to reproduce this error, I'm afraid I'm unable to help any further. But best of luck to you!
Ok I have no idea what is going on with stringstream I've tried using it in other parts of my code and it doesn't work with integers. Therefore, I have reverted to using the sprintf C function:
string Employee::get_print(void) {
char out[50];
sprintf(out, "%d %d", e_id, e_type);
string output = out;
return output;
}
This returns the string which is needed.
I have moved into Netbeans and I don't have this problem. So it is an issue with Xcode.
I think the endl is not needed. You only need to write endl if you want to write a newline on a file on on std::cout.
Since you write endl, your stringstream will contain a string with 2 lines of which the second is empty. This probably confuses you. Remove the endl to get only one line.
I've got exactly the same problem - GCC and stringstream returning nothing.
As I found out, the trick is that you have to put some text data before anything else into the stringstream.
This code...
stringstream ss(stringstream::out);
ss << 3.14159;
cout << "'" << ss.str() << "'" << endl;
gets you this result:
''
But if we put a single "" inside the stringstream first...
stringstream ss(stringstream::out);
ss << "" << 3.14159;
cout << "'" << ss.str() << "'" << endl;
the result is as expected:
'3.14159'