How do I insert a variable result into a string in C++ - c++

I just started learning C++ in Qt and I was wondering how can I put a variables result in a string? I'm trying to use this for a simple application where someone puts their name in a text field then presses a button and it displays there name in a sentence. I know in objective-c it would be like,
NSString *name = [NSString stringWithFormatting:#"Hello, %#", [nameField stringValue]];
[nameField setStringValue:name];
How would I go about doing something like this with C++? Thanks for the help

I assume we're talking about Qt's QString class here. In this case, you can use the arg method:
int i; // current file's number
long total; // number of files to process
QString fileName; // current file's name
QString status = QString("Processing file %1 of %2: %3")
.arg(i).arg(total).arg(fileName);
See the QString documentation for more details about the many overloads of the arg method.

You donĀ“t mention what type your string is. If you are using the standard library then it would be something along the lines of
std::string name = "Hello, " + nameField;
That works for concatenating strings, if you want to insert other complex types you can use a stringstream like this:
std::ostringstream stream;
stream << "Hello, " << nameField;
stream << ", here is an int " << 7;
std::string text = stream.str();
Qt probably has its own string types, which should work in a similar fashion.

I would use a stringstream but I'm not 100% sure how that fits into your NSString case...
stringstream ss (stringstream::in);
ss << "hello my name is " << nameField;
I think QString has some nifty helpers that might do the same thing...
QString hello("hello ");
QString message = hello % nameField;

You could use QString::sprintf. I haven't found a good example of it's use yet, though. (If someone else finds one, feel free to edit it in to this answer).
You might be interested in seeing information about the difference between QString::sprintf and QString::arg.

Related

What is the most appropriate way to concatenate with MFC's CString

I am somewhat new to C++ and my background is in Java. I am working on a hdc printing method.
I would like to know the best practice for concatenating a combination of strings and ints into one CString. I am using MFC's CString.
int i = //the current page
int maxPage = //the calculated number of pages to print
CString pages = ("Page ") + _T(i) + (" of ") + _T(maxPage);
I would like it to look like 'Page 1 of 2'. My current code does not work. I am getting the error:
Expression must have integral or enum type
I have found more difficult ways to do what I need, but I want to know if there is a simple way similar to what I am trying. Thanks!
If that's MFC's CString class, then you probably want Format which is a sprintf-alike for it:
CString pages;
pages.Format(_T("Page %d of %d"), i, maxPage);
i.e. you can assemble the string using regular printf-format specifiers substituting in the numbers at runtime.
You can use also stringstream classes
#include <sstream>
#include <string>
int main ()
{
std::ostringstream textFormatted;
textFormatted << "Page " << i << " of " << maxPage;
// To convert it to a string
std::string s = textFormatted.str();
return 0;
}
std::string has all you need:
auto str = "Page " + std::to_string(i) + " of " + std::to_string(maxPage);
As stated correctly in the comment, you can access the underlying C-string via str.c_str(). Here is a live working example.
If you have C++11 you can use std::to_string: std::string pages = std::string("Page ") + std::to_string(i) + (" of ") + std::to_string(maxPage);
If you don't have C++11 you can use an ostringstream or boost::lexical_cast.

How to print string literal and QString with qDebug?

Is there any easy way to get the following work? I mean is there any helper class in Qt which prepares the string for qDebug?
QString s = "value";
qDebug("abc" + s + "def");
You can use the following:
qDebug().nospace() << "abc" << qPrintable(s) << "def";
The nospace() is to avoid printing out spaces after every argument (which is default for qDebug()).
No really easy way I am aware of. You can do:
QByteArray s = "value";
qDebug("abc" + s + "def");
or
QString s = "value";
qDebug("abc" + s.toLatin1() + "def");
According to Qt Core 5.6 documentation you should use qUtf8Printable() from <QtGlobal> header to print QString with qDebug.
You should do as follows:
QString s = "some text";
qDebug("%s", qUtf8Printable(s));
or shorter:
QString s = "some text";
qDebug(qUtf8Printable(s));
See:
http://doc.qt.io/qt-5/qtglobal.html#qPrintable
http://doc.qt.io/qt-5/qtglobal.html#qUtf8Printable
Option 1: Use qDebug's default mode of a C-string format and variable argument list (like printf):
qDebug("abc%sdef", s.toLatin1().constData());
Option 2: Use the C++ version with overloaded << operator:
#include <QtDebug>
qDebug().nospace() << "abc" << qPrintable(s) << "def";
Reference: https://qt-project.org/doc/qt-5-snapshot/qtglobal.html#qDebug
Just rewrite your code like this:
QString s = "value";
qDebug() << "abc" << s << "def";
I know this question is a bit old, but it appears nearly on top when searching for it in the web. One can overload the operator for qDebug (more specific for QDebug) to make it accept std::strings like this:
inline QDebug operator<<(QDebug dbg, const std::string& str)
{
dbg.nospace() << QString::fromStdString(str);
return dbg.space();
}
This thing is for years in all of my projects, I nearly forget it is still not there by default.
After that, usage of << for qDebug() is a lot more usable imho. You can even mix QString and std::string. Some additional(but not really intended) feature is, that you sometimes can throw in integers or other types that allow implicit conversion to std::string .

RapidXML weird parsing

I have a very annoying problem and I'm trying to solve it for lots of hours.
I'm using rapidXML with C++ to parse an XML file:
xml_document<> xmlin;
stringstream input; //initialized somewhere else
xmlin.clear();
xmlin.parse<0>(&(input.str()[0]));
cout << "input:" << input.str() << endl << endl;
xml_node<char> *firstnode = xmlin.first_node();
string s_type = firstnode->first_attribute("type")->value();
cout << "type: " << s_type << endl;
However I got this on the stdout:
input:<?xml version="1.0" encoding="utf-8"?><testxml command="testfunction" type="exclusive" />
type: exclusive" />
What could be the reason of this (printing the s_type variable)?
It's very annoying since I can't process the xml well.
Actually I found the solution.
Stringstream doesn't like when its content is getting modified (rapidXML does a fast in-situ parsing which means it modificates the contents of the array it gets).
However in the docs I read that string class does not like it either.
From the string::c_str documentation page:
the values in this array should not be modified in the program
But when I create a string from the stream it is working as it is expected:
xml_document<> xmlin;
stringstream input; //initialized somewhere else
string buffer = input.str()
xmlin.clear();
xmlin.parse<0>(&(buffer[0]));
I think the problem is in the code you haven't shown... Start by trying this, using a literal string - this works just fine for me...
xml_document<> xmlin;
char *input = "<?xml version=\"1.0\" encoding=\"utf-8\"?><testxml command=\"testfunction\" type=\"exclusive\" />";
xmlin.parse<0>(input);
xml_node<char> *firstnode = xmlin.first_node();
std::string s_type = firstnode->first_attribute("type")->value();
I would personally recommend this approach
xml_document<> doc;
string string_to_parse;
char* buffer = new char[str_to_parse.size() + 1];
strcpy (buffer, str_to_parse.c_str());
doc.parse<0>(buffer);
delete [] cstr;
making a non const char array out of the string you want to parse. I have always found this way safer and more reliable.
I used to do such crazy things as
string string_to_parse;
doc.parse<0>(const_cast<char*>(string_to_parse.c_str()));
and it "worked" for a long time (until the day it didn't when I needed to reuse the original string). Since RapidXML can modify the char array it is parsing and since it is not recommended to change str::string via c_str() I have always used the approach of copying my string to a non const char array and pass that to the parser. It may not be optimal and uses additional memory, but it is reliable and I have never had any errors or problems with it to date. Your data will be parsed and the original string can be reused without fear of it having been modified.

cannot convert from std::basic_string to int Visual studio C++

I've written a small sudoku program and I want to make it so each time you press a certain button the text on that button is the previous number incremented by one.
So, for instance, I have a large button that says "1" and I click on it, it will say "2" then "3" if I click it again, and so on until "9".
At first I thought it would be pretty simple, I used this code to call an integer that counts to 9, a string that equals the button text and then I tried to convert int to string and I failed, it gave me the error bellow. This is the code:
int s = 0;
String^ mystr = a0->Text;
std::stringstream out;
out << s;
s = out.str(); //this is the error apparently.
s++;
And this is the error:
error C2440: '=' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'int'
I tried searching on MSDN for that error but it's different than mine, and I left the page more confused than when I entered it.
Also for reference, I'm using a Windows Forms Application, in Windows XP, in Visual Studio 2010 C++.
If you want to convert std::string or char* to int by using std::stringstream, it could look like this:
int s = 0;
std::string myStr("7");
std::stringstream out;
out << myStr;
out >> s;
or you can construct this stringstream directly by using myStr which yields same result:
std::stringstream out(myStr);
out >> s;
And if you want to convert System::String^ to std::string, it could look like this:
#include <msclr\marshal_cppstd.h>
...
System::String^ clrString = "7";
std::string myStr = msclr::interop::marshal_as<std::string>(clrString);
although as Ben Voigt has pointed out: when you start with System::String^, you should convert it by using some function from .NET Framework instead. It could also look like this:
System::String^ clrString = "7";
int i = System::Int32::Parse(clrString);
Since you're starting with String^, you want something like:
int i;
if (System::Int32::TryParse(a0->Text, i)) {
++i;
a0->Text = i.ToString();
}
There are a lot of ways to convert a string to an int in C++ --the modern idiom may be to install the boost libraries and use boost::lexical_cast.
However, your question indicates you don't have a very good grasp of C++. If the point of your effort is to learn more about C++, you might want to try one of the many simpler tutorials before you try something as complicated as a sudoku.
If you just want to build a sudoku with Windows forms, I'd recommend you drop C++ and look at C# or VB.Net, which have many fewer pitfalls for an inexperienced programmer.
s is of type int. str() returns a string. You can't assign a string to an int. Use a different variable to store the string.
Here's some possible code (albeit it won't compile)
string text = GetButtonText(); //get button text
stringstream ss (text); //create stringstream based on that
int s;
ss >> s; //format string as int and store into s
++s; //increment
ss << s; //store back into stringstream
text = ss.str(); //get string of that
SetButtonText (text); //set button text to the string

C++ external file read: I know how to find and read a string, findMe. But how do I deal with findMei (finding any number, i, of the string)?

Apologies in advance, because I suspect this may be a silly question.
I have written a function for reading in data from an external file. I then use the data to perform calculations using other code I have written.
The function works by finding a data label that looks like this:
const std::string findMe = "<dataLabel>";
Each time I want to find data, I replace dataLabel with the label of whichever data I need from the file.
Here's what I want to do.
I don't want to have to write in the label of the data I want each time. I want to be able to do this:
for (int i = 0; i < anyNumberOfDataSets; i++)
{
findMe = "<dataLabeli>";
// Then run function for reading in data, put data into a vector.
}
I could then add any number of data sets to my external file, give each one the title
, and have each data set read into a vector.
The problem is, I simply can't figure out how to write findMe = "<dataLabeli>". Is this even possible?
I have tried things like, findMe = "<dataLabel" << i <<, but no luck!
Any suggestions would be much appreciated.
It is very hard to understand what you mean, but I guess you want this
#include <sstream>
#include <string>
for (int i = 0; i < anyNumberOfDataSets; i++)
{
std::ostringstream strm;
strm << "<dataLabel" << i << ">";
const std::string findMe = strm.str();
//...
//proceed with searching findMe
}
You can read more about string streams, for instance, here
you've already got the right answer, so this is just trying to help you with solving such problems in the future:
Your core problem here is to convert the integer i into a string s (if you've done this, than you just do findMe = "<datalabel"; findMe += s; findMe += ">";.
Googling for c++ convert integer into string will give you this as the first result. Problem solved.
This is not saying "use google before/instead of asking", it's rather "try to identify the core problem".
Another solution:
using namespace boost;
findMe = str(format("<dataLabel%d>") % i);
This will substitute %d with the value of i, formatted like printf() does.