Variable not initialized with a constant expression - c++

I'm a novice programmer who is learning C++.
Below are the relevant parts of my code. VSCode throws an error 'size' not initialized with a constant expression, and I'm unclear about the underlying error(s) in which I'm making.
int min, max;
min = max = 0;
for(int i=0;i<a.size();i++){
if(a[i]/int(pow(10,exp))%10>max) max = a[i];
if(a[i]/int(pow(10,exp))%10<min) min = a[i];
}
return std::array<int,2> {min,max};
}
std::vector<int> radixSort(std::vector<int> a){
int xp,maxval;
xp = maxval = 0;
int xpv = pow(10, xp);
for(int i=0;i<a.size();i++){
if(a[i]>maxval) maxval = a[i];
}
while(maxval/pow(10/xp) != 0){
std::array<int, 2> rg = findRange(a,xp);
int min = rg[0];
int size = rg[1]-rg[0]+1; //error at rg[1]: attempt to access storage one position past the end of an array of 1 elements
std::array<int,size> count;// Variable size cannot be used as constant
...
I'd like to clarify a few details:
I've returned an array size 2 with 2 elements {max,min} from my function findRange. So why is it that the compiler only interprets it as one? Changing the function return type to std::vector doesn't seem to fix the problem.
I realized that array sizes need to be fixed at compile time, but when I put const or constexpr infront of a size variable it doesn't fix the problem.
Feel free to point out any other mistakes in my code. Thanks!
EDIT: Changed int i to int i=0 in the first for loop

it is just because of array of size 2 with 2 elements try it with inheritance concept

Related

Why is there an error in my integer array after declaring an integer in my main function?

I am trying out some codes that is based on finding all possible combinations that add up to a integer's value that is declared in the main function. However, the problem is when I call the function "findCombinations(n);", it gives an error at "int arr[n];". That is the only line which has an error which is stopping me from running the program. If you know of a solution, do let me know.
#include <iostream>
using namespace std;
void findCombinationsUtil(int arr[], int index,
int num, int reducedNum)
{
// Base condition
if (reducedNum < 0)
return;
// If combination is found, print it
if (reducedNum == 0)
{
for (int i = 0; i < index; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// Find the previous number stored in arr[]
// It helps in maintaining increasing order
int prev = (index == 0) ? 1 : arr[index - 1];
// note loop starts from previous number
// i.e. at array location index - 1
for (int k = prev; k <= num; k++)
{
// next element of array is k
arr[index] = k;
// call recursively with reduced number
findCombinationsUtil(arr, index + 1, num,
reducedNum - k);
}
}
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
int arr[n];
//find all combinations
findCombinationsUtil(arr, 0, n, n);
}
int main()
{
int n = 10;
findCombinations(n);
return 0;
}
C-style array dimensions must be known at compile-time in Standard C++.
You can make n be a compile-time function parameter like this:
template<int n>
void findCombinations()
{
// array to store the combinations
// It can contain max n elements
int arr[n];
//find all combinations
findCombinationsUtil(arr, 0, n, n);
}
int main()
{
const int n = 10;
findCombinations<n>();
return 0;
}
From http://www.cplusplus.com/doc/tutorial/arrays/:
NOTE: The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.
While some compilers will allow it, you should avoid dynamic size arrays.
Here are a few options:
If the size of the array will always be 10, initiate it to hard-coded const 10.
Use std::shared_ptr to an array pointer:
std::shared_ptr pArray;
pArray=std::make_shared(n)
Use std::vector to dynamically allocate the size. (IMHO this is the preferred option).
use c-style pointers (IMHO should only be used as last resort)
Template class (wasteful, as it created and compiles many instances of the same function)
Type of variable arr must be known at compile time. If you need storage of variable size, you have to allocate it.
Possible alternative (one of many)
#include <vector>
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
std::vector<int> arr(n); // allocate n elements
//find all combinations
findCombinationsUtil( &*arr.begin(), 0, n, n);
}
if compiler at least partially complies to C++11 e.g. it's late gcc 4.6 or higher or VS2010 and higher, then there is method data() that returns pointer to internal storage. But better to rewrite, templatize or overload findCombinationsUtil to use a container or iterator

Implementing own realloc [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I would like to change the size of array when it exceed its limit. I have created a function for that.
void AddElemenet( int i , int value){
if( i > index - 1){
int tmp = index;
double *new_arr;
while( i > tmp){
tmp*=2
}
new_arr = new double[tmp]();
for( int j = 0; j < index ; j++){
new_arr[j] = arr[j];
}
index = tmp;
delete[] arr;
arr = new_arr;
}
arr[i] = value;
}
index refers to the max size of an array ; and arr is dynamicly allocated array using new itself.
The problem is , that i am assigning arr to a local variable that get destroyed. I tried assignign it as refference or pointer using *arr=*new_arr
but nothing worked so far. How can i change the array using this local variable?
The various bugs in your implementation demonstrate why it is almost always a good idea to use the standard library. It would be very simple to adapt std::vector to this interface.
The essence of your problem is the confusion over what index means. (That's a terrible name for a member variable. It says nothing. Index of what? And actually, it's not an index; it's the size of the array. At least, that's what it should be.)
Suppose that your array has 4 elements, so index is 4 (based on the assumption that it is the size of the array). Now you want to AddElement(4, 42);. The condition in if( i > index - 1) is certainly true: i is 4, and index - 1 is 3. So the reallocation block will be entered. However, the first thing you do is tmp = index; while( i > tmp) tmp *= 2;. i is not greater than tmp -- both of them are 4 -- so the loop will never run and tmp will still be 4. Now you allocate a new array with four elements, copy the existing four elements to it, "update" index to 4 (its current value), and delete the old array. Right afterwards, you attempt to set the element with index 4 to 42. But the array only has four elements, so that is Undefined Behaviour.
Since you have not actually changed the size of the array, or the value of index which indicates its size, your later attempt to print the values of the array will stop at its actual size, ignoring the value you modified outside the storage area of the array (which may belong to some other datastructure, so its value is meaningless anyway.)
If you rename index as size and tmp as new_size, the code is much clearer, and the fix is also clear:
if (i >= size) {
size_t new_size = size;
while (i >= new_size) new_size *= 2; /* NOT > */
double* new_array = new double[new_size]();
for (size_t j = 0; j < size; ++j) new_array[j] = array[j];
array = new_array;
size = new_size;
}
array[i] = value;
This would all have been much simpler and less error-prone if you used a std::vector:
class MyVector {
public:
void AddElement(size_t i, double value) {
if (i >= data_.size()) data_.resize(i + 1);
data_[i] = value;
}
/* Many implementation details omitted */
private:
std::vector<double> data_;
}
std::vector <int> list;
void AddElemenet(int value)
{
list.push_back (value);
}
Just use vector's. Array's size is fixed. Vector's size is dynamic.

C++ passing array by value causing segment fault

Hey everyone I am relearning C++ by doing some hacker rank challenges and am getting a segment fault error. The program should take in the dimensions for the matrix and compute both diagonals, then add them together. I am pretty sure the error is in how the 2d array is passed to the computeMainDiagonal and computeSecondaryDiagonal functions. Thanks for the help !
int ComputeMatrixMainDiagonal(int matrixDimensions, int* matrix){
int rowIndent = 0;
int diagonalValue;
for(int i = 0;i < matrixDimensions;i++){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent++;
}
return diagonalValue;
}
int ComputeMatrixSecondaryDiagonal(int matrixDimensions, int* matrix){
int rowIndent = matrixDimensions;
int diagonalValue;
for(int i = matrixDimensions;i > 0;i--){
diagonalValue =+ (&matrix)[i][rowIndent];
rowIndent--;
}
return diagonalValue;
}
int main() {
int matrixDimension;
int differenceAcrossSumsOfDiagonal;
int matrixMainDiagonal;
int matrixSecondaryDiagonal;
int * matrixPointer;
cin >> matrixDimension; //get matrix dimensions
int matrix[matrixDimension][matrixDimension]; //declare new matrix
for(int index = 0; index < matrixDimension;index++ ){ //populate matrix
for(int i = 0; i < matrixDimension;i++){
cin >> matrix[index][i];
}
}
matrixMainDiagonal = ComputeMatrixMainDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
matrixSecondaryDiagonal = ComputeMatrixSecondaryDiagonal(matrixDimension,&matrix[matrixDimension][matrixDimension]);
differenceAcrossSumsOfDiagonal = (matrixMainDiagonal + matrixSecondaryDiagonal);
cout << differenceAcrossSumsOfDiagonal;
return 0;
}
Your segmentation fault likely occurs because &matrix[matrixDimension][matrixDimension] does not mean what you think it means. Your question title suggests that you think this is a way to pass the array by value (though why you would want to do so escapes me), but pass-by-value vs. pass-by-reference is a matter of how the function is declared, not of how it is called.
The expression &matrix[matrixDimension][matrixDimension] would be the address of the matrixDimensionth element of the matrixDimensionth row of the matrix. This is outside the bounds of the matrix, as the maximum index for an array is one less than the array dimension. Even if you wrote &matrix[matrixDimension - 1][matrixDimension - 1], however, it would not be what you want. You want the address of the first element of the array, which is &matrix[0][0] or simply matrix, though these are inequivalent on account of having different type (corresponding to different senses of what the elements of matrix are).

Can't initialize array with pre-defined variable int

int shifts[c] = {0};
The c is defined. Error: shifts maybe not be initialized. Why? What am I doing wrong here? I think it has something to do with c, but I am not sure. If I can't use the current declaration, how do I get around it? I tried it with vectors first:
vector<bool> shifts(c, false)
But, it didn't work. Had bad_alloc error.
int max = 0, min = 10000;
for (int i = 0; i != 2*no_shifts; ++i) {
int x;
fin >> x;
time.push_back(x);
if (max < x)
max = x;
if (min > x)
min = x;
}
c = max - min + 1;
Based solely on c = max - min + 1; it seems that you are trying statically initialize an array without a compile time constant. Either use a dynamically allocated array or std::vector if you need something that can have it's size determined at runtime.
Edit: You may actually want to consider using std::bitset instead as an alternative container.

C++ two dimensional arrays with pointers

I have a problem with two dimensional arrays :( I feel very stupid and Visual C does not help me :( and I also think that my mistake is very stupid but still I can't find it :( I have this code:
double matrix[100][100]; //which is full with a matrix 3x4
double nVector[10000]; // for negative doubles
//I wanted to see if there are negative doubles in each row and column
//and I want this to happen with function
And this is my function:
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*(*(myMatrix+i)) < 0){
*(myNegArray+position) = *(*(myMatrix+i));
position++;
}
return myNegArray;
}
//for double*nVector I'm passing nVector
//for double*fromVector I'm passing *matrix
Visual C tells me that I have an error C2100: illegal indirection here: *(*(myMatrix+i)) I hope someone can help me (happy)
Thanks in advance!
*(*(myMatrix+i)) is wrong. This is a common mistake.
2D matrix does not create an array of pointers which you can access this way. It is a different structure. Even though an array is a pointer, 2D array is not a pointer to pointer, and it cannot be dereferrenced twice. Nor you have any other way to access element at coordinates (x,y) without knowing the layout in memory, because pointers to every line are nowhere to be found. For instance, char **argv parameter of main() is not a 2D array. This is an array of pointers to arrays, which is something else.
There're two ways to fix it.
One is replace
double *myMatrix = fromVector;
by
double *myMatrix[100] = (appropriate cast)fromVector;
and index it as myMatrix[i/n][i%n]
But then remember that 100 is a constant expression, and it cannot be passed as a parameter. Alternatively, you can implement the indexing operation yourself:
Pass additional parameter: matrix line size (100)
Instead of *(*(myMatrix+i)), write:
int row = i/n;
int col = i%n;
*(myMatrix+row*line_size+col) is your element.
first you might wanna start a small struct like
struct tmp {
bool negative;
double value;
};
and make your own way up to the
tmp *myvars [100][100];
.
instead try using that struct and try the std::vectors instead of arrays if that's possible then try using pointers on decalring the variable "1 time only" when declaring the variable as i said above
then pass arguments
( tmp *mystructpointer )
mystructpointer->.......
access your matrix directly ... peice of cake :D
If you are passing *matrix, you are actually passing a double[100] (an array of 100 doubles), that happens to be passed as a pointer to its first element. If you advance further than those 100 doubles using i added to that pointer, you advance into the next array of 100 doubles, since the 100 arrays of 100 doubles are stored next to each other.
Background: A multi-dimensional array is an array whose element type is itself an array. An array like double a[100][100]; can be declared equivalently as typedef double aT[100]; aT a[100];. If you use an array like a pointer, a temporary pointer is created to the array's first element (which might be an array). The * operator is such an operation, and doing *a creates a pointer of type double(*)[100] (which is a pointer to an array of 100 doubles), and dereferences it. So what you end up with *matrix is a double[100]. Passing it to the negativeVector function will create a pointer to its first element, which is of type double*.
Your pointer parameters point to the start of each of two arrays of 100 doubles each. So you should rewrite the function as
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*(myMatrix + i) < 0){
*(myNegArray + position) = *(myMatrix + i);
position++;
}
return myNegArray;
}
Notice that since your i iterates beyond the first of the 100 arrays stored in the 2d array, you will formally not be correct with this. But as it happens those arrays must be allocated next to each other, it will work in practice (and in fact, is recommended as a good enough work around for passing multi-dimensional arrays around as pointers to their first scalar element).
I have no clue why you are copying the arrays twice (once in the parameters of the function and a second time by declaring some new arrays)... You should also think of using the STL... std::vector will make the your life way easier ;)
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*((myMatrix+i)) < 0){
*(myNegArray+position) = *((myMatrix+i));
position++;
}
return myNegArray;
}
is that homework? some templates - just for fun ;-)
double matrix[100][100];
double nVector[10000];
template< const int m, const int n >
double* negativeVector( double* myNegArray, const double (&myMatrix)[m][n] )
{
int position = 0;
for( int i = 0; i < m; ++i )
{
for( int j = 0; j < n; ++j )
{
const double value = myMatrix[ i ][ j ];
if ( value < 0 )
{
myNegArray[ position ] = value;
++position;
}
}
}
return myNegArray;
}
int main()
{
//...initialize matrix here...
negativeVector( nVector, matrix );
}
Perhaps rewrite this using std::vector to increase readability? (#):
#include <vector>
std::vector< std::vector<double> > matrix; //which is full with a matrix 3x4
std::vector<double> row;
row.resize(100,0);
matrix.resize(100,row);
std::vector<double> nVector; // for negative doubles, no size, we'll "push_back"
//I wanted to see if there are negative doubles in each row and column
//and I want this to happen with function
This is the stl enabled version of the function:
//I'm returning void because nvector contains the result,
//so I don't feel the need to return anything. vectors contain their
//own size so n and m are also not needed. Alsom pass in references
void negativeVector(std::vector<double>& nVector,
std::vector< std::vector<double> >& fromVector){
nVector.clear();
int i,j;
for(i = 0; i < fromVector.size(); i++) {
for(j = 0; j < fromVector[i].size(); j++) {
if(fromVector[i][j] < 0){
nVector.push_back(fromVector[i][j]);
}
}
}
}
call with:
negativeVector(nVector, matrix);
Once the function completes, nVector contains all negative numbers in matrix.
Read more about std::vector here.
(#) for people like me who are too lazy/stupid to comprehend code containing pointers.
Take a look at C++ Faq site:
How do I allocate multidimensional arrays using new?
link
And read until point [16.20] summarize all the answers you are getting and at the end you get a very useful Matrix template class.
Have a good read.