So I have to make a 2-d array of strings named history[][], where history[i] stores all of the subjects currently involved in experiment i, and history[i][j] contains a string listing all of the experiments that this particular subject has been a part of. The thing is, I have to use int* numsubjects, an array of integers that tells me how many subjects are in experiment i. However, the contents of numsubjects should be able to move around as subjects can be moved into other experiments. I have no idea how to go about doing this. I cannot use vector, dequeue, or list.
experiments = 0;
numsubjects = new int[experiments+1];
numsubjects[experiments] = n;
history = new string*[0];
for(int j = 0; j < n; j++) {
history[0] = new string[j];
history[0][j] = "0";
}
The above code initializes everything when there is only one experiment, experiment 0. I need a way to make history somehow with numsubjects in it.
If you must use C-style arrays, then realloc() will allow you to resize your array.
However, since this is C++, I strongly encourage you to use std::vector or std::map.
Related
I'm trying to write directly into a
auto tablelisttt = std::make_shared<std::vector< std::array<std::string, 9>>(size);
for (int j = 1; j <=max; j++)
{
//dummy example code
tablelisttt->operator[0](j)="Hello"; //Only one string at a time in an array
}
so that data from a database is written directly to the vector array as efficiently / quickly as possible.
but no matter what i try i can't get it to write into the vector array directly with the msvc compiler (the gcc online compilers work )
i use c++19
I'm trying to use a linear search function on a dynamic array I created but then the teaching assistant for my computer science class told us that most search functions use const arrays.
Is there any way I can edit my dynamic array to become contant? Or is it also possible to make a search function that uses a dynamic array (and would not give errors?).
I'll give a brief insight into my code:
I dynamically create an array using the rows I read in from a file and then dynamically allocate each row to an array of columns.
char ** domain[] = new char * [rows];
for(int i = 0; i < rows; i++)
{
*domain = new char[columns];
domain++;
}
The type of function that we were taught for searching is:``
char searchArray( const char list[], char letter, int maxSize)
{
>code goes here
}
Is there any other method of using a search function that takes in dynamic multidimensional arrays?
In response to the comments, I can't use vectors. This is an assignment for us to use normal arrays. I haven't been taught how to to use vectors yet.
In the line
char ** domain[] = new char * [rows];
char ** domain[] tries to make an array of char **. If the compiler didn't complain about not having a valid array size in the [] and you would have a 3D structure. You want just plain old char ** for a 2D structure, so
char ** domain = new char * [rows];
The loop filling out the inner dimension is correct except it loses track of the starting point of domain
for(int i = 0; i < rows; i++)
{
*domain = new char[columns];
domain++;
}
Should be something like
char ** temp = domain;
for(int i = 0; i < rows; i++)
{
*temp = new char[columns];
temp++;
}
To preserve the starting point, but for this case array notation is probably the smarter and easier-to-read option.
for(int i = 0; i < rows; i++)
{
domain[i] = new char[columns];
}
On to searchArray. It needs to know it's getting two dimensions, (const char **) and that there are two max sizes (maxRow and maxColumn). It will look something like
char searchArray(const char ** list,
char letter,
int maxRow,
int maxColumn)
{
>code goes here
}
Code goes here is your problem, but will probably be two nested for loops iterating to maxRow and maxColumn and returning when letter is found.
But... Why return a char? Returning the location in the array is much more useful. We could use std::pair, but if std::vector is off limits, pair probably is as well. Consider something like the following instead:
struct coord
{
int row;
int column;
};
coord searchArray(const char ** list,
char letter,
int maxRow,
int maxColumn)
{
coord location;
>code goes here
return location;
}
If the item is not found, set row and column to something impossible to get like -1 so you can easily test for the not found case.
Stop here unless you want to <expletive deleted> with your teacher's brain.
The above doesn't build a 2D array. You can't get a dynamically allocated 2D array in C++. What you have is an array of arrays. There are a couple downsides to this, look at all the work that goes into stitching one together and computers love it when things go in straight lines. Array of arrays doesn't. Every different allocation can be somewhere completely different in memory forcing the program to hop around, waiting on and loading different chunks of memory. Sometimes The program will spend more time sitting around waiting for stuff to be found and loaded than it'll spend doing the actual work. This sucks.
The solution is to make a 1D array and make it look like a 2D array. Here's an example of that from the C++ FAQ
You'll learn a lot of neat stuff from following this example, not the least of which being RAII and the Rule of Three, two concepts without which you cannot write non-trivial high quality C++ code.
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.
In SO question [How to allocate a 2D array of pointers in C++] [1], the accepted answer also makes note of the correct procedure of how to de-allocate and delete said array, namely "Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order." So, I've been successfully using this 2D array in a cellular automaton simulation program. I cannot, however, get this array's memory management correct. I do not see an SO answer for how to do this other than the reference above.
I allocate the 2D array as follows:
Object*** matrix_0 = new Object**[rows];
for (int i = 0; i < rows; i++) {
matrix_0[i] = new Object*[cols];
}
My futile attempt(s) (according to Valgrind) to properly de-allocate the above array are as follows:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix_0[i][j] = NULL;
}
}
delete [] matrix_0;
matrix_0 = NULL;
Clearly, I'm missing the rows and cols part as reference [1] suggests. Can you show me what I'm missing? Thanks in advance.
[1]: (20 Nov 2009) How to allocate a 2D array of pointers in C++
You have a tonne of deleting to do in this:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
delete matrix_0[i][j]; // delete stored pointer
}
delete[] matrix_0[i]; // delete sub array
}
delete [] matrix_0; //delete outer array
matrix_0 = NULL;
There is no need to NULL anything except matrix_0 because they are gone after delete.
This is horrible and unnecessary. Use a std::vector and seriously reconsider the pointer to the contained object.
std::vector<std::vector<Object*>> matrix_0(rows, std::vector<Object*>(cols));
Gets what you want and reduces the delete work to
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
delete matrix_0[i][j]; // delete stored pointer
}
}
But SergeyA's suggestion of storing unique_ptr, std::vector<std::vector<std::unique_ptr<Object>>> matrix_0; reduces the deletions required to 0.
Since speed is one of OP's goals, there is one more improvement:
std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);
Access is
matrix_0[row * cols + col];
This trades a bit of visible math for the invisible math and pointer dereferences currently going on behind the scenes. The important part is the vector is now stored as a nice contiguous block of memory increasing spacial locality and reducing the number of cache misses. It can't help with the misses that will result from the pointers to Objects being scattered throughout memory, but you can't always win.
A note on vector vs array. Once a vector has been built, and in this case it's all done in one shot here:
std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);
all a vector is is a pointer to an and a couple other pointers to mark end and the the location of the last location used. Access to the data array is no different from access to a dynamic array made with new. Using the index operator [] compiles down to data_pointer + index exactly the same as using [] on an array. There is no synchronizing or the like as in Java's Vector. It is just plain raw math.
Compared to a dynamic array all a preallocated vector costs you is two pointers worth of memory and in return you get as close to no memory management woes as you are likely to ever see.
Before setting the pointers to NULL, you should delete them first. After every pointer in the column are deleted, you can delete[] the row and set it to NULL, as every element is deleted and gone.
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);