Trying to fill a 2d array of structures in C++ - 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

Related

How to return 2D Array without causing Segmentation Fault (C++)

A homework assignment for an introductory C++ course.
The task is to search a two dimensional array for two numbers adding up to a given number 'search_sum.' Enter all found addends as {startRow,startColumn,endRow,endColumn} in the array 'summations,' then return the array 'summations'.
The line with summations[*sums_found] = new size_t[kIndices_size]; in the if statement was written by the instructor, as well as the comment. I am under the impression that this allocates a new space in memory where data can be assigned to and stored, so, in the next line of code, I attempted to take the column and row variables from the for loop and place them in the newly allocated memory as such.
summations[*sums_found]={startRow, column, endRow, column};
This threw a 'too many assignments' and 'segmentation fault' error.
I assumed you just could not do it this way, and data must be added to a 2D array in another fashion. I removed the faulty assignment code and ran the code as shown below through a debugger, just out of curiosity. The error thrown was once again a Segmentation Fault.
// Parameters:
// - matrix: a two-dimension integer array
// - matrix_size: a two-element size_t array storing sizes of matrix
// - search_sum: the integer value for which the function seeks sums
// - sums_found: an OUTPUT PARAMETER pointing to a size_t
//
const size_t** FindSum(const int** matrix,
const size_t* matrix_size,
int search_sum,
size_t* sums_found) {
*sums_found = 0; // init sums found to 0
size_t summations_size = 2; // start assuming no more than 2 summations
// build structure to hold all found summations
size_t** summations = new size_t*[summations_size];
switch (search_sum)
{
case -92:{ //column search
for(size_t column = 0; column < matrix_size[1]; column++){
for(size_t startRow = 0; startRow < matrix_size[0]; startRow++){
for(size_t endRow = 0; endRow < matrix_size[0]; endRow++){
int j = matrix[startRow][column];
int k = matrix[endRow][column];
int sum = j + k;
if(sum = search_sum){
summations[*sums_found] = new size_t[kIndices_size]; // only done when summation is found
*sums_found++;
}
}
}
}
}
break;
case 60:{ //row search
for(size_t row = 0; row < matrix_size[0]; row++){
for(size_t startColumn = 0; startColumn < matrix_size[1]; startColumn++){
for(size_t endColumn = 0; endColumn < matrix_size[1]; endColumn++){
int j = matrix[row][startColumn];
int k = matrix[row][endColumn];
int sum = j + k;
if(sum = search_sum){
summations[*sums_found] = new size_t[kIndices_size]; // only done when summation is found
*sums_found++;
}
}
}
}
}
break;
case 1203:{ //desc/ascending diagonal
}
break;
case 412:{ //single entry
}
break;
default:{ //large array
}
break;
}
return const_cast<const size_t**>(summations);
}
I did not know what this was, so I researched the error and found that you are not allowed to perform a read/write action on read-only code, which makes sense. What I do not understand is what exactly makes this code read-only, when it seems like its function is to assign a new space for data to be assigned to, which (to me), sounds like a 'write-like' action? I more than likely am misunderstanding the full scope of the codes function, and I am further confused with as to how I should go about assigning the data to the summations array.
Also, this is a university course taught by a grad student who is (seemingly) less than well versed in c++. It is a very 'teach yourself' type class. I understand that this assignment is an exercise on pointers and references, but it feels like I am very poorly equipped to solve a problem like this, and I am unsure what exactly to research and study independently to improve my knowledge of this particular topic. Please, if you can tell what it is I am struggling with just by looking at the code I've written, let me know what I should prioritize my studying on.

C++ order of operations for initializing an array size

I'm trying to allocate the exact size of the array here. However I need to initialize it before I calculate the size of the array. does anyone know what I should do now?
Thanks in advance!
b.t.w I'm making a hangman game, just for fun.
char letters[30];
strcpy(letters, word.c_str());
int wordLen = 0;
for (int i = 0; i < letters[i]; i++){
wordLen++;
}
It is not clear, what you are trying to do with that loop, and it looks very suspicious (you need to provide more information on what you are trying to do here for advise on how to fix it if necessary), but assuming it is correct your code can be fixed by eliminating that buffer and strcpy() call at all:
int wordLen = 0;
for (int i = 0; i < word[i]; i++){
wordLen++;
}
if you need a copy of variable word to modify, not changing original, then just create another std::string instance as a copy. There is no reason to create raw char array in your case.

How to generate a hashmap for huge chunk of data?

I want to make a map such that a set of pointers point to arrays of dynamic size.
I did use hashing with chaining. But since data I am using it for is huge, the program give std::bad_alloc after few iterations. The reason of which may be new used to generate the linked list.
Someone please suggest which data structure shall I use?
Or anything else that can improve memory usage with my hash table?
Program is in C++.
This is what my code looks like:
Initialization of hashtable:
class Link
{
public:
double iData;
Link* pNext;
Link(double it) : iData(it)
{ }
void displayLink()
{ cout << iData << " "; }
};
class List
{
private:
Link* pFirst;
public:
List()
{ pFirst = NULL; }
void insert(double key)
{
if(pFirst==NULL)
pFirst = new Link(key);
else
{
Link* pLink = new Link(key);
pLink->pNext = pFirst;
pFirst = pLink;
}
}
};
class HashTable
{
public:
int arraySize;
vector<List*> hashArray;
HashTable(int size)
{
hashArray.resize(size);
for(int j=0; j<size; j++)
hashArray[j] = new List;
}
};
main snippet:
int t_sample = 1000;
for(int i=0; i < k; i++) // initialize random position
{
x[i] = (cal_rand() * dom_sizex); //dom_sizex = 20e-10 cal_rand() generates rand no between 0 and 1
y[i] = (cal_rand() * dom_sizey); //dom_sizey = 10e-10
}
for(int t=0; t < t_sample; t++)
{
int size;
size = cell_nox * cell_noy; //size of hash table cell_nox = 212, cell_noy = 424
HashTable theHashTable(size); //make table
int hashValue = 0;
for(int n=0; n<k; n++) // k = 10*212*424
{
int m = x[n] /cell_width; //cell_width = 4.7e-8
int l = y[n] / cell_width;
hashValue = (kx*l)+m;
theHashTable.hashArray[hashValue]->insert(n);
}
-------
-------
}
First things first, use a Standard Container. In your specific case, you might want:
either std::unordered_multimap<int, double>
or std::unordered_map<int, std::vector<double>>
(Note: if you do not have C++11, those are available in Boost)
Your main loop becomes (using the second option):
typedef std::unordered_map<int, std::vector<double>> HashTable;
for(int t = 0; t < t_sample; ++t)
{
size_t const size = cell_nox * cell_noy;
// size of hash table cell_nox = 212, cell_noy = 424
HashTable theHashTable;
theHashTable.reserve(size);
for (int n = 0; n < k; ++n) // k = 10*212*424
{
int m = x[n] / cell_width; //cell_width = 4.7e-8
int l = y[n] / cell_width;
int const cellId = (kx*l)+m;
theHashTable[cellId].push_back(n);
}
}
This will not leak memory (reliably), although of course you might have other leaks, and thus will give you a reliable baseline. It is also probably faster than your approach, with a more convenient interface, etc...
In general you should not re-invent the wheel, unless you have a specific need that is not addressed by the available wheels or you are actually trying to learn how to create a wheel or to create a better wheel.
The OS has to solve the same issues with the memory pages, maybe it's worth looking at how that is done? First of all, let's assume all pages are on the disk. A page is a fixed size memory chunk. For your use case, let's say it's an array of your records. Because RAM is limited, the OS maintains a mapping between the page number and it's location in RAM.
So, let's say your pages have 1000 records, and you want to access record 2024, you would ask the OS for page 2, and read record 24 from that page. That way, your map is only 1/1000 in size.
Now, if your page has no mapping to a memory location, then it is either on disk or has never been accessed before (is empty). Then you need to swap out another page, and load that page from disk (and update the location mapping).
This is a very simplified description of what happens and i wouldn't be surprised if someone jumps me in the neck for describing it like this.
The point is:
What does this mean for you?
First of all, your data exceeds your RAM - you won't get around writing to disk, if you don't want to try compression first.
Second, your chains can work as pages if you want, but i wonder whether just paging your hashcode would work better. What i mean is, use the upper bits as page number, and the lower bits as offset in the page. Avoiding collisions is still key, as you want to load the least pages possible. You can still chain your pages, and end up with a much smaller map.
Second - a crucial part is deciding which pages to swap out to make room for the new pages. LRU should do ok. If you can better predict which pages you will (not) need, so much better for you.
Third - you need placeholders for your pages to tell you whether they are in-memory or on disk.
Hope this helps.

Array "breaks" when resizing

Well, I have a class which is supposed to be a container for quadratic polynomials (which is a template and I'm using floats there, but that shouldn't matter much). I made it using a dynamic array, and I was supposed to overload + and - operators... Not a problem, eh? Well, it seemed all nice and dandy until I actually run it.
listf listf::operator+(listf rhs)
{
listf newlist;
for(int i = 0; i < elementcount; ++i)
newlist.add(array[i]);
for(int j = 0; j < rhs.elementcount; ++j)
newlist.add(rhs.array[j]);
std::cout<<newlist;
return newlist;
}
Nothing much. Should do its job correctly, right? That cout is just to check if it works. But it does not.
Should do something like this, right?
With one list consisting of:
X^2+5x+52.4
2X^2+7x-12
and the second one having just X^2+2X+1, it should make a list and display:
X^2+5x+52.4
2X^2+7x-12
X^2+2X+1
Buuuut no, it comes to this:
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
I've been battling with it for quite some time and have not found why it would do that.
Code for adding new polynomials is still quite simple:
void listf::add(polynomial<float> plnm)
{
if(array == NULL)
{
++elementcount;
array = new polynomial<float>[elementcount];
array[0] = plnm;
}
else
{
array = resize(array, elementcount+1, elementcount);
array[elementcount++] = plnm;
}
}
And resize is a private function in this class:
polynomial<float>* listf::resize(polynomial<float>* arr, int newSize, int oldSize)
{
polynomial<float>* newArr = new polynomial<float>[newSize];
for(int i = 0; i < oldSize; ++i)
{
newArr[i] = arr[i];
}
delete[] arr;
return newArr;
}
If we're making a smaller array (for deleting objects), I just put oldSize equal to newSize (I know it's a bad practice and confusing for others, but I was just testing things :( )
I'm out of ideas. Adding new elements to an object seems working, but when I want to add two objects it breaks, prints elements that are not correct and then crashes with CodeLite reporting something like "ntdll!LdrVerifyImageMatchesChecksumEx" in Call Stack. Even better, when I tested it right now, it displayed correct values, but still crashed at return.
Forget the home-made dynamic array and use vector. Whenever you go into the realm of classes and memory management, it isn't as trivial as coding up a few new[] and delete[] calls. It can stop you dead in your tracks in the development of your program.
#include <vector>
//...
typedef std::vector<polynomial<float> > PolynomialFloatArray;
//...
class listf
{
PolynomialFloatArray array;
//...
void add(const polynomial<float>& plnm);
//...
PolynomialFloatArray& resize(PolynomialFloatArray& arr, int newSize)
};
//...
void listf::add(const polynomial<float>& plnm)
{
array.push_back(plnm);
}
PolynomialFloatArray& listf::resize(PolynomialFloatArray& arr, int newSize)
{
arr.resize(newSize);
return arr;
}
There in a nutshell is all of that code you wrote, reduced down to 2 or 3 lines.
Like the comments on the question point out, you would probably be better off using std::vector for this, as it has push_back() to add stuff to the end, and automatically resizes itself to do so, though you can force it to resize with resize().

Radix Sort using C++

Suppose I have bunch of numbers. I have to first put the least significant digit into the corresponding bucket. Ex: 530 , I have to first put into the bucket 0. For number 61, I have to put into bucket 1.
I planned to use a multidimensional array to do this. So I create a 2-dimenional array, which nrows is 10 ( for 0~ 9) and ncolumns is 999999 ( because I don't know how large will the list be):
int nrows = 10;
int ncolumns = 999999;
int **array_for_bucket = (int **)malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
array_for_bucket[i] = (int *)malloc(ncolumns * sizeof(int));
left = (a->value)%10;
array_for_bucket[left][?? ] = a->value;
Then I created one node call a. In this node a, there is a value 50. To find out which bucket I want to put it in, I calculate "left" and I got 0. So I want to put this a-> value into bucket 0. But now I am stuck. How do I put this value into the bucket? I have to use a pointer array to do this.
I thought for a long time but still couldn't find a good way to do it. So please share some ideas with me. thank you!
There is a much easier way of doing this, and instead of radix*nkeys space you only need an nkeys-sized buffer.
Allocate a second buffer that can fit nkeys keys. Now do a first pass through your data and simply count how many keys end up in each bucket. You now can create a radix-sized array of pointers where each pointer is to the start of that bucket in the output buffer. Finally, the second pass though the data moves the keys. Every time you move a key, increment that bucket pointer.
Here's some C code to make into C++:
void radix_sort(int *keys, int nkeys)
{
int *shadow = malloc(nkeys * sizeof(*keys));
int bucket_count[10];
int *bucket_ptrs[10];
int i;
for (i = 0; i < 10; i++)
bucket_count[i] = 0;
for (i = 0; i < nkeys; i++)
bucket_count[keys[i] % 10]++;
bucket_ptrs[0] = shadow;
for (i = 1; i < 10; i++)
bucket_ptrs[i] = bucket_ptrs[i-1] + bucket_count[i-1];
for (i = 0; i < nkeys; i++)
*(bucket_ptrs[keys[i] % 10]++) = keys[i];
//shadow now has the sorted keys
free(shadow);
}
But I may have misunderstood the question. If you are doing something a little different than radix sort, pleas add some details.
Look the Boost Pointer containers library if you want to store pointers.
C++ isn't my forte but this code from wikipedia-Raidx Sort is very comprehensive and probably is more C++-ish than what you've implemented so far. Hope it helps
This is C++, we don't use malloc anymore. We use containers. A two-dimensional array is a vector of vectors.
vector<vector<int> > bucket(10);
left = (a->value)%10;
bucket[left].push_back(a->value);