2d boolean array initialization in c++ - c++

I don't use C that much and I recently got confused about 2d array initialization problem. I need to debug somebody's code and stuck in the following(her original code):
const int location_num = 10000;
bool **location_matrix;
if (node_locations)
{
location_matrix = (bool **)malloc(location_num*sizeof(bool *));
if (!location_matrix)
{
cout<<"error 1 allocating location_matrix" << endl;
exit;
}
for (i=0; i<location_num; i++)
{
location_matrix[i] = (bool *) malloc(location_num*sizeof(bool ));
if (!location_matrix[i])
{
cout<<"error 2 allocating location_matrix" << endl;
exit;
}
for (j=0; j<location_num; j++)
location_matrix[i][j] = false;
}
}
I thought is was redundant, so I changed it to the following:
location_matrix[location_num][location_num] = { {false} };
However, segmentation fault happens at runtime.
My question is: how does the above code fail? If it looks right, what's the difference between dynamically allocation and static allocation? Is it just because the dimension might not be constant, so we need to do it dynamically?
Also, just for curiosity, how do I malloc 2d array that stores pointers? Thanks.

The change would likely require about 100MB (10,000 * 10,000 * 1) on the stack, so the segmentation fault was likely due to a stack overflow.
Edit I originally stated 400MB in the answer, but #Mooing Duck points out bool will likely be 1 byte. I was thinking the Win32 BOOL (for no real reason at all), which is typedefed to an int.

I actually don't see anything wrong with the code.
The following code doesn't work because location_matrix is not allocated:
location_matrix[location_num][location_num] = { {false} };
GCC will allow the following (as an extension):
bool location_matrix[location_num][location_num] = { {false} };
But it will blow your stack because 10000 x 10000 is too large.
Currently, your code uses dynamic allocation. That's the correct way to do it because the matrix is too large to be done as a static array (and may overrun the stack).
As for your last question, "how to make a 2d array that stores pointers": It can be done almost the same way as your current code. Just change bool to int*.
So a 2D array of NULL int pointers will look like this:
int ***location_matrix;
if (node_locations)
{
location_matrix = (int***)malloc(location_num*sizeof(int**));
if (!location_matrix)
{
cout<<"error 1 allocating location_matrix" << endl;
exit;
}
for (i=0; i<location_num; i++)
{
location_matrix[i] = (int**) malloc(location_num*sizeof(int*));
if (!location_matrix[i])
{
cout<<"error 2 allocating location_matrix" << endl;
exit;
}
for (j=0; j<location_num; j++)
location_matrix[i][j] = NULL;
}
}

The standard library is your friend.
#include <vector>
int
main()
{
int location_num = 1000;
std::vector<std::vector<bool> > location_matrix(location_num, std::vector<bool>(location_num, false));
}

Second, the array is likely too large to fit on the stack, so you'd need to dynamically allocate it -- but you can simplify the code as long as the difference between a 2-dimensional array and an array of pointers won't be an issue (as it would be if you needed to pass the array to a function or use pointer arithmetic with it).
You could use something like this:
bool (*location_matrix)[location_num];
location_matrix = (bool (*)[location_num])calloc( location_num,
location_num * sizeof(bool) );
...which allocates space for the whole two-dimensional array and gives a pointer to an array of bool arrays with location_num elements each.

Related

while every value in array is different than specific int value

I have an array of values e.g. 1, 4, 7, 2.
I also have another array of values and I want to add its values to this first array, but only when they all are different from all values that are already in this array. How can I check it? I've tried many types of loops, but I always ended with an iteration problem.
Could you please tell me how to solve this problem? I code in c++.
int array1[7] = {2,3,7,1,0};
int val1 = rand() % 10;
int val2 = rand() % 10;
int array2[2] = {val1, val2};
and I am trying to put every value from array2 into array1. I tried loop
for (int x:array2)
{
while((val1 && val2) == x)
{
val1 = rand() % 10;
val2 = rand() % 10;
}
}
and many more, but still cannot figure it out. I have this problem because I may have various number of elements for array2. So it makes this "&&" solution infinite.
It is just a sample to show it more clearly, my code has much more lines.
Okay, you have a few problems here. If I understand the problem, here's what you want:
A. You have array1 already populated with several values but with space at the end.
1. How do you identify the number of entries in the array already versus the extras?
B. You have a second array you made from two random values. No problem.
You want to append the values from B to A.
2. If initial length of A plus initial length of B is greater than total space allocated for A, you have a new problem.
Now, other people will tell you to use the standard template library, but if you're having problems at this level, you should know how to do this yourself without the extra help from a confusing library. So this is one solution.
class MyArray {
public:
int * data;
int count;
int allocated;
MyArray() : data(nullptr), count(0), allocated(0) {}
~MyArray() { if (data != nullptr) free(data); }
// Appends value to the list, making more space if necessary
void add(int value) {
if (count >= allocated) {
// Not enough space, so make some.
allocated += 10;
data = (data == nullptr) malloc(allocated * sizeof(int))
: realloc)data, allocated * sizeof(int));
}
data[count++] = value;
}
// Adds value only if not already present.
void addUnique(int value) {
if (indexOf(value) < 0) {
add(value);
}
}
// Returns the index of the value, if found, else -1
int indexOf(int value) {
for (int index = 0; index < count; ++index) {
if (data[index] == value) {
return index;
}
}
return -1;
}
}
This class provides you a dynamic array of integers. It's REALLY basic, but it teaches you the basics. It helps you understand about allocation / reallocating space using old-style C-style malloc/realloc/free. It's the sort of code I was writing back in the 80s.
Now, your main code:
MyArray array;
array.add(2);
array.add(3);
array.add(7);
// etc. Yes, you could write a better initializer, but this is easy to understand
MyArray newValues;
newValues.add(rand() % 10);
newValues.add(rand() % 10);
for (int index = 0; index < newValues.count; ++index) {
array.addUnique(newValues.data[index]);
}
Done.
The key part of this is the addUnique function, which simply checks first whether the value you're adding already is in the array. If not, it appends the value to the array and keeps track of the new count.
Ultimately, when using integer arrays like this instead of the fancier classes available in C++, you HAVE TO keep track of the size of the array yourself. There is no magic .length method on int[]. You can use some magic value that indicates the end of the list, if you want. Or you can do what I did and keep two values, one that holds the current length and one that holds the amount of space you've allocated.
With programming, there are always multiple ways to do this.
Now, this is a lot of code. Using standard libraries, you can reduce all of this to about 4 or 5 lines of code. But you're not ready for that, and you need to understand what's going on under the hood. Don't use the fancy libraries until you can do it manually. That's my belief.

Attempting to create a dynamic array

I have the following piece of code, which is only half on the entire code:
// Declare map elements using an enumeration
enum entity_labels {
EMPTY = 0,
WALL
};
typedef entity_labels ENTITY;
// Define an array of ASCII codes to use for visualising the map
const int TOKEN[2] = {
32, // EMPTY
178 // WALL
};
// create type aliases for console and map array buffers
using GUI_BUFFER = CHAR_INFO[MAP_HEIGHT][MAP_WIDTH];
using MAP_BUFFER = ENTITY[MAP_HEIGHT][MAP_WIDTH];
//Declare application subroutines
void InitConsole(unsigned int, unsigned int);
void ClearConsole(HANDLE hStdOut);
WORD GetKey();
void DrawMap(MAP_BUFFER & rMap);
/**************************************************************************
* Initialise the standard output console
*/
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != INVALID_HANDLE_VALUE)
{
ClearConsole(hStdOut);
// Set window title
SetConsoleTitle(TEXT("Tile Map Demo"));
// Set window size
SMALL_RECT srWindowRect;
srWindowRect.Left = 0;
srWindowRect.Top = 0;
srWindowRect.Bottom = srWindowRect.Top + MAP_HEIGHT;
srWindowRect.Right = srWindowRect.Left + MAP_WIDTH;
SetConsoleWindowInfo(hStdOut, true, &srWindowRect);
// Set screen buffer size
COORD cWindowSize = { MAP_WIDTH, MAP_HEIGHT };
SetConsoleScreenBufferSize(hStdOut, cWindowSize);
}
/*************************************************************************/
/*************************************************************************
* Initialise the tile map with appropriate ENTITY values
*/
MAP_BUFFER tileMap;
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
tileMap [row][col] = WALL;
}
}
Essentially the entire code is used to create a tile map and output it to screen but I'm attempting to make tileMap a dynamic array in runtime.
I have tried creating one down where the tileMap is being created.
I've tried creating one just after "entity_lables" are given the typedef "ENTITY".
I've tried creating one after the "MAP_BUFFER" and "GUI_BUFFER" become aliases.
But still I'm at a loss, I have no idea on how to successfully implement a dynamic array to tileMap, and I certainly don't know the best spot to put it.
Any help would be greatly appreciated.
The syntax you are using for defining your array is for a constant sized C array. In general you should shy away from C arrays unless the size of the data is determined at compile time(and never needs to change) and the array never leaves the scope(because a C array does not retain information on its own size.)
In place of constant or dynamically sized C arrays I would suggest to use the Vector container. The Vector is a dynamically sized container that fills up from the back, the last element you have added to
std::vector<std::vector<ENTITY>>
To add the vector container to your project add the line
#include <vector>
To fill the container your loop could look like:
MAP_BUFFER tileMap;
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
std::vector<ENTITY> column; // A column of the tile map
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
column.push_back(WALL); // Add one element to the column
}
tileMap.push_back(column); // Add the column to the tile map
}
or you could initialize the Vector to the size you want at the beginning and use your current loop to assign the tile values:
using TILE_MAP = vector<vector<ENTITY>>;
// MAP_WIDTH x MAP_HEIGHT multidimensional vector
TILE_MAP tileMap(MAP_WIDTH, vector<ENTITY>(MAP_HEIGHT));
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
tileMap [row][col] = WALL;
}
}
Calling an element of a vector after it has been filled has the same syntax as an array.
tileMap[2][4]
You can also check the length of the vector:
int rows = tileMap.size();
if( rows > 0 )
int columnsInRow0 = tileMap[0].size()
While you are at it you should look into other containers like Maps and Sets since they make your life easier.
Edit:
Since you want to know how to make a dynamic array not using a vector I will give you an answer: std::vector is the C++ defined dynamically sized array. C arrays will not change size after they are defined, vector will.
However I think you are asking about the ability to define runtime constant sized arrays. So I will explain what they are and why you should not use them.
When you define the C array you are probably getting a warning saying that the expression needs to be constant.
A C array is a pointer to the stack. And the implementation of the compiletime C array is that it needs to be a constant size at compile time.
int compiletimeArray[] = { 1, 2, 3 };
// turns out c arrays are pointers
int* ptr = compiletimeArray;
// prints 2
std::cout << compiletimeArray[1];
// prints 2
std::cout << ptr[1];
// prints 2
std::cout << *(compiletimeArray + 1);
// also prints 2
std::cout << *(ptr + 1); //move pointer 1 element and de-reference
Pointers are like a whiteboard with a telephone number written on it. The same kind of issues occur as with telephone numbers; number on whiteboard has been erased, number on whiteboard has changed, recipient does not exist, recipient changed their number, service provider running out of available numbers to give new users... Keep that in mind.
To get create a runtime constant sized array you need to allocate the array on the heap and assign it to a pointer.
int size = 4;
int* runtimeArray = new int[size]; // this will work
delete[] runtimeArray; // de-allocate
size = 8; // change size
runtimeArray = new int[size]; // allocate a new array
The main difference between the stack and heap is that the stack will de-allocate the memory used by a variable when the program exits the scope the variable was declared in, on the other hand anything declared on the heap will still remain in memory and has to be explicitly de-allocated or you will get a memory leak.
// You must call this when you are never going to use the data at the memory address again
// release the memory from the heap
delete[] runtimeArray; // akin to releasing a phone number to be used by someone else
If you do not release memory from the heap eventually you will run out.
// Try running this
void crashingFunction() {
while(true)
{
// every time new[] is called ptr is assigned a new address, the memory at the old address is not freed
// 90001 ints worth of space(generally 32 or 64 bytes each int) is reserved on the heap
int* ptr = new int[90001]; // new[] eventually crashes because your system runs out of memory space to give
}
}
void okFunction() {
// Try running this
while(true)
{
// every time new[] is called ptr is assigned a new address, the old is not freed
// 90001 ints worth of space is reserved on the heap
int* ptr = new int[90001]; // never crashes
delete[] ptr; // reserved space above is de-allocated
}
}
Why use std::vector? Because std::vector internally manages the runtime array.
// allocates for you
vector(int size) {
// ...
runtimeArray = new runtimeArray[size];
}
// When the vector exits scope the deconstructor is called and it deletes allocated memory
// So you do not have to remember to do it yourself
~vector() {
// ...
delete[] runtimeArray;
}
So if you had the same scenario as last time
void vectorTestFunction() {
// Try running this
while(true)
{
std::vector<int> vec(9001); // internally allocates memory
} // <-- deallocates memory here because ~vector is called
}
If you want to use a runtime constant array I suggest the std:array container. It is like vector in that it manages its internal memory but is optimized for if you never need to add new elements. It is declared just like vector but does not contain resizing functions after its constructor.

my code does not run for the input 1 and 1000 or any other larger inputs

when i am trying to run this code for input 1 and 1000 it shows me segmentation fault .what will be the correction in this code ?
void sorting(int sum[],long int k);
int main() {
int sum[100000];
int L,R,i,j;
long int k=0;
cin>>L;
cin>>R;
for(i=L;i<=R;i++)
{
for(j=i;j<=R;j++)
{
sum[k]=i^j;
k++;
}
}
sorting(sum,k);
cout<<sum[k-1];
return 0;
}
void sorting(int sum[],long int k)
{
int i,j;
long int temp;
for(i=0;i<k;i++)
{
for(j=0;j<k;j++)
{
if(sum[i]<=sum[j])
{
temp=sum[i];
sum[i]=sum[j];
sum[j]=temp;
}
}
}
}
The segmentation fault is caused by stack overflow. This line:
int sum[100000];
sum uses 400K spaces of stack, which is bigger than the normal size of stack.
To fix the problem, you can use std::vector to implement sum instead.
I think the problem is not in the stack size, but content of variable k
for(i=L;i<=R;i++)
{
for(j=i;j<=R;j++)
{
sum[k]=i^j;
k++;
}
}
For L = 1, R = 1000, this loop makes k as large as 500500, which exceeds the size of sum array, which has 100000 elements.
To dirty-fix this error you could make sum array larger, but, since stack size indeed can be limited, it's better to allocate huge arrays on a heap. This is also more elegant solution in your case, because you can dynamically set required size of the array.
To allocate memory on heap you can use std::vector or C++11 unique_ptr<int[]> (you could also use new[] and delete[], although recently it is advised to use methods mentioned previously, because they secure some aspects of dynamic memory allocation).
To create array with unique_ptr<int[]>
std::unique_ptr<int[]> sum = std::make_unique<int[]>(mysize);
//or if make_unique is not available
std::unique_ptr<int[]> sum(new int[mysize]);
It looks like you have arithmetic series, so you can calculate mysize using equations for the sum of arithmetic progression http://en.wikipedia.org/wiki/Arithmetic_progression#Sum
With std::vector it can be less error-prone, because std::vector can grow, so you can simply push_back() elements inside the loop.
Define sum variable
std::vector<int> sum;
Then inside the loop instead of sum[k]=i^j; you write
sum.push_back(i^j);

Array as out parameter in c++

I created a function that returns an error code (ErrCode enum) and pass two output parameters. But when I print the result of the function, I don't get the correct values in the array.
// .. some codes here ..
ErrCode err;
short lstCnt;
short lstArr[] = {};
err = getTrimmedList(lstArr, &lstCnt);
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d", i, lstArr[i]);
// .. some codes here ..
The getTrimmedList function is like this:
ErrCode getTrimmedList(short* vList, short* vCnt)
{
short cnt;
ErrCode err = foo.getListCount(FOO_TYPE_1, &cnt);
if (NoError!=err) return err;
short* list = new short [cnt];
short total = 0;
for (short i=0; i<cnt; ++i)
{
FooBar bar = foo.getEntryByIndex(FOO_TYPE_1, i);
if (bar.isDeleted) continue;
list[total] = i;
++total;
}
*vCnt = total;
//vList = (short*)realloc(index, sizeof(short)*total);
vList = (short*)malloc(sizeof(short)*total);
memcpy(vList, list, sizeof(short)*total)
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d", i, lstArr[i]);
return NoError;
}
where:
foo is an object that holds arrays of FooBar objects
foo.getListCount() returns the number of objects with type FOO_TYPE_1
FOO_TYPE_1 is the type of object we want to take/list
foo.getEntryByIndex() returns the ith FooBar object with type FOO_TYPE_1
bar.isDeleted is a flag that tells if bar is considered as 'deleted' or not
What's my error?
Edit:
Sorry, I copied a wrong line. I commented it above and put the correct line.
Edit 2
I don't have control over the returns of foo and bar. All their function returns are ErrCode and the outputs are passed through parameter.
Couple of questions before I can answer your post...
Where is "index" defined in:
vList = (short*)realloc(index, sizeof(short)*total);
Are you leaking the memory associated with:
short* list = new short [cnt];
Is it possible you have accidentally confused your pointers in memory allocation? In any case, here is an example to go from. You have a whole host of problems, but you should be able to use this as a guide to answer this question as it was originally asked.
WORKING EXAMPLE:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int getTrimmedList(short** vList, short* vCnt);
int main ()
{
// .. some codes here ..
int err;
short lstCnt;
short *lstArr = NULL;
err = getTrimmedList(&lstArr, &lstCnt);
// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
printf("lstArr[%3d] = %d\n", i, lstArr[i]);
// .. some codes here ..
return 0;
}
int getTrimmedList(short** vList, short* vCnt)
{
short cnt = 5;
short* list = new short [cnt];
short* newList = NULL;
short total = 0;
list[0] = 0;
list[1] = 3;
list[2] = 4;
list[3] = 6;
total = 4;
*vCnt = total;
newList = (short*)realloc(*vList, sizeof(short)*total);
if ( newList ) {
memcpy(newList, list, sizeof(short)*total);
*vList = newList;
} else {
memcpy(*vList, list, sizeof(short)*total);
}
delete list;
return 0;
}
You have serious problems.
For starters, your function has only one output param as you use it: vCnt.
vList you use as just a local variable.
realloc is called with some index that we kow nothing about, not likely good. It must be something got from malloc() or realloc().
The allocated memory in vList is leaked as soon as you exit getTrimmedList.
Where you call the function you pass the local lstArr array as first argument that is not used for anything. Then print the original, unchanged array, to bounds in cnt, while it has 0 size still -- behavior is undefined.
Even if you managed to pass that array by ref, you could not reassign it to a different value -- C-style arrays can't do that.
You better use std::vector that you can actually pass by reference and fill in the called function. eliminating the redundant size and importantly the mess with memory handling.
You should use std::vector instead of raw c-style arrays, and pass-by-reference using "&" instead of "*" here. Right now, you are not properly setting your out parameter (a pointer to an array would look like "short **arr_ptr" not "short *arr_ptr", if you want to be return a new array to your caller -- this API is highly error-prone, however, as you're finding out.)
Your getTrimmedList function, therefore, should have this signature:
ErrCode getTrimmedList(std::vector<short> &lst);
Now you no longer require your "count" parameters, as well -- C++'s standard containers all have ways of querying the size of their contents.
C++11 also lets you be more specific about space requirements for ints, so if you're looking for a 16-bit "short", you probably want int16_t.
ErrCode getTrimmedList(std::vector<int16_t> &lst);
It may also be reasonable to avoid requiring your caller to create the "out" array, since we're using smarter containers here:
std::vector<int16_t> getTrimmedList(); // not a reference in the return here
In this style, we would likely manage errors using exceptions rather than return-codes, however, so other things about your interface would evolve, as well, most likely.

Trying to fill a 2d array of structures in C++

As above, I'm trying to create and then fill an array of structures with some starting data to then write to/read from.
I'm still writing the cache simulator as per my previous question:
Any way to get rid of the null character at the end of an istream get?
Here's how I'm making the array:
struct cacheline
{
string data;
string tag;
bool valid;
bool dirty;
};
cacheline **AllocateDynamicArray( int nRows, int nCols)
{
cacheline **dynamicArray;
dynamicArray = new cacheline*[nRows];
for( int i = 0 ; i < nRows ; i++ )
dynamicArray[i] = new cacheline [nCols];
return dynamicArray;
}
I'm calling this from main:
cacheline **cache = AllocateDynamicArray(nooflines,noofways);
It seems to create the array ok, but when I try to fill it I get memory errors, here's how I'm trying to do it:
int fillcache(cacheline **cache, int cachesize, int cachelinelength, int ways)
{
for (int j = 0; j < ways; j++)
{
for (int i = 0; i < cachesize/(cachelinelength*4); i++)
{
cache[i][ways].data = "EMPTY";
cache[i][ways].tag = "";
cache[i][ways].valid = 0;
cache[i][ways].dirty = 0;
}
}
return(1);
}
Calling it with:
fillcache(cache, cachesize, cachelinelength, noofways);
Now, this is the first time I've really tried to use dynamic arrays, so it's entirely possible I'm doing that completely wrong, let alone when trying to make it 2d, any ideas would be greatly appreciated :)
Also, is there an easier way to do write to/read from the array? At the moment (I think) I'm having to pass lots of variables to and from functions, including the array (or a pointer to the array?) each time which doesn't seem efficient?
Something else I'm unsure of, when I pass the array (pointer?) and edit the array, when I go back out of the function, will the array still be edited?
Thanks
Edit:
Just noticed a monumentally stupid error, it should ofcourse be:
cache[i][j].data = "EMPTY";
You should find your happiness. You just need the time to check it out (:
The way to happiness