I am trying to declare an array that is sized at runtime/compile through an overload constructor.
private:
auto** arr = new int[n][n];
overloadConstruct(int n){
arr[n][n] = {0,0};
}
This does not work, it says the second n needs to be constant and auto is not allowed. Any help would be appreciated. I am not sure of all the rules with arrays, especially 2d arrays when doing this. I just need to be able to size a 2d array at runtime/compile through an input.
Use a vector of vectors instead:
#include <iostream>
#include <vector>
class Foo
{
public:
Foo( const int rowCount, const int colCount )
: m_2dArray( rowCount, std::vector<int>( colCount ) ) // initialize the vector
{ // member like this
}
void printArr() const
{
for ( size_t row = 0; row < m_2dArray.size( ); ++row )
{
for ( size_t col = 0; col < m_2dArray[ 0 ].size( ); ++col )
{
std::cout << m_2dArray[ row ][ col ] << " ";
}
std::cout << '\n';
}
}
private:
std::vector< std::vector<int> > m_2dArray; // the vector member
};
int main ()
{
int rowCount { };
int colCount { };
std::cout << "Enter row count: ";
std::cin >> rowCount;
std::cout << "Enter column count: ";
std::cin >> colCount;
std::cout << "\nThe contents of 2D array:\n";
Foo obj( rowCount, colCount ); // construct the object using user's input
obj.printArr( );
}
The output:
Enter row count: 10
Enter column count: 20
The contents of 2D array:
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 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 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 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 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 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 0 0
As you can see, the user can enter the values at runtime.
I am recently working with BFS algorithm. I made a maze solving program with this algorithm. here is my code:
#include<iostream>
#include<cmath>
#include<sstream>
#include<vector>
#include<queue>
#include <unistd.h>
using namespace std;
int m,n;
inline int indexFor(int x,int y) {
return (x-1) + m*(y-1);
}
int main() {
FILE *file = fopen("test_case","r"); // test_case file
//build maze
fscanf(file,"%d",&m);
fscanf(file,"%d",&n);
vector<int> grid((m+1)*(n+1));
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
int k;
fscanf(file,"%d",&k);
grid[indexFor(i,j)] = k;
}
}
int startX,startY,endX,endY;
fscanf(file,"%d",&startX);
fscanf(file,"%d",&startY);
fscanf(file,"%d",&endX);
fscanf(file,"%d",&endY);
//bfs starts
queue<int> x,y;
x.push(1);
y.push(1);
vector<int> visited((m+1)*(n+1),0);
vector<vector<int>> path_track((m+1)*(n+1),vector<int>(2,0));
while(x.size()>0) {
int k = x.front(), l = y.front();
x.pop();
y.pop();
visited[indexFor(k,l)]=1;
// this part for printing each steps
cout << "\033[2J\033[H";
cout << "queue size: " << x.size()<<endl;
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
if(visited[indexFor(i,j)]==1) cout << "* ";
else {
if(grid[indexFor(i,j)]==0) {
cout << ". ";
} else {
cout << "# ";
}
}
}
cout << endl;
}
usleep(10);
if(k-1>0) {
if(grid[indexFor(k-1,l)] != 1 && visited[indexFor(k-1,l)]!=1) {
x.push(k-1);
y.push(l);
path_track[indexFor(x.back(),y.back())] = {k,l};
}}
if((k+1)<=m) {
if(grid[indexFor(k+1,l)] != 1 && visited[indexFor(k+1,l)]!=1) {
x.push(k+1);
y.push(l);
//cout << "Path_track: "<<x.back() << ", " << y.back() << " : " << k << ", " << l <<endl;
path_track[indexFor(x.back(),y.back())] = {k,l};
}}
if(l-1>0) {
if(grid[indexFor(k,l-1)] != 1 && visited[indexFor(k,l-1)]!=1) {
x.push(k);
y.push(l-1);
path_track[indexFor(x.back(),y.back())] = {k,l};
}}
if(l+1<=n) {
if(grid[indexFor(k,l+1)] != 1 && visited[indexFor(k,l+1)]!=1) {
x.push(k);
y.push(l+1);
path_track[indexFor(x.back(),y.back())] = {k,l};
}}
}
cout << "\033[2J\033[H";
vector<vector<int>> path;
path.push_back({endX,endY});
while(endX!=0&&endY!=0) {
int kx = endX, ky = endY;
endX = path_track[indexFor(kx,ky)][0];
endY = path_track[indexFor(kx,ky)][1];
path.push_back({endX,endY});
}
path.pop_back();
if(path[path.size()-1][0] == startX && path[path.size()-1][1] == startY)
{
for(vector<int> l:path) grid[indexFor(l[0],l[1])] = 8;
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
if(grid[indexFor(i,j)]==8) {
cout << "X ";
} else {
if(grid[indexFor(i,j)]==0) {
cout << ". ";
} else {
cout << "# ";
}
}
}
cout << endl;
}
} else {
cout << "No path found\n";
for(vector<int> l:path) grid[indexFor(l[0],l[1])] = 8;
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
if(grid[indexFor(i,j)]==8) {
cout << "X ";
} else {
if(grid[indexFor(i,j)]==0) {
cout << ". ";
} else {
cout << "# ";
}
}
}
cout << endl;
}
}
//cout<<path_track[indexFor(2,2)][0]<<","<<path_track[indexFor(2,2)][1]<<endl;
return 0;
}
I made a maze_generator for this problem which is :
#include <iostream>
#include <vector>
using namespace std;
int m,n;
inline int indexFor(int x,int y) {
return m * (x-1) + (y-1);
}
int main() {
srand(time(nullptr));
FILE * f = fopen("test_case","w");
cin >> m;
cin >> n;
vector<int> grid(m*n,0);
fprintf(f,"%d %d\n",m,n);
for(int i = 0; i<grid.size();i++) {
int k = (rand()%7);
if(i == 0 || i==grid.size()-1 ) k = 0;
grid[i] = k<5?0:1;
}
grid[indexFor(m,n)] = 0;
for(int i = 1;i<=m;i++) {
for(int j = 1; j<=n;j++) {
cout << grid[indexFor(i,j)] << " ";
fprintf(f,"%d ",grid[indexFor(i,j)]);
}
cout<<endl;
fprintf(f,"\n");
}
fprintf(f,"1 1\n%d %d",m,n);
return 0;
}
which generated this test_case:
21 50
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1
0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0
1 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0
0 1 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0
0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0
0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0
0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 1 1 0 1 1 0 1
0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1
1 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 0
0 0 1 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0
0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1
1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 1
0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0
0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0
0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1
1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0
0 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 0 1 1 1 0 0
1 1
21 50
In the test case the last two line represents starting and ending point for the maze. In case for maze 0 indicates free path and 1 indicates wall. 1st line denotes the size of maze.
Problem is that when I solve it the queue size jumped to 130k+ for this particular test_case. Is there something I missing? or it is normal?
I solved the problem. Looks like i needed use another array for queue mapping to check if a point is already queued. Here is the final solution:
#include<iostream>
#include<cmath>
#include<sstream>
#include<vector>
#include<queue>
#include <unistd.h>
using namespace std;
int m,n;
inline int indexFor(int x,int y) {
return (x-1) + m*(y-1);
}
int main() {
FILE *file = fopen("test_case","r");
fscanf(file,"%d",&m);
fscanf(file,"%d",&n);
vector<int> grid((m+1)*(n+1));
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
int k;
fscanf(file,"%d",&k);
grid[indexFor(i,j)] = k;
}
}
int startX,startY,endX,endY;
fscanf(file,"%d",&startX);
fscanf(file,"%d",&startY);
fscanf(file,"%d",&endX);
fscanf(file,"%d",&endY);
queue<int> x,y;
x.push(1);
y.push(1);
vector<int> visited((m+1)*(n+1),0);
vector<int> queued((m+1)*(n+1),0); // <-- THIS IS WHAT I ADDED
vector<vector<int>> path_track((m+1)*(n+1),vector<int>(2,0));
while(x.size()>0) {
int k = x.front(), l = y.front();
x.pop();
y.pop();
visited[indexFor(k,l)]=1;
cout << "\033[2J\033[H";
cout << "queue size: " << x.size()<<endl;
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
if(visited[indexFor(i,j)]==1) cout << "* ";
else {
if(grid[indexFor(i,j)]==0) {
cout << ". ";
} else {
cout << "# ";
}
}
}
cout << endl;
}
usleep(10000);
if(k-1>0) {
if(grid[indexFor(k-1,l)] != 1 && visited[indexFor(k-1,l)]!=1&&!queued[indexFor(k-1,l)]) {
x.push(k-1);
y.push(l);
queued[indexFor(x.back(),y.back())] = 1;
path_track[indexFor(x.back(),y.back())] = {k,l};
}}
if((k+1)<=m) {
if(grid[indexFor(k+1,l)] != 1 && visited[indexFor(k+1,l)]!=1&&!queued[indexFor(k+1,l)]) {
x.push(k+1);
y.push(l);
//cout << "Path_track: "<<x.back() << ", " << y.back() << " : " << k << ", " << l <<endl;
path_track[indexFor(x.back(),y.back())] = {k,l};
queued[indexFor(x.back(),y.back())] = 1;
}}
if(l-1>0) {
if(grid[indexFor(k,l-1)] != 1 && visited[indexFor(k,l-1)]!=1&&!queued[indexFor(k,l-1)]) {
x.push(k);
y.push(l-1);
path_track[indexFor(x.back(),y.back())] = {k,l};
queued[indexFor(x.back(),y.back())] = 1;
}}
if(l+1<=n) {
if(grid[indexFor(k,l+1)] != 1 && visited[indexFor(k,l+1)]!=1&&!queued[indexFor(k,l+1)]) {
x.push(k);
y.push(l+1);
queued[indexFor(x.back(),y.back())] = 1;
path_track[indexFor(x.back(),y.back())] = {k,l};
}}
}
cout << "\033[2J\033[H";
vector<vector<int>> path;
/*
for(int i=1;i<=m;i++) {
for(int j =1;j<=m;j++) {
cout << path_track[indexFor(i,j)][0] << "," << path_track[indexFor(i,j)][1]<< " ";
}
cout << endl;
}
*/
path.push_back({endX,endY});
while(endX!=0&&endY!=0) {
int kx = endX, ky = endY;
endX = path_track[indexFor(kx,ky)][0];
endY = path_track[indexFor(kx,ky)][1];
path.push_back({endX,endY});
}
path.pop_back();
if(path[path.size()-1][0] == startX && path[path.size()-1][1] == startY)
{
for(vector<int> l:path) grid[indexFor(l[0],l[1])] = 8;
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
if(grid[indexFor(i,j)]==8) {
cout << "X ";
} else {
if(grid[indexFor(i,j)]==0) {
cout << ". ";
} else {
cout << "# ";
}
}
}
cout << endl;
}
} else {
cout << "No path found\n";
for(vector<int> l:path) grid[indexFor(l[0],l[1])] = 8;
for(int i=1;i<=m;i++) {
for(int j =1;j<=n;j++) {
if(grid[indexFor(i,j)]==8) {
cout << "X ";
} else {
if(grid[indexFor(i,j)]==0) {
cout << ". ";
} else {
cout << "# ";
}
}
}
cout << endl;
}
}
//cout<<path_track[indexFor(2,2)][0]<<","<<path_track[indexFor(2,2)][1]<<endl;
return 0;
}
Does int myarray[7][7] not create a box with 8x8 locations of 0-7 rows and columns in C++?
When I run:
int board[7][7] = {0};
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
cout << board[i][j] << " ";
}
cout << endl;
}
I get output:
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 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 146858616 1 0 0 146858832 1 1978920048
So the 8 columns seem to work, but not the 8 rows.
If I change it to int board[8][7] = {0}; it works on mac CodeRunner IDE, but on linux Codeblocks I get:
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 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1503452472
Not sure what's going on here.
Two dimensional arrays are not different to the one dimensional ones in this regard: Just as
int a[7];
can be indexed from 0 to 6,
int a2[7][7];
can be indexed from 0 to 6 in both dimensions, index 7 is out of bounds. In particular: a2 has 7 columns and rows, not 8.
int board[7][7]; will only allocate 7x7, not 8x8. When it's allocated, you specify how many, but indexes start at 0 and run to the size - 1.
So based on your source, I would say you really want int board[8][8].
int board[7][7] = {0}; creates a 7x7 array. You are going out of bounds in your loop. Change it to int board[8][8] = {0};
int board[8][7] = {0};
When you do as above, you created only 8 rows and 7 columns.
So your loop condition should be as follows:
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 7; j++)
{
If you try as follows system will print garbage values from 8th columns
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
Araay starts from zero means that it will have n-1 elements not n+1 elements
try
int a[8][8] = {}
i = 0
j = 0
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
a[i][j] = 0;
}
}
I have made a 'Map' array and I am attempting to populate it from a 'map' file. On creation I assign the value '0' to each element of the array but the 'Map' file contains the following:
MAP:
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 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
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
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 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 0 0 0 0 0 0 0 0 0
I load the map using 'loadMap()'
loadMap():
void room::loadMap()
{
int x=0;
int y=0;
string line;
ifstream mapFile(NAME + "_MAP.txt");
while(!mapFile.eof())
{
for(int i=0; i<cellsY; i++)
{
getline(mapFile,line,'\n');
for(int j=0; j<cellsX; j++)
{
getline(mapFile,line,' ');
map[(cellsX*j) + cellsY] = atoi(line.c_str());
};
};
}
y = 10;
x = 15;
for(int i=0; i<y; i++)
{
cout << endl;
for(int j=0; j<x; j++)
{
cout << map[(x*j) + y];
};
};
}
In this example the elements are still assigned to '0', but I am trying to mimic the Map files layout.
For starters, you never test that any of the input works, nor
that the open succeeded. Then, in the outer loop, you read
a line from the file, and throw it away, before reading further
in the inner loop. And your calcule of the index is wrong.
What you're probably looking for is something like:
std::ifstream mapFile(...);
if ( !mapFile.is_open() ) {
// Error handling...
}
for ( int i = 0; mapFile && i != cellsY; ++ i ) {
std::string line;
if ( std::getline( mapFile, line ) ) {
std::istringstream text( line );
for ( int j = 0; j != cellsX && text >> map[cells X * i + j]; ++ j ) {
}
if ( j != cellsX ) {
// Error: missing elements in line
}
text >> std::ws;
if ( text && text.get() != EOF ) {
// Error: garbage at end of line
}
}
}
For the error handling, the simplest is just to output an
appropriate error message and continue, noting the error so you
can return some sort of error code at the end.
I think this is what you are looking for.
void room::loadMap()
{
int x=0;
int y=0;
ifstream mapFile(NAME + "_MAP.txt");
for(int i=0; i<cellsY; i++)
{
for(int j=0; j<cellsX; j++)
{
int v;
mapFile >> v;
if ( mapFile.eof() )
{
break;
}
map[(cellsX*j) + cellsY] = v;
}
}
y = 10;
x = 15;
for(int i=0; i<y; i++)
{
cout << endl;
for(int j=0; j<x; j++)
{
cout << map[(x*j) + y];
};
};
}