Can't initialize array with pre-defined variable int - c++

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.

Related

Variable not initialized with a constant expression

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

Can I use memset to initialize a 2 dimensional array?

According to the C standard (SO link 1 and link 2) we cannot access an element of a row using out-of-bounds index:
int x[10][10] = ...; // initialize x
int q = x[0][10]; // This is an out-of-bounds access
Then is it valid to initialize the array using the following loop?
int *p = &x[0][0];
for (int i = 0; i < 100; ++i)
p[i] = 0;
If this is not valid, then is it valid to initialize x using memset(&x[0][0], 0, sizeof(x))?
int *p = &x[0][0];
memset(p, 0, sizeof(x))?
edit:
I wonder whether the answers are different in C++ as well..! :)
The loop is not valid, see the comments by #EricPostpischil .
Yes, the memset approach is valid too. But it is not preferred solution. It operates on individual bytes so it can only ever be reasonably used for zeroing the memory.
C++
Value initialization T array[10][10] = {}; zeroes the array of primitives types, calls default constructors for classes.
std::fill(p,p+100,value) for assigning a specific value.
There is not standard way how to initialize an array to non-zero values without listing them.
std::array<T,N> is the preferred way for arrays of known size.
C
cppreference
There is no special construct in C corresponding to value initialization in C++; however, = {0} (or (T){0} in compound literals) (since C99) can be used instead, as the C standard does not allow empty structs, empty unions, or arrays of zero length.
So, in case of nested arrays, use T array[10][10] = {{0}};.
You asked in title:
Can I use memset to initialize a 2 dimensional array?
Yes, as memset(...) only cares about byte count, you could use it like:
int x[10][10];
memset(&x, 0, sizeof(x));
But in C++, an empty initializer-list would do same, like:
int x[10][10] = {};
And in C since C99 (as mentioned in comments), we clould do instead:
int x[10][10] = {{0}};
Anyway, you say:
int q = x[0][10]; // This is an out-of-bounds access
Then asked is following valid:
int *p = &x[0][0];
for (int i = 0; i < 100; ++i)
p[i] = 0;
Well yes, but only because you do something as simple as setting to zero, a more complex logic could require you to loop 2 dimensionally, like:
for (int x = 0; x < 10; ++x) {
for (int y = 0; y < 10; ++y) {
myArray[x][y] = something_more_complex_here;
}
}

for Loops in C++ with Arrays and Pointers

My teacher introduced us to looping through an array in the following format:
int size;
cin >> size;
int *garbage = new int[size];
for (int* p = garbage; p < (garbage + size); p++) {
if (*p > *max) {
max = p;
}
}
I understand what's going on, but it's just odd to me as a new concept. Are there better ways of going through an array like this?
Second Question: do you have to turn every pointer to a nullptr once you are done with it? For example, does it cause memory leaks to have that for loop like that with the pointer p or does it self destruct once it leaves the for loop scope?
There certainly are better (as in - more readable) ways of iterating through an array. For instance:
for (int index = 0; index < size; index++) {
if (p[index] > *max) {
max = &p[index];
}
}
However, as you see in the max = ... assignment, it's easier to have a pointer to an element of an array if you want to pass it on to another pointer variable.
Regarding your second question - there is no inherent value in setting it to nullptr. However, to prevent memory leaks, you should deallocate (free) the memory you reserved with operator new by using the operator delete once you're done with the array, like so:
delete [] p;
EDIT: Please note that you won't be able to safely dereference the pointer max (meaning you can't read that int it's pointing to with *max expression) after you deallocate the array without causing Undefined Behavior and possibly crashing your program, because your program will return the reserved memory to the OS and won't have access to it.
Thanks to #user4581301 for pointing it out.
There's another way of solving the problem. There's a C++ standard library algorithm for finding the maximum element in a range: std::max_element. No hand-written loop is needed.
int max = *std::max_element(garbage, garbage + size);
Note that it returns an iterator (a pointer in this case) so I used * to get the value from the iterator.
Your teacher might not like this solution.
It's a bit cleaner to do this:
int size = 10, max = 0;
int *mem = new int[size];
int *end = mem + size;
for (int *p = mem; p < end; p++)
if (*p > max)
max = *p;
But if you start using C++11 you can do this:
int max = 0;
std::vector<int> mem;
for (auto &i : mem)
if (i > max)
max = i;
There are probably even easier ways using other std namespace tools.
do you have to turn every pointer to a nullptr once you are done with it?
No, but it helps a lot when debugging. If you use a freed pointer that wasn't set to nullptr you'll be a lot more confused than if it is nullptr. Setting the pointer to nullptr doesn't actually automatically free the memory. You still have to call the appropriate 'free' function before setting to nullptr.
in C++11 you can do this:
int max = 0;
std::vector<int> mem;
for (auto &i : mem)
if (i > max)
max = i;

Initialize two 2-d array to zero in C/C++

My question is can we initialize 2-d array using int a[10][10] = {{0}}.
According to the top answer in initialize-large-two-dimensional-array-in-c,
int array [ROW][COLUMN] = {0};
which means: "initialize the very first column in the first row to 0, and all other items as if they had static storage duration, ie set them to zero."
However, checking C99 Standard 9899:TC3 and C++11 Standard N4296, I haven't found any official records supporting what was mentioned in this answer.
Besides, I do come across this issue when I try to solve the LeetCode 474. Ones and Zeroes problem with the following solution.
// To make question clear:
// It seems that "int dp[m + 1][n + 1] = {{0}}" cannot initilize all elem to 0
// "memset(dp, 0, sizeof dp)" is necessary to pass the OJ test. Any idea?
class Solution {
public:
// m : 0s, n : 1s
int findMaxForm(vector<string>& strs, int m, int n) {
int dp[m + 1][n + 1] = {{0}};
// We will get "Wrong Answer" without memset() function below
memset(dp, 0, sizeof dp);
for (auto& str : strs) {
auto cost = getCost(str);
for (int i = 0; i + cost.first <= m; ++i)
for (int j = 0; j + cost.second <= n; ++j)
dp[i][j] = std::max(dp[i + cost.first][j + cost.second] + 1,
dp[i][j]);
}
int max = 0;
for (int i = 0; i <= m; ++i)
for (int j = 0; j <= n; ++j)
max = std::max(max, dp[i][j]);
return max;
}
private:
pair<int, int> getCost(const string& str) const {
int cnts[] = {0, 0};
for (char c : str) ++cnts[static_cast<char>(c == '1')];
return {cnts[0], cnts[1]};
}
};
Your code is C++ code. Other questions and documents about C are irrelevant; C and C++ are different languages.
In Standard C++ , array dimensions must be known at compile-time. int dp[m + 1][n + 1] is an error (let alone trying to initialize it).
Possibly you're using a compiler that offers C++ VLA as a non-standard extension. In that case you are at the mercy of the particular compiler as to what the behaviour of the code will be, and what the behaviour of ={{0}} on it might be. The C++ standard will not help.
My advice would be to avoid non-standard constructs, so that you retain the guarantees provided by the standards documents.

Initializing a multi dimensional array in C++

I recently started programming in C++, I have quite some experience in JAVA programming but I am facing a rather unclear situations whilst trying to initialize multi dimensional arrays in c++.
The code I would use in java would be something like:
int x = 5;
int y = 10;
int array [][] = new int[x][y];
which works fine, I could assign any value to x and y using a scanner or option pane. However (and please bear with me, I am quite new to c++) in c++ I am required to use constants which prevent me from using for example:
int x;
cin >> x;
int y;
cin >> y;
int array [][] = new int[x][y];
I am trying to make a random map generator, eventually i will assign 3d object to positions within the array and design an algorithm to sort all of the objects. However I want the user to be able to specify the size of the grid, specify x and y, the rows and columns.
Any help would be greatly appreciated!
Many thanks in advance.
This record
int array [][] = new int[x][y];
is invalid in C++. If you want to allocate an array in the heap using operator new and the right dimension is not a constant expression then you should write
int x;
cin >> x;
int y;
cin >> y;
int **array = new int *[x];
for ( int i = 0; i < x; i++ ) array[i] = new int[y];
If the right dimension is set by a constant expression then you can write
int x;
cin >> x;
const int y = SomeValue;
int ( *array )[y] = new int [x][y];
Take into account that you could use standard container std::vector instead of a manually allocated array.
For example
std::vector<std::vector<int>> v( x, std::vector<int>( y ) );
There are multiple ways to do this. To create a permanent array on the heap:
int** data = new int*[x];
for(int i = 0; i < x;i++)
{
data[i] = new int[y];
}
To create an array of fixed size on the stack:
int data[5][5];
The dimensions of the array must be known at compile time.
For me this simple code fails to compile due to lack of knowledge of the array size.
int i = 5;
int arr [] = new int[i];
arr[2] = 2;
If you want to use arrays you have two choices, use constants that are known at compile time, or create the array using malloc to reserve memory.
If you are able to use the STL use the vector class.
int i = 5;
vector<int> vec(i);
vec[2] = 2;
Or you could use pointers as shown in 'Vlad from Moscow' or 'user3482801' answers.