set all elements of 2-D array to zero [duplicate] - c++

This question already has answers here:
Fill multidimensional array elements with 0's
(12 answers)
Closed 6 years ago.
int a[100][100]; //globally declared array
int main()
{
while(testcases--)
{
a[100][100]={0};
//rest of code
}
return 0;
}
This code works only for first testcase. For next testcases, it doesn't set the elements to zero.
I can't afford to run a loop to run a loop and iterate all the elements.
I want to perform this task in O(1). Is it possible?

You are using the same array between runs and you want to reset it to zero. You cannot avoid iterating on all the cells and setting them to zero.
Even when initializing to zero on decleration, there's no such thing as promising O(1). The way the compiler initializes is up to the compiler.

First, you seem to have a slight misunderstanding of terms.
This is an initialization:
int a = b;
This is an assignment:
int a;
a = b;
You can initialize an array to zeroes using following code:
int array[10][20] = {0};
Or:
int array[10][20] = {};
Or:
int array[10][20] {};
Keep in mind that global (and static) arrays are zero-initialized by default.
You can fill array with zeroes after it was created like this:
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
array[i][j] = 0;
Or:
for (int (&a)[100] : array) // or for (auto &a : array)
for (int &b : a) // or for (auto &b : a)
b = 0;
Or:
std::memset(array, 0, sizeof array);
P.S.
You can't fill an array with zeroes at runtime for O(1).

Your array is zero-initialized "for the first testcase" simply because it is declared with static storage duration. And such array with static storage duration begins its life zero-initialized.
Your
a[100][100]={0};
line has nothing to with it. This is actually a mere a[100][100] = 0, which is writing a single 0 into a non-existing (out of bounds) element of your array. (The behavior is undefined).
If you wan to reinitialize your array with zeros on each iteration, you have to do it either manually or using a library-level solution, since there is no core-language-level feature that would do it for you. In your case (an array of integers) you can even use the old-fashioned
std::memset(a, 0, sizeof a);
You can also use something clever-but-inefficient like
decltype(a) zeros{};
std::swap(a, zeros);
on each iteration, but it's probably not worth it.

Related

Dynamic array of Linear search funcion implementation

Need to implement a function
int* linearSearch(int* array, int num);
That gets a fixed size array of integers with a number and return an array with indices to the occurrences of the searched number.
For example array={3,4,5,3,6,8,7,8,3,5} & num=5 will return occArray={2,9}.
I've implemented it in c++ with a main function to check the output
#include <iostream>
using namespace std;
int* linearSearch(int* array, int num);
int main()
{
int array[] = {3,4,5,3,6,8,7,8,3,5}, num=5;
int* occArray = linearSearch(array, num);
int i = sizeof(occArray)/sizeof(occArray[0]);
while (i>0) {
std::cout<<occArray[i]<<" ";
i--;
}
}
int* linearSearch(int* array, int num)
{
int *occArray= new int[];
for (int i = 0,j = 0; i < sizeof(array) / sizeof(array[0]); i++) {
if (array[i] == num) {
occArray[j] = i;
j++;
}
}
return occArray;
}
I think the logic is fine but I have a syntax problems with creating a dynamic cell for occArray
Also a neater implantation with std::vector will be welcomed
Thank You
At very first I join in the std::vector recommendation in the question's comments (pass it as const reference to avoid unnecessary copy!), that solves all of your issues:
std::vector<size_t> linearSearch(std::vector<int> const& array, int value)
{
std::vector<size_t> occurrences;
// to prevent unnecessary re-allocations, which are expensive,
// one should reserve sufficient space in advance
occurrences.reserve(array.size());
// if you expect only few occurrences you might reserve a bit less,
// maybe half or quarter of array's size, then in general you use
// less memory but in few cases you still re-allocate
for(auto i = array.begin(); i != array.end(); ++i)
{
if(*i == value)
{
// as using iterators, need to calculate the distance:
occurrences.push_back(i - array.begin());
}
}
return occurences;
}
Alternatively you could iterate with a size_t i variable from 0 to array.size(), compare array[i] == value and push_back(i); – that's equivalent, so select whichever you like better...
If you cannot use std::vector for whatever reason you need to be aware of a few issues:
You indeed can get the length of an array by sizeof(array)/sizeof(*array) – but that only works as long as you have direct access to that array. In most other cases (including passing them to functions) arrays decay to pointers and these do not retain any size information, thus this trick won't work any more, you'd always get sizeOfPointer/sizeOfUnderlyingType, on typical modern 64-bit hardware that would be 8/4 = 2 for int* – no matter how long the array originally was.
So you need to pass the size of the array in an additional parameter, e.g.:
size_t* linearSearch
(
int* array,
size_t number, // of elements in the array
int value // to search for
);
Similarly you need to return the number of occurrences of the searched value by some means. There are several options for:
Turn num into a reference (size_t& num), then you can modify it inside the function and the change gets visible outside. Usage of the function get's a bit inconvenient, though, as you need to explicitly define a variable for:
size_t num = sizeof(array)/sizeof(*array);
auto occurrences = linearSearch(array, num, 7);
Append a sentinel value to the array, which might be the array size or probably better maximum value for size_t – with all the disadvantages you have with C strings as well (mainly having to iterate over the result array to detect the number of occurences).
Prepend the number of occurrences to the array – somehow ugly as well as you mix different kind of information into one and the same array.
Return result pointer and size in a custom struct of yours or in e.g. a std::pair<size_t, size_t*>. You could even use that in a structured binding expression when calling the function:
auto [num, occurences] = linearSearch(array, sizeof(array)/sizeof(*array), 7);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// here the trick yet works provided the array is declared above the call, too,
// as is in your example
Option 4 would be my personal recommendation out of these.
Side note: I switched to size_t for return values as negative indices into an array are meaningless anyway (unless you intend to use these as sentinel values, e. g. -1 for end of occurrences in option 2).

How do I use the for-each loop to scan through an int array object? [duplicate]

This question already has answers here:
Range-based for loop on a dynamic array?
(6 answers)
Closed 6 years ago.
if I create a new int array object using new like below:
int *array = new int[20];
and fill the array with some integers, then attempting to scan through that array with a for-each loop will throw me an error:
for (int x : array) // error
why does this happen and how can I fix it? I tried playing around with the referencer and address notations (* and &) but every combination I tried fails.
ex.
for (int &x : *array) // does not work either.
array is not an array, but a pointer, which can't be used for Range-based for loop, because there's no information about the size of the "array", the begin and end of the "array" can't be deduced.
range_expression - any expression that represents a suitable
sequence (either an array or an object for which begin and end member
functions or free functions are defined, see below) or a
braced-init-list.
You might make it real array, (or use std::array instead of the raw array)
int array[20];
for (int x : array) { processing with x... }
Or write the loop manually:
for (int i = 0; i < 20; i++) { processing with array[i]... }
in for (int x : array), it requires that begin(array) and end(array) are valid. which is not for int*.
it would work for int array[20], std::vector, std::array<int, 20>.

Dynamic memory allocation...how about this type of inititlization?

To create an integer on heap and initialize it to a value 5, we do:
int* a = new int(5);
To create an array of 5 integers on the heap, we do:
int* a = new int[5];
But, if we want to create an array of 5 integers and initialize each of them to 10 in one single instruction, is it possible?
To make things more interesting, let us say that the array size will only be known at run time. How about then?
Also, I know this is a very trivial question, but I'm making this transition from Java and get confused at times with C++, so... if not initialized during declaration, then unlike in Java, C++ primitive data types are not initialized with default values, and contain garbage values, right?
But someone told me that if they are declared as global variables, then they are initialized to default values like in Java...is that true as well? Why?
I prefer:
std::vector<int> a = {10,10,10,10,10};
C++ is a very complex language, with many different (even contradicting) goals.
One of the ideas behind it was that you should not pay in efficiency what you don't need and this is what is behind the concept of uninitialized values.
When you write
int x;
the variable x is initialized if it's at global/namespace scope and instead is not initialized when the definition is in a local scope.
This happens not because who designed C is crazy (of course an initialized value is better) but because initialization at global/namespace scope is free from an efficiency point of view as it's done compile/link/loading time, not at runtime.
Initializing a variable in local scope instead has a cost (small, but non-zero) and C++ inherited from C the idea that shouldn't pay for it if you don't need it, thus if you want your variable initialized to any value simply says so with:
int x = 42;
Note however that an uninitialized variable is not simply "containing a garbage value", it's uninitialized and you are not allowed to read its content as such an operation is "undefined behavior".
There are platforms in which just reading the content of an uninitialized variable may crash ("trap representations": for example hardware with dedicated registers for pointers in which just placing an invalid address in a register - not doing anything with it - provokes an hardware exception).
No, it is not possible to allocate an array with new[] and specify an initial value for the array elements. You have to fill in the array after the allocation is finished, eg:
int count = 5;
int* a = new int[count];
for (int i = 0; i < count; ++i)
a[i] = 10;
...
delete[] a;
That is not very C++-ish. You could use std::fill() to get rid of the loop, at least:
int count = 5;
int* a = new int[count];
std::fill(a, a+count, 10);
...
delete[] a;
A better option is to switch to a std::vector instead, which has a constructor that does exactly what you are looking for:
std::vector<int> a(5, 10); // create 5 elements initialized to value 10
std::vector has a constructor where you can specify the initial size and initial value:
std::vector<int> an_array(size, init_value);
If you want to use a dynamic array using new[], you have to assign the initial value to each element:
int* array = new a[size];
for(int i = 0; i < size; ++i)
array[i] = init_value;
...
delete[] array;
Use std::array if the size is known at compile-time:
std::array<int, 5> myArray = { 1, 2, 3, 4, 5 };
Which is RAII-conform and safe.
You just have to include <array> and <initializer_list>.
In other cases, use std::vector.
This works for me with g++ 4.8.2.
#include <iostream>
int main()
{
int* a = new int[5]{10, 10, 10, 10, 10};
for ( int i = 0; i < 5; ++i )
{
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
Output:
10 10 10 10 10
Update, in response to OP's comment
When you use
std::vector<int> v(5, 10);
the constructor of std::vector used is:
vector( size_type count,
const T& value,
const Allocator& alloc = Allocator());
Let's say you have a class
class MyClass
{
public:
MyClass(int ) {}
};
You can construct a std::vector<MyClass> using:
std::vector<MyClass> v(10, MyClass(50));
or
std::vector<MyClass> v(10, 50);
In the second case, the compiler knows how to implicitly construct a temporary MyClass object given the argument 50 alone. But either way, a temporary MyClass object is being passed to the vector, and that is OK because the argument type of that parameter is const MyClass&, which can bind to a temporary object.

C++ Pointer of Array of Ints Initialization

I want to have an array accessible by all functions of a class.
I put the array as private variable in the header file.
private:
int* arrayName;
In the .cpp file where I implement the class, the constructor takes in an int value (size) and creates the array. The goal is to fill it up
ClassName::ClassName(int numElements){
arrayName = new int[numElements]; //make arrays the size of numElements
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
}
I feel like this is quite inefficient. I know you can do int array[5] = {0}; but how do you do it when you don't initially know the size.
If you want to zero-initialize a newed array, just do value-initialize it. This has the effect of zero-initializing its elements:
arrayName = new int[numElements]();
// ^^
But you really want to be using an std::vector<int>.
private:
std::vector<int> vname;
and
ClassName::ClassName(int numElements) : vname(numElements) {}
This way you don't have to worry about deleting an array and implementing copy constructors and assignment operators.
You can use the memset function:
memset(arrayName,0,sizeof(int)*numElements);
This void * memset ( void * ptr, int value, size_t num ); function sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).
To use it you must include the string.h header file.
For more information: http://www.cplusplus.com/reference/cstring/memset/
What you want to do is progressively expand the array on demand.
arrayName = new int[numElements];
for(int i = 0; i<numElements; i++)
arrayName[i] = 0;
The above code (what you gave) will give you an array of size numElements, and THEN the for loop will fill it. This is allocated now, and can't, as I understand it, be simply or easily resized (memset will overwrite previously held values in the array).
You could copy the whole array over every time you want to resize it:
int * oldarr = new int[OldSize];
//fill your old array
int * newarr = new int[NewSize];
for(int i = 0; i<OldSize; i++)
newarr[i] = oldarr[i];
Other than that, you could make the array much larger, or you could use various STLs, such as std::vector. Vector can be increased with a simple push_back function, and allows [] operator access (like arr[5] and whatnot).
Hope this helps!

How do you delete (or fill with specific values) a static n-dimension array?

const int ROWS = 3;
const int COLUMNS = 4;
void fillArray(double a[ROWS][COLUMNS], double value);
void deleteArray(double a[ROWS][COLUMNS]);
int main () {
double a[ROWS][COLUMNS];
fillArray(a, 0);
deleteArray(a);
}
In C++, how do you delete (or fill with specific values) a static n-dimension array?
In C++ we generally do not use arrays. We use std::vector.
You can use memset or std::fill to fill the array with specific values.
BTW you can use delete on dynamically allocated arrays not on static ones.
memset( a, 0 ,ROWS * COLUMNS * sizeof( double ));
or
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(double), 0);
You can delete only an object created by new (and that object will be allocated in the heap). What do you mean by "deleting a static POD variable"? It has no sense:
1) It doesn't have any destructor to perform additional tasks before freeing the memory,
2) The stack memory will be "freed" as you exit the current block.
And to set it: either loop, either simple memset(a, 0, sizeof(a)); .
Also, the array in your example is not static.
std::vector is what is generally used for C++ arrays (especially when you're new at it). One of vector's constructors will fill it for you to:
std::vector<type> myVector(initialSize, defaultValue);
If you want multidimensional, you could do a vector of vectors, or boost::multi_array:
boost::multi_array<type, numberOfDimensions> myArray(boost::extents[firstSize][secondSize][thirdSize]);
In that case, you'll need to use the multiple-for-loops approach, because it doesn't seem to have a constructor that does that.
EDIT: Actually you can use std::vector to make a multidimensional array with default values:
std::vector<std::vector<double> > a(3, std::vector<double>(4, 0));
Where 3 is the number of rows, 4 is the number of columns and 0 is the default value.
What it's doing is create a vector of vectors with 3 rows, where the default value for each row is a vector with 4 zeroes.
Filling arrays in C++ is the same as filling them using C, namely nested for loops
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
a[i][j] = 0
Arrays aren't "deleted" but they can use free if they've been allocated on the heap (if they've been allocated on the stack within a function, this is unnecessary).
int i;
for (i = 0; i < ROWS; i++)
free(a[i]);
free(a);
Firstly, the code you posted seems confused. What is it that you think "deleteArray" is supposed to do? 'a' is an auto variable and therefore cannot be deleted or freed.
Secondly, wrap your array in a class. There is a nice one in the FAQ that you can start with, but it can be improved. The first improvement is to use a vector rather than newing a block of memory. Then std::fill can be used to fill the array.
Use std::fill
#include <algorithm>
And then your implementation is simply:
std::fill(&a[0][0], &a[0][0]+sizeof(a)/sizeof(a[0][0], value);
You don't delete the array since it is stack allocated.