sam
sam

Reputation: 99

Logical error. Elements in std::string not replaced properly with for loop

I'm currently doing a programming exercise from a C++ book for beginners. The task reads as follows: "Write a function that reverses the characters in a text string by using two pointers. The only function parameter shall be a pointer to the string."

My issue is that I haven't been able to make the characters swap properly, see the output below. (And I also made the assumption that the function parameter doesn't count, hence why I'm technically using three pointers).

I am almost certain that the problem has to do with the for loop. I wrote this pseudocode:

  1. Assign value of element number i in at_front to the 1st element in transfer_back.
  2. Assign value of element number elem in at_back to element number i in at_front.
  3. Assign value of the 1st element in transfer_back to element number elem in at_back.
  4. Increment i, decrement elem. Repeat loop until !(i < elem)

I wasn't sure whether of not I was supposed to take the null terminator into account. I tried writing (elem - 1) but that messed up with the characters even more so I've currently left it as it is.


#include <iostream>
#include <string>
using namespace std;

void strrev(string *at_front) {
    string *transfer_back = at_front, *at_back = transfer_back;
    int elem = 0;

    while(at_back->operator[](elem) != '\0') {
        elem++;
    }

    for(int i = 0; i < elem; i++) {
        transfer_back->operator[](0) = at_front->operator[](i);
        at_front->operator[](i) = at_back->operator[](elem);
        at_back->operator[](elem) = transfer_back->operator[](0);
        elem--;
    }
}

int main() {

    string str = "ereh txet yna";
    string *point_str = &str;

    strrev(point_str);

    cout << *point_str << endl;

    return 0;
}

Expected output: "any text here"

Terminal window: "xany text her"

The fact that the 'x' has been assigned to the first element is something I haven't been able to grasp.

Upvotes: 0

Views: 68

Answers (2)

GPrathap
GPrathap

Reputation: 7820

Here is the correct answer

void strrev(string *at_front) {
    string *at_back = at_front;
    char transfer_back;
    int elem = 0;

    while(at_back->operator[](elem) != '\0') {
        elem++;
    }

    for(int i = 0; i <elem; i++) {
        transfer_back = at_front->operator[](i);
        at_front->operator[](i) = at_back->operator[](elem);
        at_back->operator[](elem) = transfer_back;
        elem--;
    }
}

Let me explain why you have that error. string *transfer_back = at_front those two are pointed to the same reference, that is why when you change transfer_back->operator[](0) = at_front->operator[](i);this change will reflect in at_front string as well.

Upvotes: 1

Scheff&#39;s Cat
Scheff&#39;s Cat

Reputation: 20141

"Write a function that reverses the characters in a text string by using two pointers. The only function parameter shall be a pointer to the string."

This sounds to me like the question addresses C strings but not std::string. Assuming my feeling is right, this could look like:

#include <iostream>
#include <string>

void strrev(char *at_front) {
    char *at_back = at_front;
    if (!*at_back) return; // early out in edge case
    // move at_back to end (last char before 0-terminator)
    while (at_back[1]) ++at_back;
    // reverse by swapping contents of front and back
    while (at_front < at_back) {
        std::swap(*at_front++, *at_back--);
    }
}

int main() {

    char str[] = "ereh txet yna";
    strrev(str);
    std::cout << str << '\n';

    return 0;
}

Output:

any text here

Live Demo on coliru

Note:

I stored the original string in a char str[].

If I had used char *str = "ereh txet yna"; I had assigned an address of a constant string to str. This feels very wrong as I want to modify the contents of str which must not be done on constants.

strrev():

The at_back[1] reads the next char after address in at_back. For a valid C string, this should be always possible as I excluded the empty string (consisting of 0-terminator only) before.

The swapping loop moves at_front as well as at_back. As the pointer is given as value, this has no "destructive" effect outside of strrev().

Concerning std::swap(*at_front++, *at_back--);:

The swapping combines access to pointer contents with pointer increment/decrement, using postfix-increment/-decrement. IMHO, one of the rare cases where the postfix operators are useful somehow.

Alternatively, I could have written:

 std::swap(*at_front, *at_back); ++at_front; --at_back;

Please, note that std::string is a container class. A pointer to the container cannot be used to address its contained raw string directly. For this, std::string provides various access methods like e.g.

  • std::string::operator[]()
  • std::string::at()
  • std::string::data()
  • etc.

Upvotes: 1

Related Questions