im getting totally confused by this seemingly simple problem.
I have a pain old char, and I want to concatenate it in the middle of a string.
Like so.
string missingOptionArg(char missingArg) {
return "Option -" + missingArg + " requires an operand";
}
I was guessing the + operand was smart enough to deal with this sort of trivial thing, if not, what would be the simplest way of doing this?
To concatenate string literal and char:
std::string miString = std::string("something") + c;
A similar thing happens when you need to concat two strings literals.
Note that "something" is not a std::string, it is a pointer to an array of chars. Then you can't concatenate two string literals using +, that would be adding two pointers and is not what you want.
The correction of your code is in Igor's comment.
Accepted answer is the simplest but other ways to achieve the concatenation.
#include <iostream>
#include <string>
using namespace std;
string missingOptionArgRet(char missingArg) {
string s("Option -");
s += missingArg;
s += " requires an operand";
return s;
}
void missingOptionArgOut(char missingArg, std::string* out) {
*out = "Option -";
*out += missingArg;
*out += " requires an operand";
}
main(int, char**)
{
string s1 = missingOptionArgRet('x');
string s2;
missingOptionArgOut('x', &s2);
cout << "s1 = " << s1 << '\n';
cout << "s2 = " << s2 << '\n';
}
Using += rather than + will prevent temporary string objects. Also there are 2 options. Return by value missingOptionArgRet. This has disadvantage that as a result of return by value the string must be copied to the caller.
The second option missingOptionArgOut can prevent this at the cost of slightly more verbose code. I pass in an already constructed string (by pointer to make it clear its a variable to be modified, but could be passed by reference).
Related
When i try to add text to string i get random values.
Code:
#include <iostream>
using namespace std;
int main()
{
cout << "333" + 4;
}
I get some random text like:↑←#
"333" is a const char [4] not std::string as you might expect(which by the way still doesn't have operator+ for int). Adding 4, you're converting it to const char * and then moving the pointer by 4 * sizeof(char) bytes, making it point to memory with garbage in it.
It happens because those are two different types and the adding operator does not work as you may expect.
If you intend to concatenate the string literals "333" with the int value of 4 than you should simply use count like:
cout << "333" << 4; // outputs: 3334
If you want to display the sum, than use string to int conversion with the stoi() function.
cout << stoi("333") + 4; // outputs: 337
Note: When using stoi(): If the string also contains literals, than the conversion will take the integer value from the beginning of the string or will raise an error in case the string begins with literals:
cout << stoi("333ab3") + 4; // same as 333 + 4, ignoring the rest, starting a
cout << stoi("aa333aa3") + 4; // raise error as "aa" can't be casted to int
As you want to add text to text, solution would be to use proper types:
cout << std::string( "333" ) + "4";
or for c++14 or later:
using namespace std::string_literals;
cout << "333"s + "4"s;
I honestly do not know what you are trying to achieve by adding int to string. In case you want to add 333+4, you need to Parse string in to int like this :
edit:Typo
#include
using namespace std;
int main()
{
cout << std::stoi("333") + 4;
}
im getting totally confused by this seemingly simple problem.
I have a pain old char, and I want to concatenate it in the middle of a string.
Like so.
string missingOptionArg(char missingArg) {
return "Option -" + missingArg + " requires an operand";
}
I was guessing the + operand was smart enough to deal with this sort of trivial thing, if not, what would be the simplest way of doing this?
To concatenate string literal and char:
std::string miString = std::string("something") + c;
A similar thing happens when you need to concat two strings literals.
Note that "something" is not a std::string, it is a pointer to an array of chars. Then you can't concatenate two string literals using +, that would be adding two pointers and is not what you want.
The correction of your code is in Igor's comment.
Accepted answer is the simplest but other ways to achieve the concatenation.
#include <iostream>
#include <string>
using namespace std;
string missingOptionArgRet(char missingArg) {
string s("Option -");
s += missingArg;
s += " requires an operand";
return s;
}
void missingOptionArgOut(char missingArg, std::string* out) {
*out = "Option -";
*out += missingArg;
*out += " requires an operand";
}
main(int, char**)
{
string s1 = missingOptionArgRet('x');
string s2;
missingOptionArgOut('x', &s2);
cout << "s1 = " << s1 << '\n';
cout << "s2 = " << s2 << '\n';
}
Using += rather than + will prevent temporary string objects. Also there are 2 options. Return by value missingOptionArgRet. This has disadvantage that as a result of return by value the string must be copied to the caller.
The second option missingOptionArgOut can prevent this at the cost of slightly more verbose code. I pass in an already constructed string (by pointer to make it clear its a variable to be modified, but could be passed by reference).
I'm new to C++ and I was wondering what the difference is between these two lines:
cout << "John " << "Doe" << endl;
cout << "John " + "Doe" << endl;
The first one works but the second one doesn't. Any ideas?
The first line
cout << "John " << "Doe" << endl;
doesn't concatenate strings. It prints "John " and then it prints "Doe". But there never existed a string "John Doe".
The second line
cout << "John " + "Doe" << endl;
is syntactically wrong. There is no operator+ overloaded for char arrays.
To concatenate string literals you can use
#include <iostream>
#include <string>
using std::literals::string_literals::operator""s;
int main() {
std::cout << "John "s + "Doe"s << std::endl;
// or
auto name = "John "s + "Doe"s;
std::cout << name << std::endl;
}
since C++14. operator""s creates a std::string with operator+.
The second expression is evaluated as
cout << ("John " + "Doe") << endl;
due to the language grammar (often thought of as operator precedence).
But "John " is a const char[6] type and "Doe" is const char[4] type. Due to the +, both decay to a const char* pointer. And pointers cannot be added, so the compiler issues a diagnostic.
In the first case, the overload << on std::ostream for a const char* is used twice, with the results you expect.
First one inserts "John " into the standard output, and then it inserts "Doe". End result is that you see both strings in a sequence.
The second attempts to use the addition operator with arrays as operands. This is ill-formed because such operator does not exist in C++.
For starters there is no concatenation of strings.
In the first statement
cout << "John " << "Doe" << endl;
there are outputted sequentially two strings.
In the second statement
cout << "John " + "Doe" << endl;
there is an attempt to perform the binary operation + with two pointers of the type const char * to which the used string literals having array types are implicitly converted. However the operator + is not defined for pointers.
You may use the operator - for pointers like
std::cout << "John " - "Doe" << std::endl;
This statement syntactically correct but semantically has undefined behavior because the pointers do not point to elements of the same array.
Built-in array types do not have the binary operator +.
This operator is overloaded for the user-defined class template std::basic_string.
You could write for example
#include <iostream>
#include <string>
int main()
{
std::cout << std::string( "John " ) + "Doe" << std::endl;
return 0;
}
Or you could use a user-defined string literal like
#include <iostream>
#include <string>
int main()
{
using namespace std::string_literals;
std::cout << "John "s + "Doe" << std::endl;
return 0;
}
Or in the C++ 17 Standard there is defined new class template std::string_view that you also could use to concatenate strings.
To concatenate two literal strings, just write one after the other with no intervening characters other than whitespace:
const char *lit = "John " "Doe";
std::cout << lit << '\n';
or
std::cout << "John "
"Doe";
etc.
The reason the second one does not work is that you can't concatenate two string literals with + operator. On the other hand, the first approach utilizes chaining of insertion operators to print multiple expressions
The first method is the correct method to concatenate two strings in C++. Whereas the second method, is by default the method to concatenate two strings in Python.
You can't use the second as it is not supported as it indicates addition of two strings and not concatenation (as seen by c++ compiler).
String literals like "foo" cannot be added (i.e. operator+) together for concatenation like in many other languages. This is reasonable in a low-level language like C++ because (in the general case) that would mean an allocation would have to take place.
However, if you are fine with that, then you can use std::string objects which do have those facilities for you. The following works:
cout << string("John ") + string("Doe") << endl;
I've been getting error messages saying
[Error] ISO C++ forbids comparison between pointer and integer [-fpermissive]
and don't know how to fix it.
I've searched stackoverflow for people with same issues, but only came up with this: c++ compile error: ISO C++ forbids comparison between pointer and integer which didn't answer my question. What also confused me is that the error is on line indicated by the HERE comment, which is the if statement, but I don't see any integers in the condition part.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
int main() {
char in[100];
gets(in);
int len = strlen(in);
std::string s(in);
int count = 0;
for (int i = 0; i < len; i++) {
if (s.at(i) == " ") { // <-- HERE
count += 1;
}
}
cout << count;
}
Say the input is Hello World, I am expecting output to be 1, but I didn't get any output.
The expression " " is a string literal with type const char [2].
The expression s.at(i) returns a char&.
So, s.at(i) == " " is trying to find an equality operator taking
char& on the left and a reference to the literal array const char(&)[4] on the right.
It finds one or more candidates for operator==, but the argument types don't match any exactly, so next it tries the implicit conversion sequences - this is where the char& undergoes integral promotion to int, and the array decays to const char*.
It still doesn't find a match with these, and gives up, but that explains why it has int and const char * arguments when the error is emitted.
All that is a long way of saying that you write character literals like ' ' in C++. They're not just a string of length 1 as in some other languages (and you can't write strings with single quotes at all).
Change the if statement
if (s.at(i) == ' ') {
count += 1;
}
since s.at(i) returns char&, " " is a string, and ' ' is a char.
The problem is that " " is a string literal not a character! A character literal would be ' '.
The error is a bit misleading, because " " is acutally a const char*.
C++ differentiates between character strings and single characters in the literals by different quoting symbols (" vs '). The " " in your code is the string literal that contains one space, a single space character would be written as ' '. The function std::string::at returns a single character.
A small example will show you how the compiler looks on that
#include <iostream>
#include <string>
#include <typeinfo> // for typeid
using namespace std;
int main() {
string s = "Hello, world!";
cout << typeid(" ").name() << endl;
cout << typeid(' ').name() << endl;
cout << typeid(s.at(0)).name() << endl;
return 0;
}
see online demo of above code.
But, to be precise, identical types aren't required for comparisons in C++, but the types need to be compatible. Pointers (string literals are considered constant pointers to characters, in fact pointing to the first character in the literal) and integers (to which char is promoted in your case) are not compatible. To "fix" your problem quickly, change s.at(i) == " " to s.at(i) == ' ', but your program will remain problematic: it still contains a lot of C code that's problematic in it self, too. A possible C++ version could be this:
#include <iostream>
#include <string>
using namespace std;
int main() {
int count = 0;
string line;
std::getline(cin, line);
for (const auto c: line) {
if (c == ' ') {
count++;
}
}
cout << "Your input \""<< line << "\" contains " << count << " space(s)." << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
string wordB(string input);
int main() {
//ask for word
cout << "Enter a word\n";
//get word
string input = "";
cin >> input;
//return with b in between all letters
cout << wordB(input);
cout << endl << input;
}
string wordB(string str) {
string rString = "";
for (unsigned i = 0; i < str.length(); ++i) {
rString += "B" + str.at(i);
}
cout << endl << rString;
return rString;
}
Trying to display the word a users enter where between every character there is the letter "B". When I run this with the word "join" I get back "trtr".
"B" + str.at(i); doesn't do what you seem to think it does; it's not string conctatenation. It says: take a char* pointer pointing to the beginning of the string literal "B", advance it by the number of characters equal to the ASCII code of character str.at(i), and treat the resulting pointer as pointing to a nul-terminated string. Unless str.at(i) happens to be '\x0' or '\x1' (unlikely), your program exhibits undefined behavior.
There are many different ways to do what you want. Here's one:
rString.push_back('B');
rString.push_back(str[i]);
A particularly nice fix, available from C++14 onwards, is to write
rString += "B"s + str.at(i);
noting the s, which is a user-defined literal. That then forces the overloaded + operator on std::string to be used, rather than the built-in +, which is actually performing dubious (and potentially undefined) pointer arithmetic on the const char[2] literal "B" decayed to a const char*.
Admittedly it is a pitfall... in this line
rString += "B" + str.at(i);
the "B" + str.at(i) part is not doing what one might expect: It adds str.at(i) to a char pointer (pointing to the first letter of "B"). The fix is easy:
rString += std::string("B") + str.at(i);
// ^-------------- now calls the correct operator
Just as a curiosity consider this:
(rString += "B") += str.at(i);
I do not recommend to write it (its too obfuscated), but it does the right thing, because there is a std::string::operator+(char*) and a std::string::operator+(char).
What you are seeing is as a result of order of evaluation.
The += operator will force the right-hand-side of the expression to be evaluated and the result will be appended to the string.
This is what causes the problem you are facing because the right-hand-side is not std::string, and therefore the meaning of the + operator in that rhs simply translates to pointer arithemetic not string concatenation as you would expect.
A simple fix is to be more explicit and do this:
rString = rString + "B" + str.at(i);
This will now cause the compiler to first evaluate the right-hand-side of the = operator as a string and then you get concatenation. It also gives the added benefit of allowing the compiler to inform you if the right-hand side is not a string.
Another alternative is to use string streams. I think it looks cleaner so here it is:
#include <sstream>
...
string wordB(string str) {
std::ostringstream oss;
for (unsigned i = 0; i < str.length(); ++i) {
oss << 'B' << str.at(i);
}
cout << endl << oss.str();
return oss.str();
}