Initialize large two dimensional array in C++ - c++

I want to have static and constant two dimensional array inside a class. The array is relatively large, but I only want to initialize a few elements and others may be whatever compiler initializes them to.
For example, if a class is defined like:
class A {
public:
static int const test[10][10];
};
int const A::test[10][10] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
and I am interested only to initialize the elements marked with '7', how do I do this on the same elements, but with array of larger size, like array[1024][1024]?

Any part of an array which is initialized, that is beyond the initialization, is initialized to 0. Hence:
int const A::test[10][10]; // uninitialized
int const A::test[10][10] = { {0} }; // all elements initialized to 0.
int const A::test[10][10] = {1,2}; // test[0][0] ==1, test[0][1]==2, rest==0
That means all you have to initialize is up to the last non-zero:
int const A::test[10][10] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0},
{0, 0, 0, 7, 7, 7, 7, 0, 0, 0}
};
It is not the best solution, but will save some work.

There is no way to assign an int to const array after it's been initialized. So you will have to script it up:
And include your file this way:
class A {
public:
static const int test[10][10];
};
const int A::test[10][10] = {
#include "data.inc" // points to the file generated by script.
};

Coincidentally, a couple of hours after reading your question, I bumped into a possible solution while looking for something else in the book "C - A Reference Manual" 5th ed., Harbison/Steele (this is a fantastic C reference, by the way).
According to the book,
C99 allows you to name the components of an aggregate (structs, union or array) to be initialized within an initializer list.
... and it gives an example:
int a1[5] = { [2]=100, [1]=3 }; /* eqv. to {0, 3, 100, 0, 0} */
So, depending on the compliance of your compiler and on the size of the non-zero elements in your array, you may be able to use this syntax to init your matrix efficiently. That said, the book doesn't give an example for 2D arrays. Unfortunately, I couldn't test this idea since MSVC++ 2005 doesn't seem to support C99.

When I do this, I use a method to read in data. Generically, it looks like:
extern void ReadElements(string sFile, Matrix a)
{
int x;
int y;
double value;
ifstream myInFile;
myInFile.open(sFile, ifstream::in);
while(!myInFile.eof())
{
myInFile >> x >> y >> value;
a[x][y] = value;
}
myInFile.close();
return;
}

You could access the array only through accessor functions/macros and arrange the internal storage so, that the initialzed part goes first.

A solution would be to hide non-const array somewhere, load it from file or resource, and then use const reference to access it. I.e.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef int Array[1024][1024];
namespace DontTouch{
Array arr;
void initArray(){
for (int i = 0; i < 1024; i++)
for (int j = 0; j < 1024; j++)
arr[i][j] = rand() & 0xff;
}
}
const Array &arr = DontTouch::arr;
int main(int argc, char** argv){
DontTouch::initArray();
//arr[4][4] = 0;//compiler error
for (int i = 0; i < 1024; i++){
for (int j = 0; j < 1024; j++)
printf(" 0x%02x", arr[i][j]);
printf("\n");
}
return 0;
}
It will be (IMO) more readable than script-generated huge array.
You can do same thing with class that acts like 2D array (easy enough to write). Again - have non-const object somewhere, and use const reference to access the data. It should be easy to make non-const array completely invisibile outside of just one cpp.
Another way to do that is to generate array using script. If you think that big arrays are ugly, put entire thing into *.h file (make sure it is included in only one *.cpp file), so it won't scare people away. Compiler doesn't care what you write in your code as long as it is syntactically correct.
I don't think there are any other options.

It only takes four lines by using std::fill_n
using std::fill_n;
using std::begin;
fill_n(begin(test[3])+3, 4, 7);
fill_n(begin(test[4])+3, 4, 7);
fill_n(begin(test[5])+3, 4, 7);
fill_n(begin(test[6])+3, 4, 7);

install R software, it's free !
then call function defined below with
writetable(data,"test","myfile.h")
if data is your matrix then you're done
writetable<-function(data,varname="test",file="myFile.hpp"){
cat('const static double CONST_array_',varname," [][] = { \n \t\t\t\t {",file=file,append=TRUE,sep='')
for (j in 1:(dim(data)[2]-1)){
for (i in 1:(dim(data)[1]-1) ){
cat(data[i,j],',',file=file,append=TRUE)
}
cat(data[dim(data)[1],j],'},\n \t\t\t\t\t{',file=file,append=TRUE)
}
for (i in 1:(dim(data)[1]-1) ){
cat(data[i,dim(data)[2]],',',file=file,append=TRUE)
}
cat(data[dim(data)[1],dim(data)[2]],'}\n }; \n',file=file,append=TRUE)
}

Related

C++: error, multiple definition of variable [duplicate]

This question already has answers here:
include header file error: multiple definition
(2 answers)
Closed 1 year ago.
Getting error message saying: SudokuGame\sudoku_solver.h:6: error: multiple definition of `grid'
Can anyone point out why? I guess i'm including sudoku_solver.h in the wrong way
See parts of my code files below.
sudoku_solver.cpp:
#include <iostream>
#include "sudoku_solver.h"
using namespace std;
bool isPresentInCol(int col, int num) {
for (int row = 0; row < N; row++)
if (grid[row][col] == num)
return true;
return false;
}
sudoku_solver.h:
#ifndef SUDOKU_SOLVER_H
#define SUDOKU_SOLVER_H
#define N 9
int grid[N][N] = {
{3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0}
};
/*
*Check if number is present in given coloum
*/
bool isPresentInCol(int col, int num);
/*
*Check if number is present in given row
*/
bool isPresentInRow(int row, int num);
#endif // SUDOKU_SOLVER_H
main.cpp:
#include "sudoku_solver.h"
#include <iostream>
using namespace std;
int main()
{
if (solveSudoku())
printSolvedSudoku();
else
cout << "No solution exists";
return 0;
}
sudoku_solver.h is included in both sudoku_solver.cpp and main.cpp. Hence two definitions of the global variable grid.

Passing arguments to Base constructor using Derived class member variables in C/C++

I am building a class to control some hardware which has a few different versions. Because of this variety of versions, certain parameters need to be hardcoded, and they are different for each version. However, beyond those hardcoded parameters, all versions provide the same funcionality.
The way I thought I would architect this was to use a base class which contains all the methods needed, and derived classes (DerivedV1, DerivedV2, etc) where I would just define these hardcoded parameters as member variables and then pass them as constructions parameters to the base class.
Here is a minimal example of the code:
(this is deployed on a microcontroller hence the use of arrays instead of vectors, also disregard the use of std::cout, it was only included here to illustrate the problem)
#include <iostream>
using namespace std;
void print_array(uint16_t *array, uint16_t size){
cout<<"[ ";
for(int i=0; i < size-1; i++){
cout<<array[i]<<", ";
}
cout<<array[size-1]<<" ]"<<endl;
}
class BaseClass{
protected:
std::string id_;
uint16_t num_cats_;
uint16_t num_dogs_;
uint16_t *cat_mapping_;
uint16_t *dog_mapping_;
uint16_t combinations_;
public:
BaseClass(string id, uint16_t num_cats, uint16_t num_dogs,
uint16_t *cat_map, uint16_t *dog_map){
cout<<"Base Constructor"<<endl;
id_ = id;
num_cats_ = num_cats;
num_dogs_ = num_dogs;
cat_mapping_ = cat_map;
dog_mapping_ = dog_map;
combinations_ = num_cats_*num_dogs_;
cout<<"Num cats: "<<num_cats_<<endl;
cout<<"Num dogs: "<<num_cats_<<endl;
print_array(cat_mapping_, num_cats_);
print_array(dog_mapping_, num_dogs_);
cout<<"Combinations: "<<combinations_<<endl;
}
virtual ~BaseClass(){};
};
class DerivedClassV1 : public BaseClass
{
private:
uint16_t num_cats_ = 10;
uint16_t cat_map_[10] = {31, 15, 20, 32, 13, 25, 19, 16, 28, 23};
uint16_t num_dogs_ = 8;
uint16_t dog_map_[8] = {5, 25, 23, 4, 13, 15, 14, 26};
public:
DerivedClassV1(string id) : BaseClass(id, num_cats_, num_dogs_, cat_map_, dog_map_){
cout<<"Derived Constructor";
}
};
int main()
{
DerivedClassV1 dummy("v1");
return 0;
}
Execution of this code results in garbage being output:
Base Constructor
Num cats: 64
Num dogs: 64
[ 0, 0, 2, 0, 0, 0, 4781, 64, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 4704,
64, 0, 0, 3040, 64, 0, 0, 42640, 13254, 32766, 0, 0, 0, 0, 0, 0, 0, 0,
0, 44869, 10268, 32576, 0, 0, 0, 0 , 0, 42648, 13254, 32766, 0, 0, 0,
1, 0, 3456, 64, 0, 0, 0, 0, 0, 0, 13708, 48499 ]
[ 0, 0, 0, 0, 0, 0, 0, 4704, 64, 0, 0, 3040, 64, 0, 0, 42640, 13254,
32766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44869, 10268, 32576, 0, 0, 0, 0, 0,
42648, 13254, 32766, 0, 0, 0, 1, 0 , 3456, 64, 0, 0, 0, 0, 0, 0,
13708, 48499, 5513, 17381, 3040, 64, 0, 0, 42640, 13254, 32766, 0, 0,
0, 0, 0, 0, 0, 0, 0, 13708, 63219, 29188, 48153, 13708, 57481, 17840,
484 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4704, 64, 0, 0, 42648,
13254, 32766, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3040, 64, 0, 0,
42640, 13254, 32766, 0, 0, 0, 0, 0, 3081 ]
Combinations: 7936
Derived Constructor
What am I doing wrong here? Why are the arguments sent to the BaseClass not the correct ones defined in the derived class?
Should I be doing this differently? Any help is appreciated
The behaviour of your program is undefined.
Conceptually, DerivedClassV1::cat_map_ &c. do not exist at the point the base class is constructed.
A pointer to such an array (e.g. cat_map in the base class constructor) is effectively dangling.
Can't you use polymorphism to yield the appropriate arrays?
You can pass the DerivedClassV1 values to the BaseClass by using a template. But the values have to be static constants so they're initialized before the base class.
#include <iostream>
using namespace std;
void print_array(const uint16_t *array, uint16_t size){
cout<<"[ ";
for(int i=0; i < size-1; i++){
cout<<array[i]<<", ";
}
cout<<array[size-1]<<" ]"<<endl;
}
template <class T>
class BaseClass {
protected:
std::string id_;
const uint16_t *cat_mapping_ = T::cat_map_;
const uint16_t *dog_mapping_ = T::dog_map_;
uint16_t combinations_;
public:
BaseClass(string id){
cout<<"Base Constructor"<<endl;
id_ = id;
combinations_ = T::num_cats_*T::num_dogs_;
cout<<"Num cats: "<<T::num_cats_<<endl;
cout<<"Num dogs: "<<T::num_dogs_<<endl;
print_array(cat_mapping_, T::num_cats_);
print_array(dog_mapping_, T::num_dogs_);
cout<<"Combinations: "<<combinations_<<endl;
}
virtual ~BaseClass(){};
};
class DerivedClassV1 : public BaseClass<DerivedClassV1>
{
public:
static const uint16_t num_cats_ = 10;
static constexpr uint16_t cat_map_[10] = {31, 15, 20, 32, 13, 25, 19, 16, 28, 23};
static const uint16_t num_dogs_ = 8;
static constexpr uint16_t dog_map_[8] = {5, 25, 23, 4, 13, 15, 14, 26};
public:
DerivedClassV1(string id) : BaseClass(id){
cout<<"Derived Constructor";
}
};
constexpr uint16_t DerivedClassV1::cat_map_[10];
constexpr uint16_t DerivedClassV1::dog_map_[8];

Is there a way to overload a constructor with a 2D array (int)?

When I utilize the default constructor, I expect it to call the constructor that accepts an argument; however, this does not occur correctly. When debugging, as far as I can tell it is assigning the values and then the instance simply isn't maintained. I'm not sure if I need to create a helper method instead to pass the object, array, assign out values, and then pass back the object?
My goal is to have a default constructor that passes a hard-coded set of values and then a constructor that accepts the same type of array passed as values.
I've tried passing the array as an argument for the constructors, and while it seems to work for the derived class, it does not work for the base class. I ended up moving the functionality of the overloaded constructor to the default constructor and that works correctly.
This is the base class:
// Puzzle.h
class Puzzle
{
public:
Puzzle();
Puzzle(int grid[gridLength][gridLength]);
~Puzzle();
void Print_Puzzle(); // Displays puzzle in console
protected:
int grid[gridLength][gridLength]; // Our board
private:
};
This is the definition:
Puzzle::Puzzle()
{
int grid[gridLength][gridLength] = // Taken from https://www.puzzles.ca/sudoku_puzzles/sudoku_easy_505.html
{
{ 0, 7, 0, 0, 0, 2, 0, 0, 0 },
{ 0, 9, 0, 3, 7, 0, 0, 0, 0 },
{ 0, 0, 5, 0, 8, 0, 0, 0, 1 },
{ 0, 0, 4, 7, 0, 0, 0, 0, 9 },
{ 0, 0, 0, 0, 9, 6, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 8, 6, 5, 4 },
{ 0, 2, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 4, 3 },
{ 4, 0, 7, 9, 5, 0, 2, 6, 0 }
};
for (int x = 0; x < gridLength; x++)
{
for (int y = 0; y < gridLength; y++)
Puzzle::grid[x][y] = grid[x][y];
}
// Puzzle::Puzzle(grid) // Doesn't work. Not sure how to properly pass the array values.
}
Puzzle::Puzzle(int grid[gridLength][gridLength])
{
for (int row = 0; row < gridLength; row++)
{
for (int col = 0; col < gridLength; col++)
this->grid[row][col] = grid[row][col];
}
}
I expect the default constructor to pass the grid variable and the receiving constructor to assign those values to the instance's member property.
A more convenient way and no less efficient is to use std::array which can be copied, so that you do not have to copy it element-wise:
#include <array>
constexpr int gridLength = 9;
using Grid = std::array<std::array<int, gridLength>, gridLength>;
Grid const grid = {{ // Taken from https://www.puzzles.ca/sudoku_puzzles/sudoku_easy_505.html
{ 0, 7, 0, 0, 0, 2, 0, 0, 0 },
{ 0, 9, 0, 3, 7, 0, 0, 0, 0 },
{ 0, 0, 5, 0, 8, 0, 0, 0, 1 },
{ 0, 0, 4, 7, 0, 0, 0, 0, 9 },
{ 0, 0, 0, 0, 9, 6, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 8, 6, 5, 4 },
{ 0, 2, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 4, 3 },
{ 4, 0, 7, 9, 5, 0, 2, 6, 0 }
}};
class Puzzle {
Grid grid_;
public:
Puzzle(Grid const& grid)
: grid_(grid) // Copy grid into grid_.
{}
};
int main() {
Puzzle p(grid);
}
Alternatively:
class Puzzle {
Grid grid_;
static Grid make_grid() {
Grid grid;
// Your code to fill the grid.
return grid;
}
public:
Puzzle()
: Puzzle(make_grid())
{}
Puzzle(Grid const& grid)
: grid_(grid) // Copy the grid.
{}
};
In my opinion, you are committing a design error.
Never use C arrays in C++, use std::vector or std::array instead.
Try this.
class Sudoku
{
public:
Sudoku(const std::vector<std::vector<int>> initData = { {/* Write your default values here */} })
{
data = initData;
}
private:
std::vector<std::vector<int>> data;
};
if you want to use C-like arrays you will need to understand the only way to pass arrays is via pointers, and is a messy solution.
template <uint32_t width, uint32_t height>
class Sudoku
{
public:
Sudoku(int** initData, int maxX, int maxY)
{
for (int i = 0; i < maxX; i++) {
for (int j = 0; j < maxY; j++) {
data[i][j] = initData[i][j];
}
}
}
private:
std::array<width, std::array<height, int>> data;
};

How to write a "List<int[,]>" in C++? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I'm attempting to make a C++ equivalent code of the following C# code, mainly because I'm following a tutorial that is in C#, and I'm more comfortable using C++. My thought process is maybe making an outer array, then allocating a new array into each index that represents a matrix size. Would this be okay or is there a better way to go about implementing this in C++?
// current C# code
List<int[,]> pieces;
pieces = new List<int[,]>();
/* I Piece */
pieces.Add(new int[4, 4] {
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0}
});
/* J Piece */
pieces.Add(new int[3, 3] {
{0, 0, 1},
{1, 1, 1},
{0, 0, 0}
});
/* O Piece */
pieces.Add(new int[2, 2] {
{1, 1},
{1, 1}
});
/* S Piece */
pieces.Add(new int[3, 3] {
{0, 1, 1},
{1, 1, 0},
{0, 0, 0}
});
/* T Piece */
pieces.Add(new int[3, 3] {
{0, 1, 0},
{1, 1, 1},
{0, 0, 0}
});
/* Z Piece */
pieces.Add(new int[3, 3] {
{1, 1, 0},
{0, 1, 1},
{0, 0, 0}
});
My initial code is making a matrix in an array. Since I'm not looking to change the number of "pieces" in the game itself, then a fixed array should be fine. So this is what I wrote as an equivalent. Obviously, it didn't work, saying it cannot be assigned to an entity of int:
int pieces [7];
//I piece
pieces [0] = new int [4][4];
pieces [0] = {
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
/* And so on for each piece */
IMO a vector of vector of vectors seems a little cumbersome for such a simple construct.
I'd probably assume that everything is 4x4, the largest size, and just embed the pieces in that, in which case you'd have
#include <vector>
struct Piece { int v[4][4]; };
std::vector<Piece> pieces {
// I piece
{ {
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{0,0,0,0}
} },
// J piece
{ {
{0, 0, 1}, // This is OK since extra element will be 0 initialised by default.
{1, 1, 1},
{0, 0, 0}
// Dont need a row here either as it will be 0 initialised.
} }
//Others omitted for now..
};
Or for non C++11 compliant compilers:
#include <vector>
struct Piece { int v[4][4]; };
Piece raw_pieces[] = {
{ {
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{0,0,0,0}
} },
{ {
{0, 0, 1}, // This is OK since extra element will be 0 initialised by default.
{1, 1, 1},
{0, 0, 0}
// Dont need a row here either as it will be 0 initialised.
} }
};
std::vector<Piece> pieces(raw_pieces, raw_pieces + sizeof(raw_pieces)/sizeof(Piece));
Try std::list<std::vector<std::vector<int> > > or, as suggested try std::vector<std::vector<std::vector<int> > >
Here's a full example with vector<vector<vector<int>>>, but keep in mind, you will have to compile like this: g++ -std=c++0x t.cpp
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<vector<vector<int>>> A = {
{
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 1},
{1, 1, 1},
{0, 0, 0}
},
{
{1, 1},
{1, 1}
},
{
{0, 1, 1},
{1, 1, 0},
{0, 0, 0}
},
{
{0, 1, 0},
{1, 1, 1},
{0, 0, 0}
},
{
{1, 1, 0},
{0, 1, 1},
{0, 0, 0}
}
};
for(int i=0;i<A.size();i++) {
for(int j=0;j<A[i].size();j++) {
for(int k=0;k<A[i][j].size();k++) {
std::cout<<A[i][j][k];
};
std::cout<<std::endl;
};
std::cout<<std::endl;
};
}
Or, if you don't like initializing everything in one go, and you want to do it at runtime. you can always use the push_back method that std::vector comes with
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<vector<vector<int>>> A;
A.push_back(vector<vector<int>>(
{
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
));
A.push_back(vector<vector<int>>(
{
{0, 0, 1},
{1, 1, 1},
{0, 0, 0}
}
));
A.push_back(vector<vector<int>>(
{
{1, 1},
{1, 1}
}
));
A.push_back(vector<vector<int>>(
{
{0, 1, 1},
{1, 1, 0},
{0, 0, 0}
}
));
A.push_back(vector<vector<int>>(
{
{0, 1, 0},
{1, 1, 1},
{0, 0, 0}
}
));
A.push_back(vector<vector<int>>(
{
{1, 1, 0},
{0, 1, 1},
{0, 0, 0}
}
));
for(int i=0;i<A.size();i++) {
for(int j=0;j<A[i].size();j++) {
for(int k=0;k<A[i][j].size();k++) {
std::cout<<A[i][j][k];
};
std::cout<<std::endl;
};
std::cout<<std::endl;
};
}

Declaring arrays similar to C style (C++)

In C a programmer can declare an array like so:
unsigned char Fonts[2][8] {
[1] = {0, 31, 0, 31, 0, 31, 0, 31}
};
And element [0] is likely random bits. Is there a similar way in C++?
This works in C++:
unsigned char foo [2][8] = {
{},
{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
};
Here, foo[0] is zero-initialized as defined by the C++ standard (ยง8.5.5 - default initialization for POD types is zero-initialization). For non-POD-types the default constructor is called.
You can do this:
unsigned char Fonts[2][8] = {
{0},
{0, 31, 0, 31, 0, 31, 0, 31}
};
Why not just do
unsigned char Fonts[2][8] {
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 31, 0, 31, 0, 31, 0, 31}
};
?