C++ "cannot add two pointers", adding a hardcoded string to a CString - c++

I get this error quite often when I try to do something like this
CString filePath = theApp->GetSystemPath() + "test.bmp";
The compiler tells me
error C2110: '+' : cannot add two pointers
But if I change it to this below it works fine?
CString filePath = theApp->GetSystemPath();
filePath += "test.bmp";
The function GetSystemPath returns a LPCTSTR if that has anything to do with it

This has to do with the types of objects that you are dealing with.
CString filePath = theApp->GetSystemPath() + "test.bmp";
The line above is attempting to add the type of GetSystemPath() with "test.bmp" or an LPCTSTR + char[]; The compiler does not know how to do this because their is no + operator for these two types.
The reason this works:
filePath += "test.bmp";
Is because you are doing CString + char[] (char*); The CString class has the + operator overloaded to support adding CString + char*. Or alternatively which is constructing a CString from a char* prior to applying the addition operator on two CString objects. LPCTSTR does not have this operator overloaded or the proper constructors defined.

Well you can't add two pointers. The reason filePath += "test.bmp"; works is that the left hand side is a CString not a pointer. This would also work
CString(theApp->GetSystemPath()) + "test.bmp";
and so would this
theApp->GetSystemPath() + CString("test.bmp");
The rules of C++ prevent you overloading operators unless at least one of the argument is of class type. So it's not possible for anyone to overload operator+ for pointers only.

When doing this:
CString filePath = theApp->GetSystemPath() + "test.bmp";
You are trying to sum two pointers of type const char*. As the compiler is telling you, there is no overload of operator + that accepts two pointers of type const char*s as its input (after all, what you want is not to sum the pointers, but to concatenate the zero-terminated strings pointed to by those pointers).
On the other hand, there is an overload of operator += (as well as of operator +) that takes a CString and a const char*, which is why the second example compiles. For the same reason, this would also work:
CString filePath = theApp->GetSystemPath() + CString("test.bmp");
As well as this:
CString filePath = CString(theApp->GetSystemPath()) + "test.bmp";

The compiler may not be aware that the programmer is intending to concatenate two strings. it merely sees that a char const * is being added with another using the + operator.
I'd try something like this:
CString filePath = CString( theApp->GetSystemPath() ) + CString( "test.bmp" );

Related

How to properly concatenate std::strings in this case? [C++] [duplicate]

I am reading Accelerated C++ by Koenig. He writes that "the new idea is that we can use + to concatenate a string and a string literal - or, for that matter, two strings (but not two string literals).
Fine, this makes sense I suppose. Now onto two separate exercises meant to illuminate this .
Are the following definitions valid?
const string hello = "Hello";
const string message = hello + ",world" + "!";
Now, I tried to execute the above and it worked! So I was happy.
Then I tried to do the next exercise;
const string exclam = "!";
const string message = "Hello" + ",world" + exclam;
This did not work. Now I understand it has something to do with the fact that you cannot concatenate two string literals, but I don't understand the semantic difference between why I managed to get the first example to work (isn't ",world" and "!" two string literals? Shouldn't this not have worked?) but not the second.
const string message = "Hello" + ",world" + exclam;
The + operator has left-to-right associativity, so the equivalent parenthesized expression is:
const string message = (("Hello" + ",world") + exclam);
As you can see, the two string literals "Hello" and ",world" are "added" first, hence the error.
One of the first two strings being concatenated must be a std::string object:
const string message = string("Hello") + ",world" + exclam;
Alternatively, you can force the second + to be evaluated first by parenthesizing that part of the expression:
const string message = "Hello" + (",world" + exclam);
It makes sense that your first example (hello + ",world" + "!") works because the std::string (hello) is one of the arguments to the leftmost +. That + is evaluated, the result is a std::string object with the concatenated string, and that resulting std::string is then concatenated with the "!".
As for why you can't concatenate two string literals using +, it is because a string literal is just an array of characters (a const char [N] where N is the length of the string plus one, for the null terminator). When you use an array in most contexts, it is converted into a pointer to its initial element.
So, when you try to do "Hello" + ",world", what you're really trying to do is add two const char*s together, which isn't possible (what would it mean to add two pointers together?) and if it was it wouldn't do what you wanted it to do.
Note that you can concatenate string literals by placing them next to each other; for example, the following two are equivalent:
"Hello" ",world"
"Hello,world"
This is useful if you have a long string literal that you want to break up onto multiple lines. They have to be string literals, though: this won't work with const char* pointers or const char[N] arrays.
You should always pay attention to types.
Although they all seem like strings, "Hello" and ",world" are literals.
And in your example, exclam is a std::string object.
C++ has an operator overload that takes a std::string object and adds another string to it. When you concatenate a std::string object with a literal it will make the appropriate casting for the literal.
But if you try to concatenate two literals, the compiler won't be able to find an operator that takes two literals.
Since C++14 you can use two real string literals:
const string hello = "Hello"s;
const string message = hello + ",world"s + "!"s;
or
const string exclam = "!"s;
const string message = "Hello"s + ",world"s + exclam;
Your second example does not work because there is no operator + for two string literals. Note that a string literal is not of type string, but instead is of type const char *. Your second example will work if you revise it like this:
const string message = string("Hello") + ",world" + exclam;
The difference between a string (or to be precise, std::string) and a character literal is that for the latter there is no + operator defined. This is why the second example fails.
In the first case, the compiler can find a suitable operator+ with the first argument being a string and the second a character literal (const char*) so it used that. The result of that operation is again a string, so it repeats the same trick when adding "!" to it.
In case 1, because of order of operations you get:
(hello + ", world") + "!" which resolves to hello + "!" and finally to hello
In case 2, as James noted, you get:
("Hello" + ", world") + exclam which is the concat of 2 string literals.
Hope it's clear :)
if we write
string s = "hello" + "world!";
RHS has following type
const char [6] + const char [7]
Now both are built in data types.
ie, they are not std::string types any more.
So, now operator overloading of built in types
as defined by compiler applies.
ie - no more operator + overloaded by std::string.
now let us turn to how compiler overloads
binary operator for two operands of const char * type.
it turns out, compiler did not overload for this case, as it is meaning less.
ie, adding two 'const char *' is semantically wrong as result would be another const char * in run time.
There can be many reason why above does not make sense.
Hence over all, there is one generic rule for any operator overloading. it is :
overloading any operator when all operands of that operator are built-in only. Compiler designers would take of such cases. In our exact question, std::string can't overload two 'const literals' because of this rule, and compiler choose to not to implement the + binary operator for its meaninglessness.
if we like the string literal form and we can a "s" operator as below.
std::string p = "hello"s + "world!"s;
just suffix with s, the meaning changes.
(s overloaded operator)

How to concatenate an integer variable to a string literal

I want to concatenate an int variable to a string literal.String literal is a path.
This is the code
bitmap.Save(L"D:\\screen.jpeg", &clsid);
In this code,i would like to add int variable after screen.I have tried this
bitmap.Save(L"D:\\screen"+k+L".jpeg", &clsid);// where k is the integer variable.
Unfortunately, it did not worked for me.The error was
"error C2110: '+' : cannot add two pointers"
If you're in C++11, use std::to_wstring.
bitmap.Save(L"D:\\screen" + std::to_wstring(k) + L".jpeg", &clsid);
If you're not in C++11 unfortunately, you can use std::wstringstream.
std::wstringstream strm;
strm << L"D:\\screen" << k << L".jpeg";
bitmap.Save(strm.str());
You can use a std::wstring, but you need to call .c_str() in order to use it with API that expect wchar_t *.
std::wstring filename = L"D:\\screen" + std::to_wstring(k) + L".jpeg";
bitmap.Save(filename.c_str(), &clsid);
The compiler complains, because L"D:\\screen.jpeg" is of type wchar[] and k is int (probably).
The simplest way would be to explicitely convert int to wstring (or string) using std::to_wstring (or std::to_string) method.
bitmap.Save((L"D:\\screen" + std::to_wstring(k) + L".jpeg").c_str(), &clsid);

How to Concatenate Two LPCSTRs

I have two LPCSTRs I need to concatenate like so:
if (!rename(directory + originalFileName, directory + fileName)){
std::cout<<originalFileName<<std::endl<<fileName<<std::endl<<std::endl;
}
The only problem however is that I can't use the + operator here. How can I safely concatenate two LPCSTRs like this?
EDIT: Note that an LPCSTR is defined as a const * char while an LPCTSTR is defined as const TCHAR*. The two are different when UNICODE and/or _UNICODE are defined. In this case, they are.
Since LPCSTR is a CONST CHAR* i used this,
(string(dir) + string(originalFileName)).c_str()
Since these strings are const you will need a new buffer to hold the results. That means finding the length of the strings with 'strlen', allocating a buffer with 'new', and copying the strings with 'strcpy' and 'strcat'
That's a hint for how to learn it, instead of me writing the code for you.
Also, there are other options such as using std::string or CString depending on your toolset.
Thanks to WhozCraig, I got the answer:
LPCSTR str1 = "foo",
str2 = "bar";
std::string(str1).append(str2).c_str();
std::cout<<str1;
Returns
foobar
You may use the std::string class to do the heavy lifting because it contains overloaded operator+. However you must ensure that the std::string object is not destroyed before you attempt to read its contents.
One way (in C++03) would be:
std::string dest = std::string(directory) + originalFileName;
std::string src = std::string(directory) + fileName;
if (!rename(dest.c_str(), src.c_str())
// whatever...
Consider storing directory as a std::string in the first place.

C++ Threading and string help please

I am loosing my mind and new to C++ I know C# where I know that it is as simple as
var cat = "cat";
dvar(0,0, "hi" +cat+ "hi");
My issue here is I am developing a game and need to put a string into a function call like so:
string host = "HIST";
dvar(0,0, "s \"test" + host.c_str() + "connection\"");
Also about the threading I am going nuts because my game I can only call in one function at a time but I have a function that is on scree instructions that has a constant while loop so it's to busy handing that looping thread for me to activate any other functions via buttons.
You should do call the function without the c_str() in order to use the non-member string concatenation function.
dvar(0,0, ("s \"test" + host + "connection\"").c_str());
Since host is a std::string type the + operator will result in calling the non-member function operator+ for std::string.
E.g. host + "connection" will result in calling the following function, where "connection" is implicitly converted into a std::string:
std::string operator+(const std::string& lhs, std::string&& rhs);
However, if you would do host.c_str() + "connection", the compiler would be looking for a function that looks like:
??? operator+(const char* lhs, const char* rhs);
Which doesn't exist in the standard library.
The expression:
"s \"test" + host.c_str() + "connection\"
will try to add pointers to char. This cannot work. You might be
looking for a string class?
std::string host = "bar";
// this is quite inefficient
func("foo" + host + "baz");
// this is somewhat better
std::string x = "foo";
x.append(host);
x.append("baz");
func(x);

CStringT to char[]

I'm trying to make changes to some legacy code. I need to fill a char[] ext with a file extension gotten using filename.Right(3). Problem is that I don't know how to convert from a CStringT to a char[].
There has to be a really easy solution that I'm just not realizing...
TIA.
If you have access to ATL, which I imagine you do if you're using CString, then you can look into the ATL conversion classes like CT2CA.
CString fileExt = _T ("txt");
CT2CA fileExtA (fileExt);
If a conversion needs to be performed (as when compiling for Unicode), then CT2CA allocates some internal memory and performs the conversion, destroying the memory in its destructor. If compiling for ANSI, no conversion needs to be performed, so it just hangs on to a pointer to the original string. It also provides an implicit conversion to const char * so you can use it like any C-style string.
This makes conversions really easy, with the caveat that if you need to hang on to the string after the CT2CA goes out of scope, then you need to copy the string into a buffer under your control (not just store a pointer to it). Otherwise, the CT2CA cleans up the converted buffer and you have a dangling reference.
Well you can always do this even in unicode
char str[4];
strcpy( str, CStringA( cString.Right( 3 ) ).GetString() );
If you know you AREN'T using unicode then you could just do
char str[4];
strcpy( str, cString.Right( 3 ).GetString() );
All the original code block does is transfer the last 3 characters into a non unicode string (CStringA, CStringW is definitely unicode and CStringT depends on whether the UNICODE define is set) and then gets the string as a simple char string.
First use CStringA to make sure you're getting char and not wchar_t. Then just cast it to (const char *) to get a pointer to the string, and use strcpy or something similar to copy to your destination.
If you're completely sure that you'll always be copying 3 characters, you could just do it the simple way.
ext[0] = filename[filename.Length()-3];
ext[1] = filename[filename.Length()-2];
ext[2] = filename[filename.Length()-1];
ext[3] = 0;
I believe this is what you are looking for:
CString theString( "This is a test" );
char* mychar = new char[theString.GetLength()+1];
_tcscpy(mychar, theString);
If I remember my old school MS C++.
You do not specify where is the CStringT type from. It could be anything, including your own implementation of string handling class. Assuming it is CStringT from MFC/ATL library available in Visual C++, you have a few options:
It's not been said if you compile with or without Unicode, so presenting using TCHAR not char:
CStringT
<
TCHAR,
StrTraitMFC
<
TCHAR,
ChTraitsCRT<TCHAR>
>
> file(TEXT("test.txt"));
TCHAR* file1 = new TCHAR[file.GetLength() + 1];
_tcscpy(file1, file);
If you use CStringT specialised for ANSI string, then
std::string file1(CStringA(file));
char const* pfile = file1.c_str(); // to copy to char[] buffer