I have this function
void shuffle_array(int* array, const int size){
/* given an array of size size, this is going to randomly
* attribute a number from 0 to size-1 to each of the
* array's elements; the numbers don't repeat */
int i, j, r;
bool in_list;
for(i = 0; i < size; i++){
in_list = 0;
r = mt_lrand() % size; // my RNG function
for(j = 0; j < size; j++)
if(array[j] == r){
in_list = 1;
break;
}
if(!in_list)
array[i] = r;
else
i--;
}
}
When I call this function from
int array[FIXED_SIZE];
shuffle_array(array, FIXED_SIZE);
everything goes all right and I can check the shuffling was according to expected, in a reasonable amount of time -- after all, it's not that big of an array (< 1000 elements).
However, when I call the function from
int *array = new int[dynamic_size];
shuffle_array(array, dynamic_size);
[...]
delete array;
the function loops forever for no apparent reason. I have checked it with debugging tools, and I can't say tell where the failure would be (in part due to my algorithm's reliance on random numbers).
The thing is, it doesn't work... I have tried passing the array as int*& array, I have tried using std::vector<int>&, I have tried to use random_shuffle (but the result for the big project didn't please me).
Why does this behavior happen, and what can I do to solve it?
Your issue is that array is uninitialized in your first example. If you are using Visual Studio debug mode, Each entry in array will be set to all 0xCC (for "created"). This is masking your actual problem (see below).
When you use new int[dynamic_size] the array is initialized to zeros. This then causes your actual bug.
Your actual bug is that you are trying to add a new item only when your array doesn't already contain that item and you are looking through the entire array each time, however if your last element of your array is a valid value already (like 0), your loop will never terminate as it always finds 0 in the array and has already used up all of the other numbers.
To fix this, change your algorithm to only look at the values that you have put in to the array (i.e. up to i).
Change
for(j = 0; j < size; j++)
to
for(j = 0; j < i; j++)
I am going to guess that the problem lies with the way the array is initialized and the line:
r = mt_lrand() % size; // my RNG function
If the dynamically allocated array has been initialized to 0 for some reason, your code will always get stack when filling up the last number of the array.
I can think of the following two ways to overcome that:
You make sure that you initialize array with numbers greater than or equal to size.
int *array = new int[dynamic_size];
for ( int i = 0; i < dynnamic_size; ++i )
array[i] = size;
shuffle_array(array, dynamic_size);
You can allows the random numbers to be between 1 and size instead of between 0 and size-1 in the loop. As a second step, you can subtract 1 from each element of the array.
void shuffle_array(int* array, const int size){
int i, j, r;
bool in_list;
for(i = 0; i < size; i++){
in_list = 0;
// Make r to be betwen 1 and size
r = rand() % size + 1;
for(j = 0; j < size; j++)
if(array[j] == r){
in_list = 1;
break;
}
if(!in_list)
{
array[i] = r;
}
else
i--;
}
// Now decrement the elements of array by 1.
for(i = 0; i < size; i++){
--array[i];
// Debugging output
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
}
You are mixing C code with C++ memory allocation routines of new and delete. Instead stick to pure C and use malloc/free directly.
int *array = malloc(dynamic_size * sizeof(int));
shuffle_array(array, dynamic_size);
[...]
free(array);
On a side note, if you are allocating an array using the new[] operator in C++, use the equivalent delete[] operator to properly free up the memory. Read more here - http://www.cplusplus.com/reference/new/operator%20new[]/
Related
EDIT: I've solved the issue! It had nothing to do with the function itself. I initially used a vector for this function, and the cout statement I used to check the function in main() still called the vector, not the array. A simple mistake, but I appreciate the help!
Hey! I'm currently in college learning data structures, and for our final project, we're tasked with creating multiple sorting algorithms to sort 500,000 randomly generated numbers between 1 - 9,999,999 that have been defined in a text file. I'm currently trying to work on a counting sort, and I keep getting the #include vector line 1553 error 'vector subscript out of range'. I've debugged this function all the way to the last for-loop. Everything seems to work perfectly fine, so I'm assuming it has to do with somewhere in this final piece, but I'd prefer to not have to manually go through 500,000 cycles, so if anyone can see what I've done wrong, I'd like to know.
I also allocated this data on the heap because stack allocation creates a memory overload.
I apologize if this is a low-level question, but I'd love some help, as this project means a lot to me and to my grade. Thank you!
void countingSort(int numberArray[], int SIZE)
{
// Initializer for dynamically-allocated array used to hold the sorted data in the array
int* sortedArray = new int[SIZE];
// Initializes all values in sortedArray to 0
for (int i = 0; i < SIZE; i++)
sortedArray[i] = 0;
// Initializer for variable used to hold the maximum value in the original data
int max = 0;
// Finds the max in numberArray
for (int i = 0; i < SIZE; i++)
{
if (numberArray[i] > max)
max = numberArray[i];
}
// Create an array to store the amount of times each number in numberArray is used
int* countArray = new int[max + 1];
// Initialize all indexes of countArray to 0
for (int i = 0; i <= max; i++)
{
countArray[i] = 0;
}
// When a number is present in numberArray, increase its number of appearances in countArray by one
for (int i = 1; i < SIZE; i++)
countArray[numberArray[i]]++;
// Find the total frequency in the count array
for (int i = 1; i <= max; i++)
countArray[i] += countArray[i - 1];
// Store the sorted values into a sorted array
// Decrease the total count number
for (int i = SIZE - 1; i > 0; i--)
{
sortedArray[countArray[numberArray[i]] - 1] = numberArray[i];
countArray[numberArray[i]]--;
}
// Store the sorted array in the original numberArray
for (int i = 0; i < SIZE; i++)
{
numberArray[i] = sortedArray[i];
}
}
int main()
{
int* SIZE = new int;
*SIZE = 500000;
.
(*code for other functions*)
.
countingSort(numberArray, *SIZE);
cout << "\n" << numberList[0] << "\t" << numberList[499999] << endl;
}
I have this chunk of a program that merges two arrays in one. The matter is that I got this message once the program is compiled:
main.cpp:20:21: error: storage size of ‘cont’ isn’t known
Why does it happen?
Leave my code below:
int * merge(int *array_1, int *array_2, int n1, int n2)
{
static int cont[n1 + n2];
int i = 0, j = 0, k = 0;
while(i < n1 && j < n2)
if(array_1[i] < array_2[j])
cont[ k++ ] = array_1[ i++ ];
else
cont[ k++ ] = array_2[ j++ ];
if(i == n1)
for(int index = j; index < n2; index++)
cont[ k++ ] = array_2[ index ];
else if(j == n2)
for(int index = i; index < n1; index++)
cont[ k++ ] = array_1[ index ];
for(int i = 0; i < k; i++)
printf("%d ", cont[i]);
return cont;
}
In C++ a static array needs to have a size which is known during compile time. If you do not know the size beforehand it is by default a dynamic array independently if it residing on the stack: int my_array[n] or on the heap: int* my_array = new int[n] (The latter is strictly speaking not an array but behaves similar)
So essentially if you want to dynamically create the array you need to drop the static. However given how it is used in your example it will either way not work, because you return the address of a local variable which will be destructed when leaving the scope. Essentially your return value will point into no-mans-lands.
I would suggest to use std::vector instead. Please note that I also adjusted the insert logic and made it a bit easier to read because I had trouble to figure out which order your wanted to achieve when going through your example. Now it is ordered the following way:
values from array1 and and array2 are inserted alternating.
If one array is longer than the other those values are added in the end.
#include <vector>
std::vector<int> merge(int *array_1, int *array_2, int n1, int n2)
{
std::vector<int> v;
int shorter_length = n1 < n2 ? n1 : n2;
for (int i = 0; i < shorter_length; i++) {
v.push_back(array_1[i]);
v.push_back(array_2[i]);
}
for (int j = shorter_length; j < n1; ++j) {
v.push_back(array_1[j]);
}
for (int j = shorter_length; j < n2; ++j) {
v.push_back(array_2[j]);
}
for(auto& element : v)
printf("%d ", element);
return v;
}
You can play around with this example: https://godbolt.org/z/fT6xzo
the initialized static variable will be put in the "data" segment, so the compiler should know how much space should be allocated for it in the executable file.
the uninitialized static variable will be put the "bss" segment, although there will no exactly size of space left for it in the executable file (because data in "bss" segment is all zero, so the compiler can just leave a start address and a size is enough. when the executable file be loaded into memory, the loader will allocate real memory for the "bss" segment according to the start address and the size). the compiler should also know the size of the variable too, only in this way, the compiler can 'tell' this size to loader, so that the loader can know how much memory should be allocated for the "bss" segment when loading the executable into memory.
I have a 2048x2048 matrix of grayscale image,i want to find some points which value are > 0 ,and store its position into an array of 2 columns and n rows (n is also the number of founded points) Here is my algorithm :
int icount;
icount = 0;
for (int i = 0; i < 2048; i++)
{
for (int j = 0; j < 2048; j++)
{
if (iout.at<double>(i, j) > 0)
{
icount++;
temp[icount][1] = i;
temp[icount][2] = j;
}
}
}
I have 2 problems :
temp is an array which the number of rows is unknown 'cause after each loop the number of rows increases ,so how can i define the temp array ? I need the exact number of rows for another implementation later so i can't give some random number for it.
My algorithm above doesn't work,the results is
temp[1][1]=0 , temp[1][2]=0 , temp[2][1]=262 , temp[2][2]=655
which is completely wrong,the right one is :
temp[1][1]=1779 , temp[1][2]=149 , temp[2][1]=1780 , temp[2][2]=149
i got the right result because i implemented it in Matlab, it is
[a,b]=find(iout>0);
How about a std::vector of std::pair:
std::vector<std::pair<int, int>> temp;
Then add (i, j) pairs to it using push_back. No size needed to be known in advance:
temp.push_back(make_pair(i, j));
We'll need to know more about your problem and your code to be able to tell what's wrong with the algorithm.
When you define a variable of pointer type, you need to allocate memory and have the pointer point to that memory address. In your case, you have a multidimensional pointer so it requires multiple allocations. For example:
int **temp = new int *[100]; // This means you have room for 100 arrays (in the 2nd dimension)
int icount = 0;
for(int i = 0; i < 2048; i++) {
for(int j = 0; j < 2048; j++) {
if(iout.at<double>(i, j) > 0) {
temp[icount] = new int[2]; // only 2 variables needed at this dimension
temp[icount][1] = i;
temp[icount][2] = j;
icount++;
}
}
}
This will work for you, but it's only good if you know for sure you're not going to need any more than the pre-allocated array size (100 in this example). If you know exactly how much you need, this method is ok. If you know the maximum possible, it's also ok, but could be wasteful. If you have no idea what size you need in the first dimension, you have to use a dynamic collection, for example std::vector as suggested by IVlad. In case you do use the method I suggested, don't forget to free the allocated memory using delete []temp[i]; and delete []temp;
I am currently writing a program for a class that takes user input to either add or remove a number from a dynamic array, and then print all the values of the array in ascending order.
From what I have already researched, all I need to do to get the value of the element in the array to print is to ensure the dereference operator is inserted next to the pointer name. However, when done as below (newArray[i]) I get a compile-time error saying that the operand to the right of the '' must be a pointer, even though newArray is declared as pointer at the beginning of the function.
void output(int *arrayPtr, int size){
int small;
int i, j;
int *newArray;
newArray = new int[size];
for (i = 0; i < size; i++){
*newArray[i] = arrayPtr[i];
}
for (i = 0; i < size; i++){
small = *newArray[i];
for (j = 0; j < size; j++){
if (*newArray[j] < small){
*newArray[j] = small;
}
std::cout << small;
}
int number = small;
removeNumber(*& arrayPtr, number, size);
}
}
I feel like there is something totally obvious I am missing, but I would greatly appreciate any help or ideas!!
small = *newArray[i];
That should just be:
small = newArray[i];
(Same thing in the other places you compare/assign *newArray[i]
What your first operation is doing is first dereferencing newArray, which means it gets the value of the first element in the array, and then attempting to index that. The element is not a pointer, so this of course fails. When you index, it also implicitly dereferences the pointer. You could also write:
small = *(newArray + i);
However, generally you only use pointer arithmetic when you need the actual pointer, since indexing is easier to read if you need the value.
Going through your code, a few other things seem off:
for (i = 0; i < size; i++){
*newArray[i] = arrayPtr[i];
}
This might compile but I don't think it is right, I'm guessing you mean:
for (i = 0; i < size; i++){
newArray[i] = arrayPtr[i];
}
Also:
removeNumber(*& arrayPtr, number, size);
While this is technically correct, *& first returns a pointer reference, then turns around and dereferences it again. I wouldn't be surprised if the compiler optimizes it away anyway, but it is unnecessary.
I'm trying to fill an array with numbers 1111 to 8888, with each integer in the number being between 1 and 8 in c++. However, when I run it, it's only outputting large negative numbers indicating an error. I honestly have clue what the error is so it would be appreciated if you could help me out. Thanks!
int fillArray()
{
int arrayPosition;
int guesses[4096];
arrayPosition = 0;
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses[arrayPosition] = ((i * 1000) + (j * 100) + (k *10) + m);
cout << guesses[arrayPosition];
arrayPosition++;
}
return guesses[4096];
}
Your return type is wrong. int fillArray(), but you're trying to return an int[4096] that was declared on the stack... What you're actually doing with return guesses[4096]; is returning the first memory location after your array in memory, which is probably just garbage, hence your issue with large negative numbers.
You can fix it by allocating your array in the heap, and returning a pointer to the start of that array:
int * fillArray()
{
int arrayPosition;
int * guesses = new int[4096];
// other stuff stays the same...
return guesses;
}
However, since your function is called fillArray, it would make more sense to pass in an array and fill it rather than creating the array in the function. (If you wanted to do that, might call it something like make_1_to_8_array instead, to make it more clear that you're constructing something that will need to be deleted later.) Giving an int* as the first argument would allow you to pass in the base address of your array that you want filled:
void fillArray(int * guesses)
{
int arrayPosition;
// other stuff stays the same...
}
Or, if you want to verify that the you're using an array of the exact size:
void fillArray(int (&guesses)[4096])
{
int arrayPosition;
// other stuff stays the same...
}
Note that the function now returns void since you just update the array that was passed in, and you don't need to return anything new.
Your for-loops look correct, but your array handling is off, as is highlighted by other answers.
It is more usual in C++ to use std::vector and to pass this in by reference as an argument. This saves you having to handle memory allocations and deallocations. Here's an example, including the output in the for-loops:
#include <iostream>
#include <vector>
int fillArray(std::vector<int>& guesses)
{
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses.push_back((i * 1000) + (j * 100) + (k * 10) + m);
std::cout << guesses.back() << std::endl;
}
return guesses.back();
}
int main()
{
std::vector<int> guesses;
std::cout << fillArray(guesses) << std::endl;
}
You are creating your array locally then attempting to return it. If you try printing (to debug) out the result of your array prior to returning, you will see it is ok. However, once you return, the array is no linger valid. Try passing in an array into your function instead.