1

I have an application in which I need to combine strings within a variable like so:

int int_arr[4];
int_arr[1] = 123;
int_arr[2] = 456;
int_arr[3] = 789;
int_arr[4] = 10;
std::string _string = "Text " + int_arr[1] + " Text " + int_arr[2] + " Text " + int_arr[3] + " Text " + int_arr[4];

It gives me the compile error

Error C2210: '+' Operator cannot add pointers" on the second string of the expression.

As far as I can tell I am combining string literals and integers, not pointers.

Is there another concatenation operator that I should be using? Or is the expression just completely wrong and should figure out another way to implement this?

BTW I am using Visual Studio 2010

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
Nate Koppenhaver
  • 1,676
  • 3
  • 21
  • 31
  • OK I at least figured out why it is a pointer: this code is from inside a function and the integer array is a argument passed to it – Nate Koppenhaver Feb 03 '11 at 04:01
  • No, the pointer it's complaining about is the _string._ – paxdiablo Feb 03 '11 at 04:09
  • The pointer is the `char*`, specifically the `"Text "`. The C++ compiler treats any literal string as a C-style string, which in reality is just an array of `char`. And since arrays in C are represented as pointers, `"Text "` is a `char*`. – chrisaycock Feb 03 '11 at 04:09
  • 1
    @chrisay: You were fine up until you said arrays are pointers. They not pointers, they are arrays and pointers are pointers, that's it. Two different things. Arrays, however, are implicitly convertible to pointers to the first element. – GManNickG Feb 03 '11 at 04:13

4 Answers4

6

Neither C nor C++ allow concatenation of const char * and int. Even C++'s std::string, doesn't concatenate integers. Use streams instead:

std::stringstream ss;
ss << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = ss.str();
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • 1
    Note however that with `const char* p; int i;`, `p + i` is perfectly well-defined. It's just that `+` doesn't mean concatenation. – Ben Voigt Feb 03 '11 at 05:33
2

You can do this in Java since it uses the toString() method automatically on each part.

If you want to do it the same way in C++, you'll have to explicitly convert those integer to strings in order for this to work.

Something like:

#include <iostream>
#include <sstream>

std::string intToStr (int i) {
    std::ostringstream s;
    s << i;
    return s.str();
}

int main (void) {
    int var = 7;
    std::string s = "Var is '" + intToStr(var) + "'";
    std::cout << s << std::endl;
    return 0;
}

Of course, you can just use:

    std::ostringstream os;
    os << "Var is '" << var << "'";
    std::string s = os.str();

which is a lot easier.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    No you don't. The idiomatic solution in C++ is to use iostream facilities. – Marcelo Cantos Feb 03 '11 at 03:59
  • ... which is explicitly converting them, the same as you do in your answer. – paxdiablo Feb 03 '11 at 04:04
  • Now it highlights the first '+' and says "No operator matches these operands" – Nate Koppenhaver Feb 03 '11 at 04:05
  • I'd check again, @Nate, it works fine in gcc and I'm pretty certain it follows ISO, although whether _Microsoft_ follows ISO, I can't say :-) – paxdiablo Feb 03 '11 at 04:10
  • What I tried was converting the int to a string like 'std::string _STR[4]; _STR[1] = int_arr[1]; _STR[2] = int_arr[2]; _STR[3] = int_arr[3]; _STR[4] = int_arr[4];' – Nate Koppenhaver Feb 03 '11 at 04:11
  • @Nate, when I said convert them to strings, I didn't mean simply _assigning_ them (that won't work). See the code I posted, particularly `intToStr()` for how to do it. Having said that, it's a pretty roundabout way of doing it. That's not so bad for Java since conversion is built into the objects but it's a little harder for C++ since you need a helper function. I'd go for the `ostringstream` solution myself such as that shown at the bottom and in Marcelo's answer. – paxdiablo Feb 03 '11 at 04:15
  • @paxdiablo I restarted VS and it works now. just one of those quirks with MS applications I guess :-) (a while ago I had to reinstall VS because it wouldn't recognise as a library) – Nate Koppenhaver Feb 04 '11 at 04:02
1

A string literal becomes a pointer in this context. Not a std::string. (Well, to be pedantically correct, string literals are character arrays, but the name of an array has an implicit conversion to a pointer. One predefined form of the + operator takes a pointer left-argument and an integral right argument, which is the best match, so the implicit conversion takes place here. No user-defined conversion can ever take precedence over this built-in conversion, according to the C++ overloading rules.).

You should study a good C++ book, we have a list here on SO.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 2
    No, a string literal is an array of characters which *decays* into a pointer to the first element. – Adam Rosenfield Feb 03 '11 at 04:00
  • @Alf: Did you read my ENTIRE answer, including the parenthesized part, before downvoting? – Ben Voigt Feb 03 '11 at 14:48
  • @Ben: sorry no i didn't. But I'd still downvote, since it's incorrect and misleading info first. But you're in good company, so to speak, or at least, what was formerly good company, because MIT's Open University courseware for C++ programming does or did the same. However, it tried to go overboard in committing most errors per page of any course where-so-ever. But anyway, please don't perpetuate that particular misconception: it does so much harm. Plus, about + is incorrect: should be *built-in* +. Cheers, – Cheers and hth. - Alf Feb 03 '11 at 14:51
  • @Alf, I'll update the non-parenthesized part. The part about `+` is correct though, because you can't override operator `+` for built-in types like array and int. – Ben Voigt Feb 03 '11 at 15:02
  • @Ben: one would have to study the question and already know about this to understand that you meant "in the context of + between string literal and int". Why not just add *built-in* to make it correct. Also, remove that disinformation at start. – Cheers and hth. - Alf Feb 03 '11 at 15:04
  • @Ben: yes it's better. but note that built-in + is commutative. always. that means s+i yields same as i+s for built-in +. also it means that you can write i[a] instead of a[i], for built-in []. i.e. "defined with pointer left-argument" is a bit too specific IMHO. :-) – Cheers and hth. - Alf Feb 03 '11 at 15:07
0

A string literal is an expression returning a pointer const char*.

std::stringstream _string_stream;
_string_stream << "Text " << int_arr[1] << " Text " << int_arr[2] << " Text " << int_arr[3] << " Text " << int_arr[4];
std::string _string = _string_stream.str();
vz0
  • 32,345
  • 7
  • 44
  • 77
  • When I put that in it doesn't compile I get an 'Incomplete type is not allowed' error on the _string_stream stringstream. – Nate Koppenhaver Feb 03 '11 at 04:17
  • @Nate: That's because you haven't included the relevant header, `#include `. – Marcelo Cantos Feb 03 '11 at 05:55
  • 1
    -1 "A string literal is in fact a pointer" it isn't, it's an array – Cheers and hth. - Alf Feb 03 '11 at 06:43
  • Yeah, a `"String Literal"` is an array... but the compiler complains about the addition of pointers. That's because the string literal expression returns a pointer. – vz0 Feb 03 '11 at 12:14
  • 1
    @vzo: no, it's because any array expression decays to pointer type where a pointer type is expected, i.e. including in *this particular context*. In some other contexts it does not decay. THat include, for example, a `sizeof` expression (important to understand). Cheers & hth., – Cheers and hth. - Alf Feb 03 '11 at 14:57