C++ Initialise array size after declaration? - c++

This is for an assignment so I'm restricted to what operators, etc. I can use. I can't use vectors.
My program takes an input of a maze and solves it.
Originally I had this array bring used:
Crumb* crumbs[MAX_SIZE];
The maze was originally a fixed-sized and we, therefore, could initialise the crumbs array to it's max possible size. However, now we have to change it so that the maze is dynamically sized and we also have to dynamically assign memory using the 'new' operator (and delete).
We've been told to change the above code to:
Crumb** crumbs;
I'm now not really sure how to fix up my class to use this new declaration. The below code is my full class that handles the array (which is an array of Crumb objects);
Trail::Trail() {
}
Trail::~Trail() {
}
int Trail::size() {
return length;
}
Crumb* Trail::getPtr(int i) {
return crumbs[i];
}
void Trail::addCopy(Crumb* t) {
crumbs[length] = new crumb(*t);
length++;
}
bool Trail::contains(int x, int y) {
bool contains = false;
for(int i = 0; i < length; i++){
if(crumbs[i]->getX() == x && crumbs[i]->getY() == y){
contains = true;
}
}
return contains;
}
bool Trail::containsStale(int x, int y) {
bool contains = false;
for(int i = 0; i < length; i++){
if(crumbs[i]->getX() == x && crumbs[i]->getY() == y){
if(crumbs[i]->isStale() == true){
contains = true;
}
}
}
return contains;
}
I've handled reading the input and the size, so at this point of calling on this class I know the size of the maze, I'm just not sure how to now intialise and use the crumbs array.

C++ Initialise array size after declaration?
You cannot. The size of an array variable must be known when declared.
Simply allocate a dynamic array instead. Simplest solution is to use std::vector, but if you cannot use it, then implement your own vector class.

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

c++ and xcode - calling objects function throws EXC_BAD_ACCESS

This code works fine in VS2010 but now I am trying to port it to my mac with xcode 4.6 and it's giving me some bad access errors at run time. Basically I have a board class which contains a 2d array of tiles, when I create the board I can access the tiles functions but when I later run my draw function it gives me bad access. Here is a sample of my board class.
Board.h
#include "Tile.h"
class Board
{
private:
//This is the GameBoard of a 2D array of Tiles
Tile *** GameBoard;
void CreateBoard(const int size);
void FillValues();
...
public:
Board(int size);
void DrawBoard();
...
}
Board.cpp
Board::Board(const int size)
{
won=false;
lost=false;
BoardSize =size;
GameBoard = new Tile**[size];
CreateBoard(size);
}
void Board::CreateBoard(const int size)
{
...
FillValues()
}
void Board::FillValues()
{
for(int x=1;x<BoardSize+1;x++)
{
for(int y =1;y<BoardSize+1;y++)
{
if (GameBoard[x][y]->Type()=="NumberTile")
{
int neighbors = CountNeighbours(x,y);
GameBoard[x][y]->SetValue(neighbors);
//This works
}
}
}
}
void Board::DrawBoard()
{
for(int i=0;i<=BoardSize+1;i++)
{
for (int j=0;j<=BoardSize+1;j++)
{
if (GameBoard[i][j]->Type() != "BorderTile") {
GameBoard[i][j]->Draw();
//This does not work, i get the error when it tries to use ->Type()
}
}
}
}
...
I call the functions like this
GI = new Board(SCREEN_SIZE);
GI->DrawBoard();
GameBoard = new Tile**[size];
This just creates an array of Tile**. You don't yet have any actual Tiles or even Tile*s and later, when you're trying to access elements of the array with GameBoard[x][y]->, you're hitting undefined behaviour.
As you have it, you would need to do this:
GameBoard = new Tile**[size]; // Allocate an array of Tile**
for (int i = 0; i < size; i++) {
GameBoard[i] = new Tile*[size]; // Allocate an array of Tile*
for (int j = 0; i < size; j++) {
GameBoard[i][j] = new Tile(); // Allocate an array of Tile
}
}
However, this is awful. It's three lots of dynamic allocation that you have to remember to tidy up at the end (and tidy up correctly).
A simpler approach would be to just have an 2D array of tiles:
Tile GameBoard[CONSTEXPR_SIZE][CONSTEXPR_SIZE];
Or better yet, use the std::array container:
std::array<std::array<Tile, CONSTEXPR_SIZE>, CONSTEXPR_SIZE> GameBoard;
Here, the size given has to be a constant expression. If you need it to be dynamically sized, use a std::vector instead.
In the comments below, you say the size of your array is actually BoardSize+1. Still, you are iterating over too many elements in both your outer and inner for loops:
for(int i=0;i<=BoardSize+1;i++)
This should be:
for(int i=0; i<BoardSize+1; i++)
Also in the comments below, you say that Type returns a char*. That means you can't do your string comparison like this:
GameBoard[i][j]->Type() != "BorderTile"
This simply performs pointer comparison, since the left operand is a char* and the right operand is convertible to const char*. It doesn't compare the strings themselves. Instead, you want:
GameBoard[i][j]->Type() != std::string("BorderTile")
This will force std::string comparison to be used.

Delete a record in an array

int i;
int Input;
cin >> Input;
for(i = 0; i < Size ; i ++ )
if (List[i].PersonID == Input) {
}
I am trying to make a function that deletes a record from the array based on the id input provided. I am not sure what to do beyond this here. Will I also need to shift the values in the array after a record is removed?
I can't tell what type your List is.
But you should go for something like this:
List.RemoveAt(i--);
List.DeleteAt(i--);
i-- will decrement i AFTER the function has been called.
You should not need to shift any values in the array if you are using the standard containers.
If you are responsible for the array, then you do need to shift your values.
** EDIT
Here is a link to an introduction to the standard containers. If you are managing your own dynamic array you should consider using these instead.
Here I'm assuming List is a primitive array of ints.
#include<algorithm> // where std::remove() resides
#include<iterator> // where std::distance() resides (not strictly necessary)
struct BadPerson {
BadPerson(int Bad) : Bad_(Bad) { }
bool operator()(const Element& Elem) const {
return Elem.PersonID == Bad_;
}
};
// ...
int *NewEnd = std::remove_if(List, List + ListLength, BadPerson);
// the list now has a new end, because elements were "removed".
// but they weren't really removed; the array still has the same fixed size.
int ListLength = std::distance(List, NewEnd);
I think the best way to remove elements from an array/vector is to use a copy approach with something like:
int write_ptr = 0;
for (int read_ptr=0; read_ptr < n; read_ptr++)
{
if (... keep element array[write_ptr] ? ...)
{
if (read_ptr != write_ptr)
array[write_ptr] = array[read_ptr];
write_ptr++;
}
}
// The new size of the array is write_ptr
This will allow to remove even multiple elements with just one pass.
The standard library includes this approach as std::remove_if, however until C++0X arrives it's annoying to use because of limitations of the language (the code needed to be able to specify the test becomes easily quite ugly).
int i;
int Input;
cin >> Input;
for(i = 0; i < Size ; i ++ )
{
if (List[i].PersonID == Input)
{
for(int j=i;j<size-1;j++)
{
List[j]=List[j+1];
}
}
}

Deallocation of an array of objects?

I'm having some issues deallocating arrays of a class I have. Below is the Class, a simplified implementation and my code I have tried to use to close it.
Characters class
#include <cstdlib>
class Character
{
private:
bool human;
int Xposition; // the character's postion on the board.
int Yposition; // the character's postion on the board.
bool alive;
public:
Character(); //This is my constructor
~Character(); //This is my destructor
bool isHuman(); //return whether type 1 aka Human
bool isZombie(); //return whether type 2 aka Zombie
void setHuman(); //set to type 1 or Human
void setZombie(); //set to type 2 or Zombie
void setPos(int xpos, int ypos); //set the board position
int X();
int Y();
bool isAlive(); //checks to see if a Human is still alive and to be displayed
bool Dead(); //kills the character and sets alive to false
int num_moves_allowed; //number of moves allowed.
};
Allocation code:
Character *characters[11];
int human_count = 0;
for(int i=0; i<12; i++)
{
characters[human_count] = new Character();
human_count++;
}
Termination code:
for(i=11;i<=0;i--)
{
if(characters)
{
characters[i]->~Character();
delete characters[i]; characters[i] = NULL;
}
}
if(characters)
{
//ERROR IS HERE
delete [] characters;
}
I have tried a number of different "delete" commands on the array and I keep getting an "Debug Assertion Failed!" window. It says that the dbgdel.cpp from visual studio vctools is the problem place on Line 52.
It also says "Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Someone please help me I'm sure this is very simple.
I'd suggest you avoid using arrays all together. Use a vector of characters.
Declare your vector as
vector<Character> vCharacters;
then insert objects as
for(int i = 0; i < 100; i++)
vCharacters.push_back(Character());
If you want to store pointers to Character objects then wrap them in a shared_ptr which will take care of deallocating them for you.
vector<shared_ptr<Character>> vCharacters;
for(int i =0; i < 100; i++)
{
shared_ptr<Character> spCharacter(new Character());
vCharacters.push_back(spCharacter);
}
Avoid managing memory yourself when C++ can do it fo ryou
The characters array was allocated on the stack, so you don't have to delete it. However, if you want the array to survive the local scope, create it with something like this:
Character **characters = new Character[11];
then your delete[] line should work fine.
Also note that you don't need to call the destructor of Character explicitly: it is called automatically by delete.
As obelix mentioned, you should use a vector from the Standard Template Library.
However, if you're determined to use a raw array:
const int MAX_CHARACTERS = 11;
Character *characters[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
}
Paolo Capriotti is correct that characters should be declared with new if you want it to last beyond its scope:
const int MAX_CHARACTERS = 11;
Character **characters = new Character*[MAX_CHARACTERS];
for(int characterCount = 0; characterCount < MAX_CHARACTERS; ++characterCount)
{
characters[characterCount] = new Character();
}
...
if (characters != NULL)
{
for(int i = 0; i < MAX_CHARACTERS; ++i)
{
delete characters[i];
}
delete [] characters;
}
A better solution is the standard vector class:
#include <vector>
...
const int MAX_CHARACTERS = 11;
std::vector<Character> characters;
for (int i = 0; i < MAX_CHARACTERS; ++i)
{
characters.push_back(Character());
}
...
characters.clear();
Notice how much easier the cleanup was? (And in this case, it's optional, since when characters is destroyed it will automatically call the destructor of each item it contains.)
Also:
Character *characters[11];
should be
Character *characters[12];
and
for(i=11;i<=0;i--)
should be
for(i=11;i>=0;i--)
i realize this is a simplified use and all, but why bother with heap access at all?
just using
Character characters[11];
could be just as valid, and safe.
std::vector<> is nice, but if the list is always fixed size, and there's no heap involved in member data, why not?

How can I return an array?

Is there any way to return an array from a function? More specifically, I've created this function:
char bin[8];
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin[i]='1';
ascii=2^i-ascii;
}
else
{
bin[i]='0';
}
}
and I need a way to return bin[].
You can't do that but you can:
return a dynamicaly allocated array - best owned by a smart pointer so that the caller does not have to care about deallocating memory for it - you could also return something like an std::vector this way.
populate an array/vector passed to you as an argument by pointer (suggested) or a non const reference.
Your array is a local variable allocated on the stack. You should use new [] to allocate it on the heap. Then you can just say: return bin;. Beware that you will have to explicitly free it with delete [] when you are done with it.
You are really asking the wrong question. If you want to do string processing in C++, use the std::string and/or std::vector classes, not arrays of char. Your code then becomes:
vector <char> func() {
vector <char> bin(8);
for( int i = 7; i >= 0; i-- ) {
int ascii='a';
if ( 2 ^ i - ascii >= 0 ) {
bin[i] = '1';
ascii = 2^i - ascii;
}
else {
bin[i] ='0';
}
}
return bin;
}
I think your best bet is to use a vector. It can function in many ways like an array and has several upsides (length stored with type, automatic memory management).
void Calculate( std::vector<char>& bin) {
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin.push_back('1');
ascii=2^i-ascii;
}
else
{
bin.push_back('0');
}
}
}
If you want to return a copy of the array (might make sense for small arrays) and the array has fixed size, you can enclose it in a struct;
struct ArrayWrapper {
char _bin[8];
};
ArrayWrapper func()
{
ArrayWrapper x;
// Do your stuff here using x._bin instead of plain bin
return x;
}
Or just use a std::vector as has been already suggested.
Similar implemented to #ari's answer, i want to say there is already a boost solution, boost::array solving your problem:
boost::array<char, 8> f() {
boost::array<char, 8> bin;
for(int i = 7; i >= 0; i--) {
int ascii = 'a';
if(2 ^ i-ascii >= 0) {
bin[i] = '1';
ascii = 2 ^ i-ascii;
} else {
bin[i] = '0';
}
}
}
...
boost::array<char, 8> a(f());
[I'm not sure what you want to do with that algorithm though, but note that i think you want to do 1 << i (bit-wise shift) instead of 2 ^ i which is not exponentiation in C++.]
Boost array is a normal array, just wrapped in a struct, so you lose no performance what-so-ever. It will also be available in the next C++ version as std::array, and is very easy to do yourself if you don't need the begin()/size()/data()-sugar it adds (to be a container). Just go with the most basic one:
template<typename T, size_t S>
struct array {
T t[S];
T& operator[](ptrdiff_t i) { return t[i]; }
T const& operator[](ptrdiff_t i) const { return t[i]; }
};
But as usual, use the tools already written by other people, in this case boost::array. It's also got the advantage of being an aggregate (that's why it has no user declared constructor), so it allows initializing with a brace enclosed list:
boost::array<int, 4> a = {{ 1, 2, 3, 4 }};
you need to pass array bin as an argument in your function.
array always pass by address, therefore you dont need to return any value.
it will automatically show you all changes in your main program
void FunctionAbc(char bin[], int size);
void FuncationAbc(bin, size)
{
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin[i]='1';
ascii=2^i-ascii;
}
else
{
bin[i]='0';
}
}
}
You'll want to pass by reference, as follows:
void modifyBin(char (&bin)[8])
{
/* your function goes here and modifies bin */
}
int main()
{
char bin[8];
modifyBin(bin);
/* bin has been updated */
return 0;
}
I think that everyone else answered this one... use a container instead of an array. Here's the std::string version:
std::string foo() {
int ascii = 'a';
std::string result("00000000");
for (int i=7; i>=0; --i) {
if (2^i-ascii >= 0) {
result[i] = '1';
ascii = 2^i-ascii;
}
}
return result;
}
I'm not really sure if 2^i-ascii is want you want or not. This will be parsed as (2 ^ (i - ascii)) which is a little strange.