L-value substr method in C ++

I want to create a method substr

in C ++ into a string class that I have made.

The string class is of course based on the C style string and I care about memory management.

I want to write a function substr(start, length)

that can run on a regular basis:

CustomString mystring = "Hello";

cout << mystring.substr(0,2); // will print "He"

      

And also as follows:

mystring.substr(1,3) = "DD"; // mystring will be "HDDo"

      

Note that even if I get a long substring of 3 characters long, I only put 2 characters in the job and the output string will be HDDo, yet.

Any idea how to do this?

Thank!

+2


source to share


3 answers


To support this, you will probably have to write substr()

to return a proxy that keeps track of which part of the original string it refers to. The proxy object will be overloaded operator=

, and the reference to the substring with the new assignment will be replaced in it.

Edit in response to comments: the idea behind a proxy is that it is quite similar to the class for which it is a proxy that the proxy returns is still a closed operation, that is, from the user's point of view, everything. which seems to be the original object type, but it has capabilities that would be impossible (or much more difficult to implement) without a proxy. In this case, the proxy class will be closed to the string class, so the user can never create an instance of the proxy class except temporarily. This temporary can be used to change its parent row if you assign it. Using a proxy in any other way gives the string.

As for what you are buying, you are trying to do all this inside the original line: each proxy is a temporary object - the compiler can / will / keeps track of how to create temporary resources as needed, the end of the full expression, etc. The compiler also keeps track of which substring refers to a particular assignment, automatically converts it to a string when we try to use its value, and so on. In simple terms, the compiler handles almost all the hard work.

Here's some working code. The surrounding string class is pretty minimal (for example, it has no search capability). I expect to add a fair amount to a useful version of the string class. The proxy class, however, is complete - I wouldn't expect to see it change much (if at all) in the fully functional version of the string class.



#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

class string { 
    std::vector<char> data;
public:
    string(char const *init) { 
        data.clear();
        data.assign(init, init+strlen(init));
    }

    string(string const &s, size_t pos, size_t len) {
        data.assign(s.data.begin()+pos, s.data.begin()+pos+len);
    }

    friend class proxy;

    class proxy {
        string &parent;
        size_t pos;
        size_t length;
    public:
        proxy(string &s, size_t start, size_t len) : parent(s), pos(start), length(len) {}

        operator string() { return string(parent, pos, length); }

        proxy &operator=(string const &val) { 
            parent.data.erase(parent.data.begin()+pos, parent.data.begin()+pos+length);
            parent.data.insert(parent.data.begin()+pos, val.data.begin(), val.data.end());
            return *this;
        }
    };

    proxy substr(size_t start, size_t len) { 
        return proxy(*this, start, len);
    }

    friend std::ostream &operator<<(std::ostream &os, string const &s) { 
        std::copy(s.data.begin(), s.data.end(), std::ostream_iterator<char>(os));
        return os;
    }
};

#ifdef TEST

int main() { 
    string x("Hello");

    std::cout << x << std::endl;

    std::cout << x.substr(2, 3) << std::endl;

    x.substr(2, 3) = "DD";

    std::cout << x << std::endl;

    return 0;
}

#endif

      

Edit 2: It depends on the substrings of the substrings. One situation that is not currently considered is if you want to assign a substring to a substring and affect the original string. If you want something like this x=y.substr(1,4).substr(1,2);

, it will work as is. The first proxy will be converted to a string and the second substr will be called on that string.

If you want x.substr(1,4).substr(1,2) = "whatever"

:; it is currently not working. I'm not sure if it accomplishes much, but assuming it does, the addition to supporting it is pretty minimal - you'll add a subpage member to the proxy:

proxy substr(size_t start, size_t len) { 
    return proxy(parent, pos+start, len);
}

      

+6


source


Presumably you want to substr

return a string and not some other proxy class. Therefore, you need to make your string class able to contain a pointer to its own copy of the string data, as well as a pointer to another string object from which it was created (as a return value substr

), as well as information about which part of the string it was created from.

This can get quite tricky if you call substr

on a string returned from another call to substr

.



The complexity is probably not worth the attractiveness of the interface.

0


source


The first requirement is simple; look for a standard implementation of the operator.

Wrong, c_string& substr(int, int)

The second part, not much, I don't think. It looks like it will be similar. However, I will think about it and return to you on the weekend.

0


source







All Articles