I've been fighting this problem for a while now, and can't seem to find a simple solution that doesn't involve parsing a char * by hand. I need to split my char* variable by '\t', and I've tried the following ways:
Method 1:
char *splitentry;
std::string ss;
splitentry = strtok(read_msg_.data(), "\\t");
while(splitentry != NULL)
{
std::cout << splitentry << std::endl;
splitentry = strtok(NULL, "\\t");
}
Using the input '\tthis\tis\ta\ttest'
results in this output:
his
is
a
es
Method 2:
std::string s(read_msg_.data());
boost::algorithm::split(strs, s, boost::is_any_of("\\t");
for (int i = 0; i < strs.size(); i++)
std::cout << strs.at(i) << std::endl;
Which creates an identical output.
I've tried using boost::split_regex and used "\\t" as my regex value, but nothing gets split. Will I have to split it on my own, or am I going about this incorrectly?
I would try to make things a little simpler by sticking to std:: functions. (p.s. you never use this: std::string ss;)
Why not do something like this?
Method 1: std::istringstream
std::istringstream ss(read_msg_.data());
std::string line;
while( std::getline(ss,line,ss.widen('\t')) )
std::cout << line << std::endl;
Method 2: std::string::substr (my preferred method as it is lighter)
std::string data(read_msg_.data());
std::size_t SPLITSTART(0); // signifies the start of the cell
std::size_t SPLITEND(0); // signifies the end of the cell
while( SPLITEND != std::string::npos ) {
SPLITEND = data.find('\t',SPLITSTART);
// SPLITEND-SPLITSTART signifies the size of the string
std::cout << data.substr(SPLITSTART,SPLITEND-SPLITSTART) << std::endl;
SPLITSTART = SPLITEND+1;
}
Related
so i have a string like this:std::string MyString = "\\xce\\xc6";
where when i print it like this:std::cout << MyString.c_str()[0] << std::endl;
as output i get:\
and i want it to be like this:std::string MyDesiredString = "\xce\xc6";
so when i do:
std::cout << MyDesiredString.c_str()[0] << std::endl;
// OUTPUT: \xce (the whole byte)
so basically i want to identify the string(that represents bytes) and convert it to an array of real bytes
i came up with a function like this:
// this is a pseudo code i'm sure it has a lot of bugs and may not even work
// just for example for what i think
char str_to_bytes(const char* MyStr) { // MyStr length == 4 (\\xc6)
std::map<char*, char> MyMap = { {"\\xce", '\xce'}, {"\\xc6", 'xc6'} } // and so on
return MyMap[MyStr]
}
//if the provided char* is "\\xc6" it should return the char '\xc6'
but i believe there must be a better way to do it.
as much as i have searched i haven't found anything useful
thanks in advance
Try something like this:
std::string teststr = "\\xce\\xc6";
std::string delimiter = "\\x";
size_t pos = 0;
std::string token;
std::string res;
while ((pos = teststr.find(delimiter)) != std::string::npos) {
token = teststr.substr(pos + delimiter.length(), 2);
res.push_back((char)stol(token, nullptr, 16));
std::cout << stol(token, nullptr, 16) << std::endl;
teststr.erase(pos, pos + delimiter.length() + 2);
}
std::cout << res << std::endl;
Take your string, split it up by the literals indicating a hex. value is provided (\x) and then parse the two hex. characters with the stol function as Igor Tandetnik mentioned. You can then of course add those byte values to a string.
I'm trying to read the data of several objects from a file. The reading itself works fine, but I'm having trouble with writing the data into a std::list<MyObject*>. I tried a couple of things but it always ends with the application crashing after printing some stuff, which I think is random memory content. Below you can find the current version. I also tried Iterators but that didn't work either.
Here's what happens in the calling method:
PAProject proj2 = PAProject();
proj2.projectName = "myfirstOne";
PaFigureLoader::loadFigures(&proj2);
std::list<PAFigure*>::iterator figIterator;
for(figIterator = proj2.figures.begin();
figIterator != (proj2.figures.end());
figIterator++) {
PAFigure* fig = *figIterator;
if(fig->firstname.empty()) {
std::cout << "Nothing to see here\n";
break;
} else {
std::cout << fig->firstname << "\n";
}
}
The list is std::list<PAFigure*> figures
Method causing all the trouble:
static void loadFigures(PAProject *project)
{
//open input stream
fs::ifstream ifstream(filename);
std::string input;
ifstream >> input;
PAFigure * fig;
//keep a string for all the splitting:
std::string result;
//define regexs
std::regex reg1 ("(<firstname>)([a-zA-Z0-9]*)(</firstname>)");
std::regex reg2 ("(<lastname>)([a-zA-Z0-9]*)(</lastname>)");
//iterate through file to find all figures
while(input.compare("</allfigures>") != 0) {
//do the figure-loading stuff
if(input.compare("<figure>")==0) {
PAFigure newFigure = PAFigure();
project->figures.push_front(&newFigure);
fig = &newFigure;
}
//find contents
if(input.find("<firstname>")!= std::string::npos) {
std::regex_replace (std::back_inserter(result), input.begin(), input.end(), reg1, "$2");
fig->firstname = result;
result.erase();
std::cout << fig->firstname << " is firstname\n";
}
if(input.find("<lastname>")!= std::string::npos) {
std::regex_replace (std::back_inserter(result), input.begin(), input.end(), reg2, "$2");
fig->lastname = result;
result.erase();
}
//read next line
ifstream >> input;
}
PAFigure * figtest = project->figures.back();
std::cout << figtest->firstname << " last element\n";
figtest = project->figures.front();
std::cout << figtest->firstname << " first element\n";
}
Here's the output:
died
Anna is firstname
died
Dorian is firstname
Dorian last element
Dorian first element
Dorian died
Anna died
I added
PAFigure::~PAFigure()
{
std::cout << this->firstname << " died\n";
}
because I had that weird feeling that my elements were just gone, and apparently the PAFigure newFigure = PAFigure() does infact never get a firstname.
I admit that my coding experience in C++ and especially with pointer/references is very... basic. I have no idea how to solve this, not even talking about solving it in an elegant way.
Use pointer rather than reference.
Here is what's wrong:
PAFigure newFigure = PAFigure();
You should use a pointer to push, rather than reference.
PAFigure *newFigure = new PAFigure();
project->figures.push_front(newFigure);
// and create another object too.
PAFigure *fig = new PAFigure();
I want to truncate a string in a cout,
string word = "Very long word";
int i = 1;
cout << word << " " << i;
I want to have as an output of the string a maximum of 8 letters
so in my case, I want to have
Very lon 1
instead of :
Very long word 1
I don't want to use the wget(8) function, since it will not truncate my word to the size I want unfortunately. I also don't want the 'word' string to change its value ( I just want to show to the user a part of the word, but keep it full in my variable)
I know you already have a solution, but I thought this was worth mentioning: Yes, you can simply use string::substr, but it's a common practice to use an ellipsis to indicate that a string has been truncated.
If that's something you wanted to incorporate, you could just make a simple truncate function.
#include <iostream>
#include <string>
std::string truncate(std::string str, size_t width, bool show_ellipsis=true)
{
if (str.length() > width)
if (show_ellipsis)
return str.substr(0, width) + "...";
else
return str.substr(0, width);
return str;
}
int main()
{
std::string str = "Very long string";
int i = 1;
std::cout << truncate(str, 8) << "\t" << i << std::endl;
std::cout << truncate(str, 8, false) << "\t" << i << std::endl;
return 0;
}
The output would be:
Very lon... 1
Very lon 1
As Chris Olden mentioned above, using string::substr is a way to truncate a string. However, if you need another way to do that you could simply use string::resize and then add the ellipsis if the string has been truncated.
You may wonder what does string::resize? In fact it just resizes the used memory (not the reserved one) by your string and deletes any character beyond the new size, only keeping the first nth character of your string, with n being the new size. Moreover, if the new size is greater, it will expand the used memory of your string, but this aspect of expansion is straightforward I think.
Of course, I don't want to suggest a 'new best way' to do it, it's just another way to truncate a std::string.
If you adapt the Chris Olden truncate function, you get something like this:
#include <iostream>
#include <string>
std::string& truncate(std::string& str, size_t width, bool show_ellipsis=true) {
if (str.length() > width) {
if (show_ellipsis) {
str.resize(width);
return str.append("...");
}
else {
str.resize(width);
return str;
}
}
return str;
}
int main() {
std::string str = "Very long string";
int i = 1;
std::cout << truncate(str, 8) << "\t" << i << std::endl;
std::cout << truncate(str, 8, false) << "\t" << i << std::endl;
return 0;
}
Even though this method does basically the same, note that this method takes and returns a reference to the modified string, so be careful with it since this string could be destroyed because of an external event in your code. Thus if you don't want to take that risk, just remove the references and the function becomes:
std::string truncate(std::string str, size_t width, bool show_ellipsis=true) {
if (str.length() > width) {
if (show_ellipsis) {
str.resize(width);
return str + "...";
}
else {
str.resize(width);
return str;
}
}
return str;
}
I know it's a little bit late to post this answer. However it might come in handy for future visitors.
I have been getting a really annoying error about an std::out_of_range when calling substr. The exact error is
terminate called after throwing an
instance of 'std::out_of_range'
what(): basic_string::substr
I'm absolutely sure that tmp_request has a length greater then 1. No matter what I pass to substr—1, 2, or bodypos—it always throws that error. I'm using g++ on Unix.
Only interesting thing I can include is the string has multiple "\r\n", including one "\r\n\r\n".
In one cpp file:
std::string tmp_request, outRequest;
tmp_request = SS_Twitter->readData();
outRequest = SS_Twitter->parse(tmp_request);
In another:
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0]=='P')
{
if(request.find("register")!=std::string::npos)
{ //we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
}
else
{
std::string body = request.substr(bodypos);
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
}
}
Update:
std::string request2("P\r\nregister\r\nusername=hello\r\n\r\n");
std::string body = request2.substr(4);
That throws the same error. Now I know this is perfectly valid and correct code, but it's still throwing the error.
//removed source link
I modified your sample slightly to decrease amount of indentation used.
There are 5 "test cases" and none causes any problem. Could you please provide a sample request to reproduce the problem you're having.
EDIT: Forgot to mention: if this sample as it is (with commented-out bits) doesn't produce that error, your best bet is that you have a bug in your StringExplode function. You could post its source, to get a more helpful advice.
EDIT2:
In your StringExplode, change results[tmpKey] = tmpKey.substr(found+1); to results[tmpKey] = tmpResult[i].substr(found+1);. Change int found to size_t found, and remove all of if (found > 0), that will fix your mysterious out_of_range. You were substr-ing a wrong string. Just in case, here's the code with a fix:
void StringExplode(std::string str, std::string objseparator, std::string keyseperator,
std::map <std::string, std::string> &results)
{
size_t found;
std::vector<std::string> tmpResult;
found = str.find_first_of(objseparator);
while(found != std::string::npos)
{
tmpResult.push_back(str.substr(0,found));
str = str.substr(found+1);
found = str.find_first_of(objseparator);
}
if(str.length() > 0)
{
tmpResult.push_back(str);
}
for(size_t i = 0; i < tmpResult.size(); i++)
{
found = tmpResult[i].find_first_of(keyseperator);
while(found != std::string::npos)
{
std::string tmpKey = tmpResult[i].substr(0, found);
results[tmpKey] = tmpResult[i].substr(found+1);
found = tmpResult[i].find_first_of(keyseperator, found + results[tmpKey].size());
}
}
}
Initial test code:
#include <iostream>
#include <map>
#include <string>
std::string parse(const std::string &request)
{
std::map<std::string,std::string> keyval;
std::string outRequest;
if(request[0] != 'P')
return outRequest;
if(request.find("register") == std::string::npos)
return outRequest;
//we have a register request
size_t bodypos = request.find("username");
if(bodypos==std::string::npos)
{
// HttpError(400,"Malformed HTTP POST request. Could not find key username.",request);
// you said HttpError returns, so here's a return
return outRequest;
}
std::string body = request.substr(bodypos);
// StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
return outRequest;
}
int main()
{
std::string request("P\r\nregister\r\nusername=hello\r\n\r\n");
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello\r\n\r\n";
std::cout << "[" << parse(request) << "]\n";
request = "Pregisternusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "registernusername=hello";
std::cout << "[" << parse(request) << "]\n";
request = "";
std::cout << "[" << parse(request) << "]\n";
return 0;
}
This outputs, predictably:
[doing stuff]
[doing stuff]
[doing stuff]
[]
[]
Are you sure that it's failing on that substr and not on a substr call within the HttpError or StringExplode functions? If you haven't already, you should run this through a debugger so that you can see exactly where it's throwing the exception. Alternatively, you could add a:
std::cout << "calling substr" << std::endl;
line immediately before you call substr, and a similar line immediately afterwards, so that it would look like:
std::cout << "calling substr" << std::endl;
std::string body = request.substr(bodypos);
std::cout << "finished calling substr" << std::endl;
StringExplode(body,"&", "=",keyval);
outRequest = "doing stuff";
If that substr really is throwing the exception, then you'll know because the program will print "calling substr" without a matching "finished calling substr". If it prints the pair of debug messages, though, or none at all, then something else is throwing the exception.
One fairly obvious thing wrong with your code:
int k = read(ns, buf, sizeof(buf)-1);
buf[k] = '\0';
You are not checking that read() succeeded - it returns -1 on failure which will cause all sorts of memory corruption problems if it occurs.
Also:
char * buf2 = const_cast<char *>(reply.c_str());
write(ns,buf2,sizeof(buf2));
You are taking the size of the pointer - you want the length of the output string:
write(ns, buf2, reply.size() );
And you should once again test that write succeeded and that it wrote as many bytes as you requested, though this shouldn't directly cause the substr() error.
Looks like you need an else after
if(bodypos==std::string::npos)
{
HttpError(...);
}
otherwise you are calling substr with bodypos = npos
You might consider using the (unsigned) type std::string::size_type instead of int.
Why are you casting the result of find to an int here:
int(request.find("register"))!=std::string::npos
This question already has answers here:
How to concatenate a std::string and an int
(25 answers)
Closed 6 years ago.
int i = 4;
string text = "Player ";
cout << (text + i);
I'd like it to print Player 4.
The above is obviously wrong but it shows what I'm trying to do here. Is there an easy way to do this or do I have to start adding new includes?
With C++11, you can write:
#include <string> // to use std::string, std::to_string() and "+" operator acting on strings
int i = 4;
std::string text = "Player ";
text += std::to_string(i);
Well, if you use cout you can just write the integer directly to it, as in
std::cout << text << i;
The C++ way of converting all kinds of objects to strings is through string streams. If you don't have one handy, just create one.
#include <sstream>
std::ostringstream oss;
oss << text << i;
std::cout << oss.str();
Alternatively, you can just convert the integer and append it to the string.
oss << i;
text += oss.str();
Finally, the Boost libraries provide boost::lexical_cast, which wraps around the stringstream conversion with a syntax like the built-in type casts.
#include <boost/lexical_cast.hpp>
text += boost::lexical_cast<std::string>(i);
This also works the other way around, i.e. to parse strings.
printf("Player %d", i);
(Downvote my answer all you like; I still hate the C++ I/O operators.)
:-P
These work for general strings (in case you do not want to output to file/console, but store for later use or something).
boost.lexical_cast
MyStr += boost::lexical_cast<std::string>(MyInt);
String streams
//sstream.h
std::stringstream Stream;
Stream.str(MyStr);
Stream << MyInt;
MyStr = Stream.str();
// If you're using a stream (for example, cout), rather than std::string
someStream << MyInt;
For the record, you can also use a std::stringstream if you want to create the string before it's actually output.
cout << text << " " << i << endl;
Your example seems to indicate that you would like to display the a string followed by an integer, in which case:
string text = "Player: ";
int i = 4;
cout << text << i << endl;
would work fine.
But, if you're going to be storing the string places or passing it around, and doing this frequently, you may benefit from overloading the addition operator. I demonstrate this below:
#include <sstream>
#include <iostream>
using namespace std;
std::string operator+(std::string const &a, int b) {
std::ostringstream oss;
oss << a << b;
return oss.str();
}
int main() {
int i = 4;
string text = "Player: ";
cout << (text + i) << endl;
}
In fact, you can use templates to make this approach more powerful:
template <class T>
std::string operator+(std::string const &a, const T &b){
std::ostringstream oss;
oss << a << b;
return oss.str();
}
Now, as long as object b has a defined stream output, you can append it to your string (or, at least, a copy thereof).
Another possibility is Boost.Format:
#include <boost/format.hpp>
#include <iostream>
#include <string>
int main() {
int i = 4;
std::string text = "Player";
std::cout << boost::format("%1% %2%\n") % text % i;
}
Here a small working conversion/appending example, with some code I needed before.
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main(){
string str;
int i = 321;
std::stringstream ss;
ss << 123;
str = "/dev/video";
cout << str << endl;
cout << str << 456 << endl;
cout << str << i << endl;
str += ss.str();
cout << str << endl;
}
the output will be:
/dev/video
/dev/video456
/dev/video321
/dev/video123
Note that in the last two lines you save the modified string before it's actually printed out, and you could use it later if needed.
For the record, you could also use Qt's QString class:
#include <QtCore/QString>
int i = 4;
QString qs = QString("Player %1").arg(i);
std::cout << qs.toLocal8bit().constData(); // prints "Player 4"
cout << text << i;
One method here is directly printing the output if its required in your problem.
cout << text << i;
Else, one of the safest method is to use
sprintf(count, "%d", i);
And then copy it to your "text" string .
for(k = 0; *(count + k); k++)
{
text += count[k];
}
Thus, you have your required output string
For more info on sprintf, follow:
http://www.cplusplus.com/reference/cstdio/sprintf
cout << text << i;
The << operator for ostream returns a reference to the ostream, so you can just keep chaining the << operations. That is, the above is basically the same as:
cout << text;
cout << i;
cout << "Player" << i ;
cout << text << " " << i << endl;
The easiest way I could figure this out is the following..
It will work as a single string and string array.
I am considering a string array, as it is complicated (little bit same will be followed with string).
I create a array of names and append some integer and char with it to show how easy it is to append some int and chars to string, hope it helps.
length is just to measure the size of array. If you are familiar with programming then size_t is a unsigned int
#include<iostream>
#include<string>
using namespace std;
int main() {
string names[] = { "amz","Waq","Mon","Sam","Has","Shak","GBy" }; //simple array
int length = sizeof(names) / sizeof(names[0]); //give you size of array
int id;
string append[7]; //as length is 7 just for sake of storing and printing output
for (size_t i = 0; i < length; i++) {
id = rand() % 20000 + 2;
append[i] = names[i] + to_string(id);
}
for (size_t i = 0; i < length; i++) {
cout << append[i] << endl;
}
}
There are a few options, and which one you want depends on the context.
The simplest way is
std::cout << text << i;
or if you want this on a single line
std::cout << text << i << endl;
If you are writing a single threaded program and if you aren't calling this code a lot (where "a lot" is thousands of times per second) then you are done.
If you are writing a multi threaded program and more than one thread is writing to cout, then this simple code can get you into trouble. Let's assume that the library that came with your compiler made cout thread safe enough than any single call to it won't be interrupted. Now let's say that one thread is using this code to write "Player 1" and another is writing "Player 2". If you are lucky you will get the following:
Player 1
Player 2
If you are unlucky you might get something like the following
Player Player 2
1
The problem is that std::cout << text << i << endl; turns into 3 function calls. The code is equivalent to the following:
std::cout << text;
std::cout << i;
std::cout << endl;
If instead you used the C-style printf, and again your compiler provided a runtime library with reasonable thread safety (each function call is atomic) then the following code would work better:
printf("Player %d\n", i);
Being able to do something in a single function call lets the io library provide synchronization under the covers, and now your whole line of text will be atomically written.
For simple programs, std::cout is great. Throw in multithreading or other complications and the less stylish printf starts to look more attractive.
You also try concatenate player's number with std::string::push_back :
Example with your code:
int i = 4;
string text = "Player ";
text.push_back(i + '0');
cout << text;
You will see in console:
Player 4
You can use the following
int i = 4;
string text = "Player ";
text+=(i+'0');
cout << (text);
If using Windows/MFC, and need the string for more than immediate output try:
int i = 4;
CString strOutput;
strOutput.Format("Player %d", i);