7
#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".

1
  • 1
    Undefined behaviour. str.at(i) is an integral value. "B" + n where n is an integral value accesses the nth character of the string literal "B". Since the string literal "B" is represented as an array of two char, any value of n less than zero or more than 1 falls off the end. Your code appends the result of all that to rString. Commented Sep 27, 2018 at 14:27

4 Answers 4

9

"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]);
Sign up to request clarification or add additional context in comments.

1 Comment

Or rString += "B" + str.substr(i, 1);
2

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*.

Comments

0

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).

6 Comments

I'd recommend using stringstream
@smac89: Why, out of interest?
@Bathsheba Looks cleaner IMO: ss << 'B' << str.at(i)
@Bathsheba good point, but you only get to do the .str() at the end, not between concatenations
@smac89 I am with Bathsheba, I dont like the boilerplate that comes with stringstream. But there is still room for another answer ;) go ahead and add it. The more different answers, the better
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.