Concatenation operator in C++? - c++

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

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();

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.

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.

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();

Related

Unable to concat strings in C++?

I have a method to log with the following definition:
void log(std::string s) {
std::string tag = "main";
std::cout << tag << " :" << s << std::endl;
}
I'm trying to call this method like this:
log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));
direction and count are integers.
I'm getting this following error with << underlined in red:
no operator << matches these operands.
operand types are const char [10] << std::string
I have #include<string> in my header to make sure my strings are working as they should.
I tried std::string("direction") and still the issue was same.
Beginner in C++. Help would be appreciated.
operator<< isn't used for arbitrary string concatenation - it is called an "output stream operator", and it is only used in the context of std::ostream.
When you say...
std::cout << tag << " :" << s << std::endl;
...you're actually writing code roughly equivalent to:
std::cout.operator<<(tag).operator<<(" :").operator<<(s).operator<<(std::endl);
As you can see operator<< knows how to work with std::cout and std::string, but not between strings.
In order to concatenate std::string instances, you can simply use operator+:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
Please note that this concatenation technique is not the most efficient: you might want to look into std::stringstream or simply use std::string::reserve to avoid unnecessary memory allocations.
Substitute the << with the + operator as you are manipulating the string, not the stream:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
If you're determined to use the operator<< notation you need an object that understands it.
Here's such an object (I make no claims that this is a good idea):
#include <string>
#include <sstream>
#include <iostream>
void log(std::string s) {
std::string tag = "main";
std::cout << tag << " :" << s << std::endl;
}
struct string_accumulator
{
std::ostringstream ss;
template<class T>
friend string_accumulator& operator<<(string_accumulator& sa, T const& value)
{
sa.ss << value;
return sa;
}
template<class T>
friend string_accumulator& operator<<(string_accumulator&& sa, T const& value)
{
return operator<<(sa, value);
}
operator std::string () { return ss.str(); }
};
inline auto collect() -> string_accumulator
{
return string_accumulator();
}
int main()
{
int direction = 1;
int count = 1;
log(collect() << "direction" << std::to_string(direction) << ", count: " << std::to_string(count));
}
The prototype of your function is void log(std::string s);. It awaits for an std::string. So you need to pass a string to it, not a stream!
So, change this:
log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));
to this:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
where I only changed the << operator to + operator. It will now concatenate everything inside the parentheses to a single std::string.
Your attempt implies that you wanted to pass std::ostream as the parameter. Maybe you want to read C++ Passing ostream as parameter. However, if I were you, I would just overload <<.
why don't you use:
// just include thisusing namespace std;

How to use Arrays, with Strings

I'm a C++ programmer, who's still in the nest, and not yet found my wings. I was writing a Calendar program, and I discovered, that C++ does not support a string type. How do I make an Array, that will be able to store strings of characters?
I've thought of creating an enumerated data type, as the array type. While, it will work, for my Calendar, it won't work if say I was creating a database of the names of students in my class.
http://prntscr.com/7m074w I got; "error, 'string' does not name a type."
that C++ does not support a string type.
Wrong info, you can create an character array as follows
char array[length];
//Where length should be a constant integer
Otherwise you can depend on standard template library container, std::string
If you have C++11 compiler you can depend on std::array
The C++ Standard Library includes a string type, std::string. See http://en.cppreference.com/w/cpp/string/basic_string
The Standard Library also provides a fixed-size array type, std::array. See http://en.cppreference.com/w/cpp/container/array
But you may also want to learn about the dynamically-sized array type, std::vector. See http://en.cppreference.com/w/cpp/container/vector
The language also includes legacy support for c-strings and c-arrays, which you can find in a good C++ or C book. See The Definitive C++ Book Guide and List
An example of how to use an array/vector of strings:
#include <string>
#include <array>
#include <vector>
#include <iostream>
int main() {
std::array<std::string, 3> stringarray;
stringarray[0] = "hello";
stringarray[1] = "world";
// stringarray[2] contains an empty string.
for (size_t i = 0; i < stringarray.size(); ++i) {
std::cout << "stringarray[" << i << "] = " << stringarray[i] << "\n";
}
// Using a vector, which has a variable size.
std::vector<std::string> stringvec;
stringvec.push_back("world");
stringvec.insert(stringvec.begin(), "hello");
stringvec.push_back("greetings");
stringvec.push_back("little bird");
std::cout << "size " << stringvec.size()
<< "capacity " << stringvec.capacity()
<< "empty? " << (stringvec.empty() ? "yes" : "no")
<< "\n";
// remove the last element
stringvec.pop_back();
std::cout << "size " << stringvec.size()
<< "capacity " << stringvec.capacity()
<< "empty? " << (stringvec.empty() ? "yes" : "no")
<< "\n";
std::cout << "stringvec: ";
for (auto& str : stringvec) {
std::cout << "'" << str << "' ";
}
std::cout << "\n";
// iterators and string concatenation
std::string greeting = "";
for (auto it = stringvec.begin(); it != stringvec.end(); ++it) {
if (!greeting.empty()) // add a space between words
greeting += ' ';
greeting += *it;
}
std::cout << "stringvec combined :- " << greeting << "\n";
}
Live demo: http://ideone.com/LWYevW
You can create an array of characters by char name[length];.
C++ also has a data type string. You can create an array of strings and store what values you'd like. here .
So
use array of characters
use string data type
For Example -
#include <iostream>
#include <string>
int main ()
{
//To Create a String
std::string s0 ("Initial string");
return 0;
}
C++ does have a string type: string from #include <string>
If you don't want to use that, you can also use char* name = "YourTextHere..." or `char[length+1] name = "YourTextHere"

C++ const casting

I am trying to print the value of a const but it is not working. I am making a return to C++ after years so I know casting is a possible solution but I can't get that working either.
The code is as follows:
//the number of blanks surrounding the greeting
const int pad = 0;
//the number of rows and columns to write
const int rows = pad * 2 + 3;
const string::size_type cols = greeting.size() + pad * 2 + 2;
cout << endl << "Rows : " + rows;
I am trying to print the value of 'rows' without success.
You want:
cout << endl << "Rows : " << rows;
Note this has nothing to do with const - C++ does not allow you to concatenate strings and numbers with the + operator. What you were actually doing was that mysterious thing called pointer arithmetic.
You're almost there:
cout << endl << "Rows : " << rows;
The error is because "Rows : " is a string literal, thus is a constant, and generally speaking is not modified as you may think.
Going slightly further, you likely used + (colloquially used as a concatenation operation) assuming you needed to build a string to give to the output stream. Instead operator << returns the output stream when it is done, allowing chaining.
// It is almost as if you did:
(((cout << endl) << "Rows : ") << rows)
I think you want:
std::cout << std::endl << "Rows : " << rows << std::endl;
I make this mistake all the time as I also work with java a lot.
As others have pointed out, you need
std::cout << std::endl << "Rows : " << rows << std::endl;
The reason (or one of the reasons) is that "Rows : " is a char* and the + operator for char*s doesn't concatenate strings, like the one for std::string and strings in languages like Java and Python.

How to form a C++ string from concatenations of string literals?

I would like concatenate string literals and ints, like this:
string message("That value should be between " + MIN_VALUE + " and " + MAX_VALUE);
But that gives me this error:
error: invalid operands of types ‘const char*’ and ‘const char [6]’ to binary ‘operator+’|
What is the correct way to do that? I could split that in 2 string declarations (each concatenating a string literal and a int), but that's ugly. I've also tried << operator.
Thanks
You should probably use stringstream for this.
#include <sstream>
std::stringstream s;
s << "This value shoud be between " << MIN_VALUE << " and " << MAX_VALUE;
message = s.str();
The c++ way to do this is to use a stringstream then you can use the << operator. It will give you a more consistent code feel
There are many ways to do this, but my favourite is:
string message(string("That value should be between ") + MIN_VALUE + " and " + MAX_VALUE);
That extra string() around the first literal makes all the difference in the world because there is an overloaded string::operator+(const char*) which returns a string, and operator+ has left-to-right associativity, so the whole thing is turned into a chain of operator+ calls.
#include <sstream>
#include <string>
template <typename T>
std::string Str( const T & t ) {
std::ostringstream os;
os << t;
return os.str();
}
std::string message = "That value should be between " + Str( MIN_VALUE )
+ " and " + Str( MAX_VALUE );
You probably want to use a stringstream like this:
std::stringstream msgstream;
msgstream << "That value should be between " << MIN_VALUE << " and " << MAX_VALUE;
std::string message(msgstream.c_str());

Comparing Character Literal to Std::String in C++

I would like to compare a character literal with the first element of string, to check for comments in a file. Why use a char? I want to make this into a function, which accepts a character var for the comment. I don't want to allow a string because I want to limit it to a single character in length.
With that in mind I assumed the easy way to go would be to address the character and pass it to the std::string's compare function. However this is giving me unintended results.
My code is as follows:
#include <string>
#include <iostream>
int main ( int argc, char *argv[] )
{
std::string my_string = "bob";
char my_char1 = 'a';
char my_char2 = 'b';
std::cout << "STRING : " << my_string.substr(0,1) << std::endl
<< "CHAR : " << my_char1 << std::endl;
if (my_string.substr(0,1).compare(&my_char1)==0)
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
std::cout << "STRING : " << my_string.substr(0,1) << std::endl
<< "CHAR : " << my_char2 << std::endl;
if (my_string.substr(0,1).compare(&my_char2)==0)
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
std::cout << "STRING : " << my_string << std::endl
<< "STRING 2 : " << "bob" << std::endl;
if (my_string.compare("bob")==0)
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
}
Gives me...
STRING : b
CHAR : a
NOPE...
STRING : b
CHAR : b
NOPE...
STRING : bob
STRING 2 : bob
WOW!
Why does the function think the sub-string and character aren't the same. What's the shortest way to properly compare chars and std::string vars?
(a short rant to avoid reclassification of my question.... feel free to skip)
When I say shortest I mean that out of a desire for coding eloquence. Please note, this is NOT a homework question. I am a chemical engineering Ph.D candidate and am coding as part of independent research. One of my last questions was reclassified as "homework" by user msw (who also made a snide remark) when I asked about efficiency, which I considered on the border of abuse. My code may or may not be reused by others, but I'm trying to make it easy to read and maintainable. I also have a bizarre desire to make my code as efficient as possible where possible. Hence the questions on efficiency and eloquence.
Doing this:
if (my_string.substr(0,1).compare(&my_char2)==0)
Won't work because you're "tricking" the string into thinking it's getting a pointer to a null-terminated C-string. This will have weird effects up to and including crashing your program. Instead, just use normal equality to compare the first character of the string with my_char:
if (my_string[0] == my_char)
// do stuff
Why not just use the indexing operator on your string? It will return a char type.
if (my_string[0] == my_char1)
You can use the operator[] of string to compare it to a single char
// string::operator[]
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str ("Test string");
int i; char c = 't';
for (i=0; i < str.length(); i++)
{
if (c == str[i]) {
std::cout << "Equal at position i = " << i << std::endl;
}
}
return 0;
}
The behaviour of the first two calls to compare is entirely dependent on what random memory contents follows the address of each char. You are calling basic_string::compare(const char*) and the param here is assumed to be a C-String (null-terminated), not a single char. The compare() call will compare your desired char, followed by everything in memory after that char up to the next 0x00 byte, with the std::string in hand.
Otoh the << operator does have a proper overload for char input so your output does not reflect what you are actually comparing here.
Convert the decls of and b to be const char[] a = "a"; and you will get what you want to happen.
Pretty standard, strings in c++ are null-terminated; characters are not. So by using the standard compare method you're really checking if "b\0" == 'b'.
I used this and got the desired output:
if (my_string.substr(0,1).compare( 0, 1, &my_char2, 1)==0 )
std::cout << "WOW!" << std::endl;
else
std::cout << "NOPE..." << std::endl;
What this is saying is start at position 0 of the substring, use a length of 1, and compare it to my character reference with a length of 1. Reference