Go Down

Topic: Trying to adapt a circular buffer/ring buffer using String (Read 111 times) previous topic - next topic

GeorgeFlorian

Hello !

As the title says I am trying to adapt a circular buffer I've found online.

Code: [Select]

#include <iostream>
#include <string>
#include <vector>

struct ring_buffer
{
    ring_buffer( std::size_t cap ) : buffer(cap) {}
    bool empty() const { return sz == 0 ; }
    bool full() const { return sz == buffer.size() ; }

    void push( std::string str )
    {
        if( last >= buffer.size() ) last = 0 ;
        buffer[last] = str ;
        ++last ;
        if( full() ) first = (first+1) %  buffer.size() ;
        else ++sz ;
    }

    std::string& operator[] ( std::size_t pos )
    {
        auto p = ( first + pos ) % buffer.size() ;
        return buffer[p] ;
    }

    std::ostream& print( std::ostream& stm = std::cout ) const
    {
        if( first < last )
            for( std::size_t i = first ; i < last ; ++i ) std::cout << buffer[i] << ' ' ;
        else
        {
            for( std::size_t i = first ; i < buffer.size() ; ++i ) std::cout << buffer[i] << ' ' ;
            for( std::size_t i = 0 ; i < last ; ++i ) std::cout << buffer[i] << ' ' ;
        }
        return stm ;
    }

    private:
        std::vector<std::string> buffer ;
        std::size_t first = 0 ;
        std::size_t last = 0 ;
        std::size_t sz = 0 ;
};

int main()
{
    ring_buffer rb(8) ;

    for( int i = 10 ; i < 30 ; ++i )
    {
        rb.push( std::to_string(i) ) ;
        rb.print() << '\n' ;
    }
}


This is what I found. It seems simple enough, right ? Well, I managed to mess it up:

Code: [Select]

struct ring_buffer
{
    ring_buffer(size_t cap) : buffer(cap) {}

    bool empty() const { return sz == 0 ; }
    bool full() const { return sz == buffer.size() ; }

    void push( String str )
    {
        if(last >= buffer.size()) last = 0 ;
        buffer[last] = str ;
        ++last ;
        if(full())
first = (first+1) %  buffer.size() ;
        else ++sz ;
    }

    // String operator[] ( size_t pos )
    // {
    //     auto p = ( first + pos ) % buffer.size() ;
    //     return buffer[p] ;
    // }

    String print() const
    {
        if( first < last )
            for( size_t i = first ; i < last ; ++i ) return (String)buffer[i] + "<br>";
        else
        {
            for( size_t i = first ; i < buffer.size() ; ++i ) return (String)buffer[i] + "<br>";
            for( size_t i = 0 ; i < last ; ++i ) return (String)buffer[i] + "<br>";
        }
return String();
    }

    private:
        std::vector<String> buffer ;
        size_t first = 0 ;
        size_t last = 0 ;
        size_t sz = 0 ;
};


As you can imagine, I ended up messing with the print() function. Now it only prints one element from the buffer,  instead of them all.
I also don't understand why are there 2 for structures inside the else.

Do you have any clue ? Because I most certainly don't.

Thank you !

PaulS

Quote
I also don't understand why are there 2 for structures inside the else.
There really is no such thing as a circular array in C or C++. There is a linear array. You can pretend that the end is the beginning. To do that, you would print from some position to the end, and then from the beginning to another position. That requires two for loops.

The original code did not return values. Your new code does. Nothing after a return statement is executed, so the behavior you are seeing is what I would expect.
The art of getting good answers lies in asking good questions.

Robin2

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

If their general use is risky my guess is trying to use Strings in a circular buffer will definitely fail.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up