Thread: Help with Strings

  1. #16
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,150
    Quote Originally Posted by Zeus_
    What I would implement is this: All copy assignments will point to the same block of memory until either of the copies are required to be modified. In such case, a new copy will be made elsewhere in memory. Once reference count hits zero, I'd deallocate the memory that was being held by the copies.
    While it does involve reference counting, that technique is more specifically called copy-on-write.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  2. #17
    Registered User
    Join Date
    Aug 2019
    Location
    Inside a Singularity
    Posts
    102
    So, I've been busy studying other subjects preparing for entrance exams and haven't had much time to code lately but I found some time yesterday and added a little more content to my String class. I'm having trouble overloading the >> operator for input. Any help suggesting how I should approach this will be great!

    Here's the main issue part...

    Code:
    std::istream& operator >> (std::istream& stream , String& _String_)
    {
        _String_.m_Size = 0;
        delete [] _String_.m_Text;
    
        char* Input;
        stream >> Input;
    
        _String_ = String((const char*)Input);
    
        return stream;
    }
    [EDIT]
    Also, I'm creating a new string when _String_ = String((const char*)) happens. Should I be doing that or should I write an overload = for const char*? I haven't done that because a statement like A = "Hello World" (where A is a String instance) works correct as it basically is the same as A = String("Hello World").
    [/EDIT]

    Now, obviously I cannot do stream >> Input because Input is just a pointer to a char and has no size bound to it. I can get around this by setting a max size to it (say 256) but I don't want to do that. How would you guys suggest taking care of the input?

    Here's the entire code till now...

    Code:
    class String
    {
    
    private: /* Variables */
    
        size_t m_Size;
        char*  m_Text;
    
    private: /* Method Declarations and/or Definitions */
    
        size_t StringLength (const char* _String_) const;
    
        void StringCopy (const char* _String_);
    
    public: /* Constructors and Destructor */
    
        String ();
    
        String (const char* _String_);
    
        String (const String& _String_);
    
        ~String ();
    
    public: /* Getters and Setters */
    
        const size_t& Size (void) const;
    
        char& At (signed int Position) const;
    
    public: /* Method Declarations and/or Definitions */
    
        friend std::ostream& operator << (std::ostream& stream , const String& _String_);
        friend std::istream& operator >> (std::istream& stream , String& _String_);
    
        String& operator = (const String& _String_);
    
        char& operator [] (signed int Position) const;
    
    };
    
    /* Private: Method Declarations and/or Definitions */
    
    size_t String::StringLength (const char* _String_) const
    {
        size_t Position = 0;
    
        while (_String_[Position] != '\0') Position++;
    
        return Position;
    }
    
    void String::StringCopy (const char* _String_)
    {
        size_t Position = 0;
    
        while (Position < m_Size + 1)
        {
            m_Text[Position] = _String_[Position];
            Position++;
        }
    }
    
    
    /* Public: Constructors and Destructor */
    
    String::String ()
        : m_Size(0) ,
          m_Text(nullptr)
    { }
    
    String::String (const char* _String_)
        : m_Size(StringLength(_String_)) ,
          m_Text(new char [m_Size + 1])
    {
        StringCopy(_String_);
    }
    
    String::String (const String& _String_)
        : m_Size(_String_.Size()) ,
          m_Text(new char [m_Size + 1])
    {
        StringCopy(_String_.m_Text);
    }
    
    String::~String ()
    {
        delete [] m_Text;
    }
    
    /* Public: Getters and Setters */
    
    const size_t& String::Size (void) const
    {
        return m_Size;
    }
    
    char& String::At (signed int Position = 0) const
    {
         /*       
            String: "Hello"
    
            Size: 5
    
            Indexing: 'H' 'E' 'L' 'L' 'O' '\0'
                       0   1   2   3   4   5
                      -5  -4  -3  -2  -1
        */
    
        return operator [] (Position);
    }
    
    /* Public: Method Declarations and/or Definitions */
    
    std::ostream& operator << (std::ostream& stream , const String& _String_)
    {
        return stream << _String_.m_Text;
    }
    
    std::istream& operator >> (std::istream& stream , String& _String_)
    {
        _String_.m_Size = 0;
        delete [] _String_.m_Text;
    
        char* Input;
        stream >> Input;
    
        _String_ = String((const char*)Input);
    
        return stream;
    }
    
    char& String::operator [] (signed int Position) const
    {
         /*        
            String: "Hello"
    
            Size: 5
    
            Indexing: 'H' 'E' 'L' 'L' 'O' '\0'
                       0   1   2   3   4   5
                      -5  -4  -3  -2  -1
        */
    
        if (Position < 0)
            return ((Position > -(int)m_Size) ? m_Text[(int)m_Size + Position] : m_Text[0]);
    
        return ((Position < (int)m_Size) ? m_Text[Position] : m_Text[(int)m_Size - 1]);
    }
    
    String& String::operator = (const String& _String_)
    {
        delete [] m_Text;
    
        m_Size = _String_.m_Size;
    
        m_Text = new char [m_Size + 1];
    
        StringCopy(_String_.m_Text);
    
        return *this;
    }
    Last edited by Zeus_; 2 Weeks Ago at 03:59 AM. Reason: Removed hidden formatting copied from IDE...

  3. #18
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,150
    I suggest keeping track of both size (number of elements in use, whether or not the null character is included is up to you) and capacity (number of elements for which memory has been allocated). This will allow you to more easily grow the string so as to implement operator>> for istream. You will need to parse the input yourself and reallocate as needed in a loop.

    Note that you should overload operator[] for both const and non-const versions: the non-const version should return a non-const reference; the const version should either return a const reference or by value.

    Your copy assignment operator is not exception-safe. You should only delete[] after allocating and copying. The right approach to do this is either the old way of implementing it through the copy constructor, destructor, and swap function, or the new way of doing a copy and move.

    As for naming: identifers that begin with an underscore followed by an uppercase letter are reserved to the implementation for any use, so you should not use such names yourself.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #19
    Registered User
    Join Date
    Aug 2019
    Location
    Inside a Singularity
    Posts
    102
    > I suggest keeping track of both size (number of elements in use, whether or not the null character is included is up to you) and capacity (number of elements for which memory has been allocated). This will allow you to more easily grow the string so as to implement operator>> for istream. You will need to parse the input yourself and reallocate as needed in a loop.

    Thanks, I'll see what I'm able to cook myself when I next sit for writing the class.

    >
    Note that you should overload operator[] for both const and non-const versions: the non-const version should return a non-const reference; the const version should either return a const reference or by value.

    Could you demonstrate in an example why a non-const reference overload should be provided? Everything seems to work fine with the const version (as far as I've tried with simple examples) as putting the const in the end just says that the overload [] will not be modifying the contents of the class member variables.

    >
    Your copy assignment operator is not exception-safe. You should only delete[] after allocating and copying. The right approach to do this is either the old way of implementing it through the copy constructor, destructor, and swap function, or the new way of doing a copy and move.

    That makes sense, the delete[] after allocation and copying. I'll see what I can do. We haven't learnt about Move Constructors so I'll hold that out for now until I learn it myself some other day....

    >
    As for naming: identifers that begin with an underscore followed by an uppercase letter are reserved to the implementation for any use, so you should not use such names yourself.

    Noted. Changed all _String_ to Str for now.

    Thanks for your help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 04-13-2017, 01:29 AM
  2. Replies: 2
    Last Post: 05-16-2012, 06:08 AM
  3. Table mapping Strings to Strings
    By johnmcg in forum C Programming
    Replies: 4
    Last Post: 09-05-2003, 11:04 AM

Tags for this Thread