How do I code a simple integer circular buffer in C/C++? - c++

I see a lot of templates and complicated data structures for implementing a circular buffer.
How do I code a simple integer circular buffer for 5 numbers?
I'm thinking in C is the most straightforward?
Thanks.

Have an array, buffer, of 5 integers. Have an index ind to the next element. When you add, do
buffer[ind] = value;
ind = (ind + 1) % 5;

Take an array, arr, an index idx, and a counter, num.
To insert foo, say arr[idx++] = foo; idx %= buffer_len; num++;.
To read out an item into foo, say foo = arr[(idx-num)%buffer_len]; num--;.
Add boundary checks.

If the size and data type of your buffer are fixed, a simple array is all you need:
int buffer[5];
Add to that a couple pointers:
int* start = &buffer[0];
int* end = &buffer[4]+1;
int* input = start;
int* output = start;

int rI =0;
int wI=0;
#define FIFO_SIZE 3
int checkAvail()
{
int avail=0;
if(wI<rI)
avail= (rI-wI);
else
avail = (FIFO_SIZE-wI+rI);
return avail;
}
int addFIFO(int *a, int val)
{
if(checkAvail()>0)
{
a[wI]=val;
wI++;
if(wI>FIFO_SIZE)
wI=0;
}
else
{
printf("FIFO full");
}
return 0;
}
int remFIFO(int *a)
{
int val;
if((FIFO_SIZE-checkAvail()>0))
{
val =a[rI];
rI++;
if(rI>FIFO_SIZE)
rI=0;
}
else
{
printf("FIFO empty");
}
return 0;
}
int main(array<System::String ^> ^args)
{
int FIFO_ARRAY[FIFO_SIZE]={};
addFIFO(FIFO_ARRAY,1);
addFIFO(FIFO_ARRAY,2);
addFIFO(FIFO_ARRAY,3);
addFIFO(FIFO_ARRAY,4);
remFIFO(FIFO_ARRAY);
remFIFO(FIFO_ARRAY);
remFIFO(FIFO_ARRAY);
remFIFO(FIFO_ARRAY);
remFIFO(FIFO_ARRAY);
}

Related

Arrays with unknown size on Arduino

I'm doing an Arduino project and I need to pass arrays with different sizes as parameter to my function.
The problem is that std::vector is not an option.
How can I do that?
The fallback is to pass a pointer to the first element in the array and the size:
void foo(int* arr, size_t size);
The reason for std::vector not being available on some platforms is that on some platforms dynamic allocations is a bad idea. However, once you are dynamically allocating arrays:
int* x = new int[42];
foo(arr,42); // array decays to pointer
delete[] x;
then you could as well use std::vector.
If std::vector is not available to you, then either search for an alternative (maybe this?) or write your own. The pointer + size approach is fragile and not recommended unless absolutely necessary. The power of std::vector is from the abstract concept to encapsulate the array, its size and capacity. Nobody can prevent you to apply that concept even if you cannot use std::vector.
In case you are talking about statically sized arrays, then thats not quite the use case for std::vector. You do not need dynamic allocation, and you can pass arrays by reference. I won't repeat here what you can find in this answer (std::array) or here (c-arrays).
Something like this should work
template<size_t N>
void DaFunction(std::array<int, N>& daArray)
you can do it without having to deal with memory allocation or pointers just by creating a string variable and a limited size array and then you start shifting
#include <Arduino.h>
class ArrayShifter
{
private:
// String Reservoire Tank
String _text;
// a fixed size array of 5 in my case (depending on the amount of data you expect)
String _viewPortArray[5];
int _size = 0;
// Methode to fill the array
bool shiftArray(int position);
public:
ArrayShifter(/* args */);
// Method that gets the text from Serial
String getSerialText();
// get data from the array
String getArrayData(int index);
// array size getter
int getSize();
//clear the array
void clearArray();
//remove item
void removeArrayItem(int index);
};
ArrayShifter::ArrayShifter(/* args */)
{
}
String ArrayShifter::getSerialText()
{
// lesteing to the serial and returning the value
_text = Serial.readString();
return _text;
}
bool ArrayShifter::shiftArray(int position)
{
/*Assuming that the data is comming separated with ";" for each row and ":" for each value
to optimize the size of array in this way :
name:value;age:value;gender:value;
*/
String text = getSerialText();
int index = 0;
_size = 0;
if (text.length() > 0) // text isn't empty
{
if (position <= 5) // if the data belongs to the first 5 range
{
for (int i = 0; i < 5; i++)
{
// get the index of our separator that we've chosed to be ";"
index = text.indexOf(";");
if (index > 0)
{
// index found
_size++;
// putting the value before ";" in the array
_viewPortArray[i] = text.substring(0, index);
// deleting the value from the tank
text = text.substring(index + 1);
}
}
}
else
{
_size = 0;
// to wich range the desired index belongs
unsigned int dataRange = ((position - position % 5));
int ghostIndex = 0;
// looping throught all ";" to get indexes
for (int i = 0; i < dataRange; i++)
{
ghostIndex = text.indexOf(";");
if (ghostIndex > 0)
{
_size++;
text = text.substring(ghostIndex + 1);
}
}
// grabing just 5 of the data
for (int i = 0; i < 5; i++)
{
if (ghostIndex > 0)
{
_size++;
_viewPortArray[i] = text.substring(0, ghostIndex);
text = text.substring(ghostIndex + 1);
}
// updating ghost index
ghostIndex = text.indexOf(';');
}
}
return true;
}
return false;
}
String ArrayShifter::getArrayData(int index)
{
// turn the roulette
if (shiftArray(index))
{
if (index <= 5)
{
// yes we have this
return _viewPortArray[index];
}
else
{
// but we have to put it in the range of 5
index = index - 5;
return _viewPortArray[index];
}
}
}
int ArrayShifter::getSize()
{
return _size;
}
void ArrayShifter::clearArray()
{
for(int i = 0 ; i <5 ; i ++)
{
_viewPortArray->remove(i);
_size = 0;
}
}
void ArrayShifter::removeArrayItem(int index)
{
_viewPortArray->remove(index);
_size--;
}
main class :
#include <Arduino.h>
#include <ArrayShifter.h>
ArrayShifter array;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial){}
}
void loop() {
if(Serial.available()>0)
{
Serial.println(array.getArrayData(7));
int sizeOption2 = array.getSize();
Serial.println(sizeOption2);
array.removeArrayItem(7);
Serial.println(array.getArrayData(7));
}
}
please check my github repository
https://github.com/Riadam/ViewPort-Array-Shifter-for-Arduino-Uno.git

Searching a string inside a char array using Divide and Conquer

Let's say that I have a struct array and each element has a name. Like:
struct something{
char name[200];
}a[NMAX];
Given a new string (char array), i need to find the correct index for it using divide and conquer. Like:
char choice[200];
cin>>chioce;
int k=myFunction(choice); // will return the index, 0 otherwise
// of course, could be more parameters
if( k )
cout<<k;
I don't know how to create that searching function (I tried, I know how D&C works but i'm still learning! ).
And no, i don't want to use strings !
This is what i tried:
int myFunction(char *choice, int l,int r) // starting with l==0 && r==n-1
{
int m;
if(strcmp(a[m].name,choice)==0)
return m;
else{
m=(l+r)/2;
return myFunction(choice,l,m-1);
return myFunction(choice,m+1,r);
}
}
This is my solution for your above problem. But i have modified a few things in your code.
#include<iostream>
using namespace std;
#define NMAX 10
struct something{
char *name; //replaced with char pointer so that i can save values the way i have done
}a[NMAX];
int myFunction(char *choice, int l,int r) // starting with l==0 && r==NMAX-1
{
if(l>r) //return if l has become greater than r
return -1;
int m=(l+r)/2;
if(strcmp(a[m].name,choice)==0)
return m+1;
else if(l==r) //returned -1 as the value has not matched and further recursion is of no use
return -1;
else{
int left= myFunction(choice,l,m-1);//replaced return
int right= myFunction(choice,m+1,r);//by saving values returned
if(left!=-1) //so that i can check them,
return left; //otherwise returning from here onlywould never allow second satatement to execute
if(right!=-1)
return right;
else
return -1;
}
}
int main(){
a[0].name="abc";
a[1].name="a";
a[2].name="abcd";
a[3].name="abcf";
a[4].name="abcg";
a[5].name="abch";
a[6].name="abcj";
a[7].name="abck";
a[8].name="abcl";
a[9].name="abcr";
char choice[200];
cin>>choice;
int k=myFunction(choice,0,NMAX-1); // will return the index, 0 otherwise
// of course, could be more parameters
if( k !=-1)
cout<<k;
else
cout<<"Not found";
return 0;
}
Hope it will help.

passing pointer to function and using realloc

I want to pass a pointer to a function which will call a second function that will use realloc.
The issue is that realloc is returning NULL.
I don't know if the mistake is in the numbers of * in the function call or something else.
Could you please help me ?
The code:
int main(){
// some code.
clause_t* ptr; //clause_t is a structure i declared.
//Some work including the initial allocation of ptr (which is working).
assignLonely(matSAT, ic.nbClause, ic.nbVar, ptr); //the issue is here.
//Some other work
}
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t* ptr)
{
int i = 0, j = 0;
int cpt = 0;
int indice = -1;
for (i = 0; i < nbClause ; ++i)
{
j = 0;
cpt = 0;
while((j < nbVar) && (cpt < 2))
{
if (matSAT[i][j] != 0)
{
cpt++;
}
else
{
indice = j;
}
if (cpt < 2)
{
deleteClause(indice, &ptr);
}
j++;
}
}
}
void deleteClause(int indiceClause, clause_t** ptr)
{
int i = indiceClause;
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
int tailleElt = sizeof((*ptr)[0]);
while(i+1 < nbElt)
{
(*ptr)[i] = (*ptr)[i+1];
i++;
}
*ptr = (clause_t*)realloc(*ptr, (nbElt-1)*tailleElt);
if (*ptr == NULL)
{
fprintf(stderr, "Erreur reallocation\n");
exit(EXIT_FAILURE);
}
}
You have to declarae function assignLonely similarly to function deleteClause like
void assignLonely(int** matSAT, int nbClause, int nbVar, clause_t** ptr);
if you want that changes of ptr in the function would be stored in the original object in main.
Also take into account that this statement
int nbElt = sizeof((*ptr))/sizeof((*ptr)[0]);
is wrong.
Expression sizeof((*ptr)) will return the size of the pointer. Pointers do not keep information about how many elements in arrays they point to.
So expression
(nbElt-1)
can be equal to zero or even be negative.

Creating the biggest array of chars which can be allocated

I have tried to check programmatically how big an array I can allocate but my code does not seem to check it. How to make it faster? In the end I would like to get an exception.
#include "stdafx.h"
#include "iostream"
using namespace std;
int ASCENDING = 1, DESCENDING = 2;
int tworzTablice(int rozmiar, char* t){
try{
t = new char[rozmiar];
delete []t;
}catch (std::bad_alloc& e){
tworzTablice(rozmiar - 1,t);
return -1;
}
return rozmiar;
}
int f(long p, long skok){
char* t;
try{
while(true){
t = new char[p];
delete []t;
p = p + skok;
}
}
catch (std::bad_alloc& ba){
p = tworzTablice(p-1, t);
cout<<"blad";
}
return p;
}
int main(){
cout<<f(0, 100000000)<<endl;;
cout<<"koniec"<<endl;
system("pause");
return 0;
}
As I noted, there is a way to query the OS in order to determine the maximal size of heap-allocated memory, but I can't for the heck of it remember its name.
However, you can easily find out yourself. However, you should use malloc/free instead of new/delete in order to avoid the unnecessary initialisation of all cells;
#include <cstdlib>
#include <cstdio>
size_t maxMem() {
static size_t size = 0;
if (!size) {
size_t m = 0;
for (void* p = 0; (p = malloc(1<<m)); m++)
free(p);
while (m) {
size_t const testSize = size + (1<<(--m));
if (void* const p = malloc(testSize)) {
size = testSize;
free(p);
}
}
}
return size;
}
int main() {
// forgive me for using printf, but I couldn't remember how to hex-format in std::cout
printf("%u (hex %X)\n",int(maxMem()),int(maxMem()));
}
On my 64 bit machine I get
2147483647 (hex 7FFFFFFF)
while on another 32 system I get
2140700660 (hex 7F987FF4)
You can then go ahead and new an array of that size if you really have to. Note however, that this is the largest consecutive chunk you can request. The total memory your process might allocate is larger and depends on the installed RAM and the reserved swap space.
Allocating all available memory is probably a bad idea, but if you really want to:
vector<char*> ptrs;
int avail;
try {
while (true)
ptrs.push_back(new char[1000]);
}
catch (bad_alloc& b)
{
avail = ptrs.size() * 1000;
for (int i = 0; i < ptrs.size(); i++)
delete[] ptrs[i];
}

dynamic memory allocation with arrays in c++

I am trying to insert an int into an array that is in a class object, and I cannot figure out what I am doing wrong. The current state of my code never inserts the int into the array.
Basically what I am trying to do is when i call insert(int) it will check to to see if there is any room left in the array, and if there is it will add it, otherwise it would reallocate with 8 more spaces in the array.
here is some relevant class info
private:
unsigned Cap; // Current capacity of the set
unsigned Num; // Current count of items in the set
int * Pool; // Pointer to array holding the items
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
unsigned capacity() const { return Cap; }
// Initialize the set to empty
//
Set()
{
Cap = Num = 0;
Pool = NULL;
}
here is the code i am working on
bool Set::insert(int X)
{
bool Flag = false;
if (Num == Cap)
{
//reallocate
const unsigned Inc = 8;
int * Temp = new int[Cap+Inc];
for (unsigned J=0;J<Num;J++)
{
Temp[J] = Pool[J];
}
delete [] Pool;
Pool = Temp;
Cap = Cap+Inc;
}
if(Num < Cap)
{
Pool[Num+1] = X;
Flag = true;
}
return Flag;
}
Your insert function never updates Num. Try Pool[Num++] = X; or something like that.
You probably want to increment the number of element but only after copying the new element in: the first element should have index 0. Basically, your insert() function should look something like this:
bool Set::insert(int X)
{
if (Num == Cap)
{
const unsigned Inc(std::max(8, 2 * Cap));
std::unique_ptr<int[]> Temp(new int[Cap+Inc]);
std::copy(Pool.get(), Pool.get() + Num, Temp.get());
Pool.swap(Temp);
Cap += Inc;
}
Pool[Num] = X;
++Num;
return true;
}
Of course, this assumes that Pool is reasonably declared as std::unique_ptr<int[]> (or something with similar functionality which is easy to write if necessary). The reason to use std::unique_ptr<int[]> rather than raw pointers is that they automatically clean up resources when they are destroyed. Copying a sequence of ints won't throw an exception but if int get's replaced by a std::string or a template parameters there is potential to throw exceptions.