which is best way to initialize array, "memset" or " {//value} "? - c++

int main(){
int ar[50]={1};
//OR
int br[50];
memset(br, 1, sizeof(br));
return 0;
}

int ar[50]={1};
This will set only the first element to 1. Rest all will be 0.
memset(br, 1, sizeof(br));
This will set all the bytes in br to 1. It is not the same as setting all the values to 1. The values afterwards are:
{16843009, 16843009, 16843009, 16843009, 16843009}
Use memset when you know you really need it. It is not exactly made for initializing arrays, it just set the memory to a particular value.
Best way in C++? Use std::fill or std::fill_n.
Example:
int array[5];
std::fill(array, array + 5, 8);
Array now contains:
{8, 8, 8, 8, 8}
Using fill_n
std::fill_n(array, 5, 99);
Array now contains:
{99, 99, 99, 99, 99}
As a side note, prefer using std::array instead of c-style arrays.
Try on godbolt: https://godbolt.org/z/DmgTGE
References:
[1] : Array Initialization
[2] : memset doc

suppose you do
int ar[50] = {-1};
Now you will expect this line to initialize all array elements with -1
but it will not. It will only set the first element of array to -1 and rest to 0.
Whereas memset will show the expected behaviour.
See this Initialization of all elements of an array to one default value in C++? for more info.
let's take an example:-
int arr[5] = { 1, 2 }; // this will initialize to 1,2,0,0,0
int ar[5] = { }; // this will initialize all elements 0
int myArray[10] = {}; // his will also all elements 0 in C++ not in c
So If you want to initialize a specific value to an array use memset().
If you want to initialize all elements in an array to 0 use
static int myArray[10]; // all elements 0
Because objects with static storage duration will initialize to 0 if no initializer is specified and it is more portable than memset().
Also, The int ar[50]={0}; will be infinite because it just initializes the array and does not have an ending but in memset(arr,0,sizeof(br)) it has the correct way of ending the loop in arrays

Related

Why does using push_back on a vector declared with size result in a vector of zeros?

I made a vector of constant size to store negative values, and then printing the values all I got was zeroes. I just want to know why it is not storing negative values.
#include <iostream>
#include <vector>
int main() {
std::vector<int> v(5);
v.push_back(-1);
v.push_back(-2);
v.push_back(-3);
v.push_back(-4);
v.push_back(-5);
for (int i=0; i<5; i++)
std::cout << v[i] << " "; // All I got was zeroes
}
That's because push_back puts new elements onto the end of the vector.
You can see the effect by running i to 9: the negative numbers will occupy v[5] to v[9].
Writing
std::vector<int> v{-1, -2, -3, -4, -5};
instead is a particularly elegant fix.
The constructor that you invoke fills the first 5 elements with zeros, see here (#3 in the list of overloads):
Constructs the container with count default-inserted instances of T
(where the "default-inserted instance" of an int is 0). What you might have wanted is
std::vector<int> v;
v.reserve(5); /* Prevent unnecessary allocations as you know the desired size. */
v.push_back(-1);
/* ... */
An alternative using the original constructor call is
#include <numeric>
std::vector<int> v(5);
std::iota(v.rbegin(), v.rend(), -v.size());
though this does more work than necessary as every element is first default constructed and then assigned to a new value again.
This is a case where the DRY principle would help you understand your mistake.
vector<int> v(5);
...
for(int i=0;i<5;i++)
Here you are creating an array, for which you think you reserve space for 5 elements. Then you insert those 5 elements. After that you wanted to print contents of the whole array, but instead of just writing v.size(), you repeated the 5, so that your code now reads like "Print first five elements of v", instead of "Print all elements of v".
If you instead wrote what you mean, you'd see that the array actually has 10 elements, not 5.
BTW, since C++11 you can loop over all elements in a more straightforward way:
for(int x : v)
or, if the elements were some more copy-expensive type, you could use references to the elements, even auto-type references:
for(auto& x : v)
This new for-loop syntax is called the range-based for loop.
You can consider the vector a flexible version of the primitive array in C/C++. When you initialize a vector with a size n, the constructed vector has size of n (or maybe larger in the memory, but you don't know since it's implicitly handled by compiler). Note that here n represents the number of entries, but not the actual memory usage (i.e. bytes). If you do not initialize it with a size parameter, the vector is empty with size 0, but in the memory it would have some implicit default memory size.
Let's say your current vector has size 5. And you want to push_back() in another element, then the vector internally will reallocate the entire array into a new memory location which could hold all its old entries plus the new one. So you don't need to reallocate the memory manually by yourself, like what you have to do in C.
Here, in your example, to fill in those 5 negative integers in your vector, there are a couple of ways.
1) You can initialize a vector without specifying the size. And then push in each element you want.
vector<int> v;
for (int i = -1; i >= -5; --i) {
v.push_back(i);
}
2) You can initialize the vector in your way with that size parameter. And then assign them with new values.
vector<int> v(5);
for (int i = 0; i < v.size(); ++i) {
v[i] = -i;
}
3) You can also initialize the vector with those entries when it is constructed.
vector<int> v{-1, -2, -3, -4, -5};
or vector<int> v = {-1, -2, -3, -4, -5};
When you declared the vector with
std::vector<int> v(5);
You made v store five 4-byte spaces in memory (assuming an int = 4 bytes on your system), and by default all of these 4-byte spaces store the bits representing 0's. Then, you pushed 5 more ints (-1, -2, -3, -4, -5) onto the end of the vector with:
v.push_back(-1);
v.push_back(-2);
v.push_back(-3);
v.push_back(-4);
v.push_back(-5);
At this point the vector has 10 elements, the first five being the unknown ints that happen to store 0's on the instance you ran the program. Since your for loop prints the first five elements in the vector, this is why it printed all 0's.
When you declared this line vector<int>v(5) it created a vector of size 5 with default value of all elements 0, at this stage your vector looks like this -
{0, 0, 0, 0, 0}
Now when you called v.push_back(-1) what it did is it pushed -1 to the back of vector increasing its size, now your vector looks like this -
{0, 0, 0, 0, 0, -1}
After every push back is performed your final vector will be - {0, 0, 0, 0, 0, -1, -2, -3, -4, -5}
The size of your vector is now increased to 10 from 5 and when you looped from index 0 to 4 it only printed 0. I hope I explained it well and fix for this is already provided in previous answers.

For loop with the length of array that has values

Say I have an integer array called abc[100]. abc only has values in the first 5 "slots". How can I write a for loop for this where the loop goes up until the last value in abc that isnt empty?
int abc[100] = {1, 2, 3, 4, 5};
In C++ arrays, there is no concept of an array element being "empty".
That idea simply doesn't exist. Erase it from your mind.
Each array element always exists.
In C & C++, when part of an array is explicitly initialized, and part is not explicitly initialized, the part that you didn't specify defaults to zero.
So, you effectively wrote:
int abc[100] = {1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0....};
If you want, you can treat value 0 as a marker for values that aren't set.
int i;
for(i=0; abc[i] != 0; ++i)
{
cout << "[" <<i<< "] : " << abc[i] <<endl;
}
In C++ if you declare an array and initialize only the first few elements, the remaining elements will be value initialize, meaning basically that the "default constructor" will be called.
For built-in types such as int value initializing sets the value to zero. So if you fix the problems with your array, and only initialize the first five elements the remaining will be initialized to zero.

c++ arrays, how to add a new row of values in the same array?

how do you create a new row of values in an array from user input or cin?
say theres a row of values already in the array and you need to add a second row of values
but not added to the first row, and how would you put the braces and the comma in, does the user put it in or is there something that will automatically put the bracers and comma in
int test [] = { 1, 21, 771, 410, 120711 },
{ 1, 2, 3, 4, 5 };
Without very bad and dirty tricks this is not possible. Better use list or vector (which is the nearest to an array). The other possibility is to use pointers and to extend it create a temporary memory, copy the old data and then add the new.
There is no way to change the size of array while still preserving its contents. The only way to change the size of an array at all is to use the new operator to allocate dynamic memory to a pointer, but this will destroy any data the array previously held. If you want to have a re-sizable array, you should probably use std::vector.
If you're keen on using c++11 you can keep your initialiser lists with std::vector like so:
#include <vector>
int main()
{
// initialise
std::vector<std::vector<int>> test = { { 1, 21, 771, 410, 120711 },
{ 1, 2, 3, 4, 5 } };
// add new data from user
test.push_back({9, 8, 7, 6, 5, 4, 3, 2, 1});
}
You're asking for a two-dimensional array. This is declared like this:
int test[][5] = {
{1, 21, 771, 410, 120711},
{1, 2, 3, 4, 5 },
// Add more if you want.
};
The first array is accessed through test[0], the second through test[1], etc. The first element of the first array is test[0][0], the second test[0][1] and so forth.
Note that this is an array with a static size. You can't change it at runtime. If you know in advance how many rows you need, you just declare it as:
int test[NUMBER OF ROWS][NUMBER OF COLUMNS];
and then fill it with values later. But you cannot change the size. If you want a fully dynamic array, then you should use a vector of vectors:
std::vector< std::vector<int> > test;
You then add rows with:
test.push_back(std::vector<int>());
and add elements to each row with:
// Adds a number to the first row.
test[0].push_back(some_int);
Access happens the same way as with the static array (test[0], test[0][0], etc.)

Accessing values from a two dimensional initialized array

int a[][30]={{2, 16},{4, 8},{5, 16, 21},{2,6,3,5,6}};
Since the size of the second dimension is varying. If I want to access something like for a particular value of i(first dimension), access all j values(2nd dimension), how do I write that statement?
What I thought was:
for(int j=0;j<30;j++)
a[i][j]=some operation;
but its unnecessarily looping till 30 which is the max value. What's the efficient way to do it?
Thanks.
The compiler does not keep any information about how many values were in the braced initializer. Instead, it fills the "missing" values with zeros.
So these two are equivalent:
int a[][4] = {{2, 16},{4, 8, 5}};
int a[][4] = {{2, 16, 0, 0}, {4, 8, 5, 0}};
If you know that none of the "actual" data elements are zero, you can stop your loop when you find a zero element. Otherwise, you'll need to set up the data differently.
The size of both dimensions is fixed. The outer dimension has size 4 and the inner has size 30.
If you iterate over the inner dimension, then you will print lots of zeros, as that is what you initialize the remaining integers that aren't explicitly initialized to.
You seem to want this:
std::vector<int> a[] = {
boost::list_of(2)(16),
boost::list_of(4)(8),
boost::list_of(5)(16)(21),
boost::list_of(2)(6)(3)(5)(6)
};

Initializing arrays in C++

I'm trying to initialize the last element in the array
int grades[10];
to grade 7 but it doesn't seem to work
I'm using C++ btw
If you want to initialize them all at definition:
int grades[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 };
If you want to initialize after:
int grades[10];
grades[9] = 7;
But, be aware that grades 0..8 will still be uninitialized, and will likely be junk values.
One more thing, if you initialize only the first element (if explicit array size is specified) or a shorter initiliazation list, the unspecified elements are fill with 0. E.g.
int grades[10] = {8}; //init with one element
is the same as:
int grades[10] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
or
int grades[10] = { 1, 9, 6, 16 }; //or init with a shorter than array size list with a minimum of 1 element
is the same as:
int grades[10] = { 1, 9, 6, 16, 0, 0, 0, 0, 0, 0 };
I find it handy for initializing an array with 0 values.
float coefficients[10] = {0.0f}; //everything here is full of 0.0f
when You write something like
int a[5] = {0};
it sets the whole array to zero on the contrary
int a[5] = {3};
sets only the first element and the rest may be anything(garbage values);
if You want to set the whole array with some value then u can go for the
std :: fill()
something like this
std::fill(arr, arr+100, 7); // sets every value in the array to 7
and if there is a character array You can always go for the memset function
The last element is grades[9], since arrays in C++ are zero-based (e.g. grades[0] to grades[9] are 10 elements). Is that what you're doing?
You might need to subtract one from the grade to use as your subscript value, or set the extent to one more.
Remember that an array with ten elements will have grades[0] through grades[9], and that grades[10] is an error.