Reputation: 2234
Here is a code that doesn't compile on my machine. I have a workaround but I don't understand the behavior and why is the workaround
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
string pdfPath;
string tempFolder;
//... both strings are read from config file ...//
string listPath = tempFolder+"\\"+"list";
string dir = "dir "+"\""+pdfPath+"\" "+"/b >"+" \""+listPath+"\"";
//... all the other stuff ...//
}
This code does not compile and gives this error:
|71|error: invalid operands of types 'const char [5]' and 'const char [2]' to binary 'operator+'|
This is the line it refers to: string dir = "dir "+"\""+pdfPath+"\" "+"/b >"+" \""+listPath+"\"";
If, however, I change it to:
string dir = "dir "+string("\"")+pdfPath+"\" "+"/b >"+" \""+listPath+"\"";
How comes it cares for "\""
construction in one place but doesn't care about the others? I've concatenated with "\""
before (in the same program) and it didn't cause any problems. And this works just fine:
string dir = "dir "+pdfPath+"\" "+"/b >"+" \""+listPath+"\"";
although it haves that "\""
.
Upvotes: 1
Views: 408
Reputation: 310980
Always read closely error messages. The error message you got is clear enough
|71|error: invalid operands of types 'const char [5]' and 'const char [2]' to binary 'operator+'
In this statement
string dir = "dir "+"\""+pdfPath+"\" "+"/b >"+" \""+listPath+"\"";
you are trying to add string literals "dir "
and "\""
. The first one has type const char [5]
and the second one - const char [2] (string literals include terminating zero '\0').
That is it is what you are trying to do
"dir "+"\""
However arrays have no built-in operator +. You may not add arrays.
In the second case
string dir = "dir "+string("\"")+pdfPath+"\" "+"/b >"+" \""+listPath+"\"";
you add
"dir "+string("\"")
that is a string literal with an object of type std::string. Class std::string has overloaded operator +
for operands of type std::string (more precisely there is non-member function that overloads operator + for objects of type std::string). As the class std::string has a conversion constructor that can convert an object of type const char * to an object of type std::string then the compiler applies this conversion to the string literal and calls operator + for objects of class std::string.
In fact this expression is converted by the compiler to the following
string( "dir " ) + string("\"") // call of the conversion constructor
operator + ( string( "dir " ), string("\"") ) // call of the operator
Upvotes: 1
Reputation: 33536
There are several overlapping issues here, so you may find it hard to understand at first sight and you may get a false impression on the overall things.
The most important ones are (not exhaustively):
"mom"
is not a string. This is effectively "pointer to array of const char"5
to a pointer, but there is no way you can add two pointers togetherstd::string
the class can provide its own operators, including +
and -
a + b + c + d + e + ..
where no operator has a higher precedence than others, can analyze the expression in any orderLet's first inspect the 4th point.
Given
string dir = "dir "+"\""+pdfPath+"\" "+"/b >"+" \""+listPath+"\"";
How does that evaluate? All +
operators are equal. None has higher priority. The only sure thing is that the =
-assign will be executed last. A common way to do across compilers is to either evaluate it left-hand-first or right-hand-first. So, one compiler will do:
string dir = ("dir "+("\""+(pdfPath+("\" "+("/b >"+(" \""+(listPath+"\""))))));
and other can do it:
string dir = (((((("dir "+"\"")+pdfPath+"\" ")+"/b >")+" \"")+listPath)+"\"");
(Or they can make it in any other order way they like)
Now, in the second example, note that in the inner-most parens, there's a:
("dir "+"\"")
Hence, some compilers can report here an error of "being unable to add pointer to pointer". See issue 2nd in the above list.
On the other hand, a left-hand-first compiler will not fail here, because in the first example, the innermost part is
(listPath+"\"")
and the listPath is a std::string
. See 3rd point in the list above. std::string
defines an operator+ that handles adding string-to-pointer. This operator returns a std::string
again. So the innermost parens result in a string, that will be added to string, and so on. So - no complation error.
But this is all compiler-dependent, because the order of evaluation is not strictly defined.
The easiest way to solve that problem, and cover all compilers, is to convert all parts to strings:
string dir = string("dir ") + string("\"") + ...
and so on. But, that's irritating. Therefore, there are many libraries, that allow you to use some kind of "format strings" that work as "patterns" that are filled with "data". This saves you from worrying and also makes the code clearer.
An example could look like:
string dir = format_me( "dir \"%s\" /b > \"%s\"", pdfPath, listPath);
string dir = format_me( "dir \"{0}\" /b > \"{1}\"", pdfPath, listPath);
or stream-like:
buffer buff;
buff << "dir \"" << pdfPath << "\" /b > \"";
buff << listPath << "\"";
string cmd = buff.toString();
The %s
and {0}
markers are "placeholders" where the parameters will be put. Those examples are artificial and are not related to any library. Check your platform and libs to find the formatter you like the most. For example, Boost
provides you with stringstream
class. It works similar to the last stream-like one
Upvotes: 1
Reputation: 1845
You can concatenate a c-string to an std::string
:
std::string dir; dir = dir + "dir " + pdfPath;
but you cannot concatenate a c-string to a c-string to a using the operator+()
in C++
"one" + "two"
tells the compiler to add the pointer value of the first c-string to the second one. std::string("one") + std::string("two")
concatenates the two strings. If you want to concatenate two c-strings you will have to do "one" "two"
Upvotes: 2
Reputation: 249203
You cannot concatenate C string literals using +
in C or C++. But you can concatenate them using no operator at all:
string dir = "dir " "\"" + pdfPath + "\" " "/b >" " \"" + listPath + "\"";
The compiler is smart enough to put adjacent string literals together, and there is no runtime cost for the concatenation then.
Upvotes: 2