0

I'm trying to write a for loop that starts from where my currentIndex variable leaves off, and traverses through the circular buffer.

I am using the circular buffer to store load data. Data is periodically stored.

Currently, this is how I populate data:

//currentIndex starts at 0
buffer[currentIndex] = data;
currentIndex = (currentIndex + 1) % size;

Ex: size is 6. 8 entries (1 2 10 11 12 13 8 9) are stored, so 2 entries at index 0 and 1 get overwritten.

Index : 0 1 2 3 4 5

Buffer: 8 9 10 11 12 13

After 9 is populated, currentIndex becomes 2. I want to traverse indices in this order: 9, 8, 13, 12, 11, 10. I want to start from the last index (most recent data) populated.

I am having trouble coming up with the logic to do this in a for loop.

skmiley1
  • 249
  • 2
  • 11
  • Why would you want to go *backwards* from the current index? That would overwrite 8 and 9, which are the most recent ones – information_interchange Aug 23 '17 at 02:12
  • I want to traverse the buffer, not overwrite 8 and 9. I just want to start from most recent data (9), and read each entry in this order: 9, 8, 13, 12, 11, 10. – skmiley1 Aug 23 '17 at 02:13
  • Then shouldn't the indices be traversed in this order? 10 11 12 13 8 9? – information_interchange Aug 23 '17 at 02:14
  • In that order, we are not starting from the most recent data which is 9. – skmiley1 Aug 23 '17 at 02:16
  • is this what you're looking for? https://stackoverflow.com/questions/3437477/how-do-you-iterate-backward-over-circular-buffer-without-a-conditional – information_interchange Aug 23 '17 at 02:22
  • I looked at that, but I'm having some trouble figuring out what should be my ending condition of the loop. I want to terminate once I reach 9 again (in a loop) – skmiley1 Aug 23 '17 at 02:24
  • Re "*I want to start from the last index (most recent data) populated.*", There's no reason to use a circular buffer for a stack. – ikegami Aug 23 '17 at 03:42
  • If any of the answers below has helped to solve your problem, you should [accept](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) by clicking on the checkmark next to that answer. – ad absurdum Aug 24 '17 at 07:35

4 Answers4

0

If you want to begin printing from the element previous to the last indexed value, you can use a do loop that decrements a non-zero array index, or assigns the last available index to the array index:

#include <stdio.h>

int main(void)
 {
     size_t size = 6;
     int buffer[size];
     int input[] = { 1, 2, 10, 11, 12, 13, 8, 9 };

     /* Populate array */
     size_t currentIndex = 0;
     size_t lastIndex = 0;
     for (size_t i = 0; i < 8; i++) {
         buffer[currentIndex] = input[i];
         currentIndex = (currentIndex + 1) % size;
         lastIndex = currentIndex;
     }

     /* Print array contents */
     for (size_t i = 0; i < size; i++) {
         printf("%5d", buffer[i]);
     }
     putchar('\n');

     /* Print in reverse, starting before the last index */
     size_t i = lastIndex;
     do {
         i ? --i : (i = size - 1);
         printf("%5d", buffer[i]);
     } while (i != lastIndex);
     putchar('\n');

     return 0;
 }     

Program output:

8    9   10   11   12   13
9    8   13   12   11   10
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
0

There's on reason to use a circular buffer for a stack. One uses a circular buffer to implement a lock-less queue with one writer and one reader.

int head = 0;
int tail = 0;
int buffer[BUF_SIZE];  // Holds one less than BUF_SIZE elements.

// Returns true if successful, false if empty.
int circular_buffer_read(int* val_ptr) {
   if (head == tail)
      return 0;

   *val_ptr = buffer[tail];
   tail = (tail + 1) % BUF_SIZE;
   return 1;
}

// Returns true if successful, false if full.
int circular_buffer_write(int val) {
   buffer[head] = val;
   int new_head = (head + 1) % BUF_SIZE;
   if (new_head == tail)
      return 0;

   head = new_head;
   return 1;
}

If you have a single reader and a single writer, the above is thread-safe if the comparisons (head == tail and new_head == tail) are thread-safe.

void producer() {
   int i = 0;
   while (1) {
      if (!circular_buffer_write(i)) {
         sleep(1);
         continue;
      }

      ++i;
   }
}

void consumer() {
   while (1) {
      int i;
      if (!circular_buffer_read(&i)) {
         sleep(1);
         continue;
      }

      printf("Got %d\n", i);
   }
}
ikegami
  • 367,544
  • 15
  • 269
  • 518
0

It seems like you need a LIFO kind of structure instead of the circular buffer (queue) which is typically used for FIFO.

A stack might work better for your use case.

As a producer puts elements on the top of the stack, the consumer takes out elements from the very same top, processing newest elements first.

0
for(int i = size; i > 0; --i)
{
    printf("%d ", buffer[(currentIndex + i) % size]);
}

Index calculations:

(currentIndex + size    ) % size ~ currentIndex
(currentIndex + size - 1) % size ~ currentIndex - 1
...
Aconcagua
  • 24,880
  • 4
  • 34
  • 59