how to initialize part of an array as zero c++ - c++

I am a new programming student. I am currently studying pointers and dynamic arrays. The assignment I need help with asked me to create an array then use a function to double the elements and initialize the last half of the array as zeros. Here is my code:
#include <iostream>
using namespace std;
// Function prototype
void doubleArray(int*, int);
// Global variable for array elements
int numElems = 5;
int main()
{
int* oldArray; // Array variable
oldArray = new int[numElems]{1, 3, 5, 7, 9}; // Makes the array dynamic
// Display old array
cout << "This is the old array.\n";
for (int a = 0; a < numElems; a++)
{
cout << oldArray[a] << endl;
}
// Double the array size, copy old array into new array, and initialize the rest of the space to zero
doubleArray(oldArray, numElems);
cout << endl;
delete[] oldArray;
oldArray = nullptr;
return 0;
}
// Function doubles array size, copies old array into new array, and initializes the rest of the space to zero
void doubleArray(int* newArray, int size)
{
size *= 2;
for (int b = 5; b < (size/2); b++)
{
newArray[b] = {0};
}
cout << "This is the new array.\n";
for (int c = 0; c < size; c++)
{
cout << newArray[c] << endl;
}
}
Here is the output:
This is the old array.
1
3
5
7
9
This is the new array.
1
3
5
7
9
0
138433
0
0
0
As you can see, there is garbage in the second 'for' loop in the function doubleArray when it runs through the loop a second time. I have been diligently searching for an answer here on the forum, but have not yet succeeded.

The array you have allocated memory for is only for 5 integers , when you try to increase the number of elements you have to allocate more memory for the array.
What you should do is allocate memory for an array with double the size copy the contents of the initial array , and then assign the other half of the elements as 0.
And then return the reference of the new array or you could make the old array "point" to the new reference

Nowhere in doubleArray do you double the array. Instead you start stomping on the data around the old array. This is not a good idea. You don't know what's there. Could be something important. Could crash your program. In the old days it could have crashed the computer or smashed some important information in another program. Maybe someone's bank account. Maybe the instructions on where to fly the plane. Not good.
To fix this you will need to new[] yourself another array of ints twice the size of the original. Do not reuse the variable for the old array. If you write over it, you lose the old array. You still need to get the old data from the old array into the new array and if you don't put the old array away properly you will leak memory.
Once you've done that, on to the next bit: preserving the old data and zeroing the rest of the new array. To do this, copy all of the data from the old array to the new array (a for loop is perfect for this job) and fill the remainder of the new array with zeros.
Next some house keeping. Since the old array is no longer needed, you can safely delete[] it to prevent the memory leak.
Finally return the new array to the caller.
If you're feeling brave, point out to your instructor that there's this really cool thing called std::vector that was invented back in the 1990s and basically does all this stuff (and a lot more!) for you.

Related

Dynamic resizing array code not working in C++?

I am trying to create an array, which doubles every time it is completely filled.
#include <iostream>
using namespace std;
int* array_doubler(int* array, int size){
int *new_array = new int[size*2];
for(int i = 0; i < size; i++){
new_array[i] = array[i];
}
delete[] array;
return new_array;
}
int main()
{
int N = 10; // Size of array to be created
int *array = new int[0];
for(int i = 0; i < N; i++)
{
if(array[i] == '\0')
array = array_doubler(array, i);
array[i] = i*2;
}
//Printing array elemensts
for(int i = 0; i < N; i++)
cout << array[i] << '\t';
cout << '\n';
return 0;
}
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot). i.e. If i write:
int* p = new int[5];
then all the 5 blocks in memory p[0],p[1],p[2],p[3],p[4],p[5] have \0 in them, not just the p[5]. So the if(array[i] == '\0') in my main() calls array_doubler for every single iteration of for loop. I want it to fill the available spots in the array first and when it reaches the last element, then call array_doubler.
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot).
Actually they have undefined values in them. 0 is a valid value for them to have, but tomorrow the compiler might suddenly decide that they should all have 1 instead of 0.
If you want to detect the end of an array, then you have to remember how big the array is. C++ doesn't do it for you. Actually, it does do it for you if you use std::vector, but I suppose that's not the point of this exercise.
I'm not sure why you'd want to do this, as std::vector offer this kind of feature, and are more idiomatic of c++ (see isocpp faq on why C-style array are evil).
One of the issue of C-style array is the fact that they don´t know their own size, and that they don't have default value, thus stay uninitialized.
If for some reason you need to not use std::vector, the next best solution would be to wrap the array with it's size in a structure or a class (which is kinda what std::vector is doing), or to initialize your array using std::memset (which is the C function you would use if you were in C).
Do keep in mind that this is not considered as good practices, and that the STL offer plenty of solution when you need containers.

Having trouble doubling the size of a dynamic array in C++

I have a function that adds integers to an array. If space runs out it should double the array size and add the value at the next free spot. So if the array size is 3 for example and I enter 99, 105, and 45. Now if I want to add 100 a new array of size 6 should be created. There is a snippet of the code below. It all works and I even display array[4] within the local function it returns 100. When the program returns to main to display the menu again all the values become -572662307. I spent days attempting to figure this out but could not. can anyone help?
//Snippet from Main
cout<<"Enter the size of the array to be created";
cin >> size;
int *myArray = new int[size]();
add(myArray,Size);
//Problematic Code
void add (int Array[], int size){
int* temp = new int[size*2]; // create new Array 2x The Size
for (int i = 0; i < size; i++) {
temp[i] = Array[i];//Copy data over
}
delete [] Array;//Delete the old array
Array = temp;
cout << "\n\nEnter a Number: ";
cin >> newNumber;
Array[sizeTrack] = newNumber;
sizeTrack = sizeTrack++;
If this is a school assignment and you can't use std::vector, then you need to know that by declaring an argument as int Array[], it's really the same as int* Array. What you have is a pointer, and when calling the function you pass a copy of the pointer.
That last part is important: You pass a copy of the value in the variable. That means, when you modify the argument variable inside the function, you only modify the copy. And modifying a copy leaves the original unmodified.
There are two possible solutions here, both which you should either already know about (go through your text-books and class notes) or should be able to find in your text-book:
Returning the new pointer.
Passing the argument by reference.

Dynamic memory Points in C++

I am trying to write code in C++ that reads from a file, a sequence of points, stores it in a dynamic array and then prints back.
This is the specification I've been given:
"We want to take advantage of the fact that we can use dynamic memory, thus instead of allocating at beginning an amount of memory large enough according to our estimations, we implement the following algorithm:
Initially, very little memory is allocated.
At each iteration of the loop (reading from the file and storing into the
dynamic array) we keep track of:
The array maximum size (the allocated memory).
The number of elements in the array.
When, because of a new insertion, the number of elements would become
greater than the array maximum size, memory reallocation needs to take
place as follows:
Allocate another dynamic array with a greater maximum size.
Copy all the elements from the previous array to the new one.
Deallocate the memory area allocated for the previous array.
Get the pointer to the previous array to point to the new one.
Add the new item at the end of the array. This is where my problem is.
From my code below, I think everything else is fine but the last requirement, which is to add the new item at the end of the array.
The code works fine when the array Max_Size exceeds file's number of
elements, but when I try extending the num_elements, the result is
that the extra digits in the file are just saved as zeros
.
Also to add, the assignment doesn't allow use of vectors just yet.
Sorry I forgot to mention this, I'm new to stackoverflow and somewhat
to programming.
Any help please
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct point {
double x;
double y;
};
int main () {
ifstream inputfile;
inputfile.open("datainput.txt");
if(!inputfile.is_open()){
cout << "could not open file" << endl;
exit(EXIT_FAILURE);
}
//initially very little memory is allocated
int Max_Size = 10;
int num_elements = 0;
point *pp = new point[Max_Size];
//read from file and store in dynamic array
for (int i = 0; !inputfile.eof(); i++) {
inputfile >> pp[i].x >> pp[i].y;
num_elements++; //keep track of number of elements in array
}
//detecting when number of elements exeeds max size due to new insertion:
if (num_elements > Max_Size){
// allocate another dynamic array with a greater maximum size
Max_Size *= 2; // Max_Size = 2*Max_Size to double max size whenever there's memory problem
point *pp2 = new point[Max_Size];
//copy all elements from previous array to new one
for (int j=0; j<(Max_Size/2); j++) {
pp2[j].x = pp[j].x ;
pp2[j].y = pp[j].y;
}
//deallocate memory area allocated for previous array
delete [] pp;
//get pointer to previous array to point to the new one
pp = pp2;
**//add new item at end of the array
for (int k = ((Max_Size/2)-1); k<num_elements; k++) {
inputfile.seekg(k, ios::beg) >> pp2[k].x;
inputfile.seekg(k, ios::beg) >> pp2[k].y;
}**
//print out dynamic array values
for (int l = 0; l<num_elements; l++) {
cout << pp2[l].x << ",";
cout << pp2[l].y << endl;
}
//delete dynamic array
delete [] pp2;
}
else {
//print out dynamic array values
for (int m = 0; m<num_elements; m++) {
cout << pp[m].x << ",";
cout << pp[m].y << endl;
}
//delete dynamic array
delete [] pp;
}
cout <<"Number of elements = " << num_elements <<endl;
//close file
inputfile.close();
return 0;
}
Others have already pointed out std::vector. Here's roughly how code using it could look:
#include <vector>
#include <iostream>
struct point {
double x;
double y;
friend std::istream &operator>>(std::istream &is, point &p) {
return is >> p.x >> p.y;
}
friend std::ostream &operator<<(std::ostream &os, point const &p) {
return os << p.x << "," << p.y;
}
};
int main() {
// open the file of data
std::ifstream in("datainput.txt");
// initialize the vector from the file of data:
std::vector<point> p {
std::istream_iterator<point>(in),
std::istream_iterator<point>() };
// print out the data:
std::copy(p.begin(), p.end(), std::ostream_iterator<point>(std::cout, "\n"));
}
On top of being a lot shorter and simpler than the code you posted, getting this to work is likely to be a lot simpler and (as icing on the cake) it will almost certainly run faster1 (especially if you have a lot of data).
1. In fairness, I feel obliged to point out that the big difference in speed will mostly come from using \n instead of endl to terminate each line. This avoids flushing the file buffer as each line is written, which can easily give an order of magnitude speed improvement. See also: https://stackoverflow.com/a/1926432/179910
The program logic is flawed. You run the loop until EOF but you don't check to see if you have exeeded your array size. I would add an if statement inside of the first loop to check if you have passed the Max_Size. I would also write a function to reallocate the memory so you can simply call that function inside of your first loop.
Also you have problems with your memory allocation. You should do like this:
point temp = pp;
pp = new Point[...];
// Copy the contents of temp into pp
delete temp;
You need to set your pointer to the old array first so you don't lose it. Then after you have copied the contents of you old array into the new array, you can then delete the old array.

length of array in c++

I read to get the length of array in C++, you do this:
int arr[17];
int arrSize = sizeof(arr) / sizeof(int);
I tried to do the same for a string:
where I have
string * arr;
arr = new (nothrow) string [213561];
And then I do
arr[k] = "stuff";
where I loop through each index and put "stuff" in it.
Now I want the size of the array which should be 213561, what's the correct way to do it and why is it so complex in C++?
What you are trying to do cannot work because sizeof works on types at compile-time (and pointer types never hold the size of the array they may be pointing to).
In your case, computing sizeof(arr) returns the size taken in memory by the pointer, not
size of the array * size of a std::string
I suggest you use one of these two options
either use fixed-size arrays (sizeof works)
or vectors (myVector.size() returns what you need)
... unless you have a good reason not to.
The correct way of doing this in C++ is to use a vector. That way you can either specify a size up-front, or resize it as you go.
Specifying size up-front:
using namespace std;
vector<string> arr(213561);
for (vector<string>::iterator p = arr.begin(); p != arr.end(); ++p)
{
*p = "abc";
}
Expanding the vector as you go:
using namespace std;
vector<string> arr; // <-- note, default constructor
for (int i = 0; i < 213561; ++i)
{
// add elements to the end of the array, automatically reallocating memory if necessary
arr.push_back("abc");
}
Either way, the size of the array is found with:
size_t elements = arr.size(); // = 213561
The sizeof method only works as long as your array is really an array, i.e. an object that has the array type. In your first example object arr has type int[17]. It is an array type, which means that you can use the sizeof method and get 17 as the result.
Once you convert your array type T[N] to a pointer type T *, you basically lose your array type. The sizeof method applied to a pointer will not evaluate to the size of the original array.
When you allocate array of type T[N] with new[], the result is a pointer of type T * right away. It is not an array type from the very beginning. The information about array size is lost right away and trying to use the sizeof method with such a pointer will not work. In order to preserve the size information about a dynamically allocated run-time sized array, you have to store it in a separate variable yourself.
Here is how you find the size of an array:
const size_t ARRAY_SIZE = 17;
int array[ARRAY_SIZE];
//...
std::cout << "My array size is: " << ARRAY_SIZE << "\n";
You can put ARRAY_SIZE into a header so that other translation units can access the array size.
If you want a dynamic array, that will grow as needed, try std::vector.
You need to keep track of the length using a separate variable. There is no way of getting the length of an area that you only have a pointer to, unless you store that length somewhere.
You cannot get the length of the allocated array.
What you can do is save it seperately at the time of allocation..
Also, you could check the length of the string (which isn't what you're asking, but still..) using strlen()
In c++ here arr is simply a reference to the first element of the array. In case of dynamic arrays it is not possible.
There is a subtle nuance in both C and C++ with memory allocation. Neither language supports dynamic arrays. Here is what you are seeing:
int ary[17];
int arrSize = sizeof(ary) / sizeof(ary[0]);
Here ary is a true array of 17 integers. The array size calculation works because sizeof(ary) returns the size of the memory block allocated for the entire array. You divide this by the size of each element and violà you have the number of elements in the array.
std::string * arr;
arr = new (std::nothrow) std::string[213561];
In this case arr is a pointer to some memory. The new operator allocates a block of memory large enough to hold 213,561 contiguous std::string objects and constructs each of them into the memory. The arr variable simply points to the beginning of the block of memory. C++ does not track the number of elements that you have allocated. You didn't really create a dynamic array - instead, you have allocated enough memory for a bunch of contiguous objects.
C and C++ both allow you to apply the subscripting operator to a pointer as syntactical sugar. You will see a lot of comments about how arr[0] translates into *(arr + 0). The reality is that allocating memory using the new operator results in a block of memory that is not an array at all. The syntactical sugar makes it look like one. The next thing that you will encounter is that multi-dimensional arrays are similar sugar.
Consider the following snippet. Once you understand what is going on there, you will be a lot closer to understanding how memory works. This is the primary reason why C and C++ cannot tell you how large an array is if it is dynamically allocated - it does not know the size, all that it has is a pointer to the allocated memory.
#include <iostream>
int
main()
{
//
// The compiler translates array subscript notation into
// pointer arithmetic in simple cases so "hello"[3] is
// is translated into *("hello" + 3). Since addition is
// commutative, the order of "hello" and 3 are irrelevant.
//
std::cout
<< "\"hello\"[3] = '" << "hello"[3] << "'\n"
<< "3[\"hello\"] = " << 3["hello"] << "\n"
<< std::endl;
//
// All memory is linear in C or C++. So an 3x3 array of
// integers is a contiguous block of 9 integers in row
// major order. The following snippet prints out the 3x3
// identity matrix using row and column syntax.
//
int ary[3][3] = { { 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 } };
for (int r=0; r<3; ++r) {
for (int c=0; c<3; ++c) {
std::cout << "\t" << ary[r][c];
}
std::cout << "\n";
}
std::cout << "\n";
//
// Since memory is linear, we can also access the same
// 3x3 array linearly through a pointer. The inner loop
// is what the compiler is doing when you access ary[r][c]
// above - "ary[r][c]" becomes "*(ptr + (r * 3) + c)"
// since the compiler knows the dimensions of "ary" at
// compile time.
//
int *ptr = &ary[0][0];
for (int i=0; i<9; ++i) {
ptr[i] = i;
}
for (int r=0; r<3; ++r) {
for (int c=0; c<3; ++c) {
std::cout << "\t" << *(ptr + (r * 3) + c);
}
std::cout << "\n";
}
return 0;
}

Dynamic Arrays

I'm just starting to learn C++ so excuse me for this simple question. What I'm doing is reading in numbers from a file and then trying to add them to an array. My problem is how do you increase the size of the array? For example I thought might be able to just do:
#include <iostream>
using namespace std;
int main() {
double *x;
x = new double[1];
x[0]=5;
x = new double[1];
x[1]=6;
cout << x[0] << "," << x[1] << endl;
return 0;
}
But this obviously just overwrites the value, 5, that I initially set to x[0] and so outputs 0,6. How would I make it so that it would output 5,6?Please realize that for the example I've included I didn't want to clutter it up with the code reading from a file or code to get numbers from a user. In the actual application I won't know how big of an array I need at compile time so please don't tell me to just make an array with two elements and set them equal to 5 and 6 respectively.Thanks for your help.
You don't want to work with arrays directly. Consider using a vector, instead. Then, you can call the push_back function to add things to the end, and it will automatically resize the vector for you.
#include <iostream>
#include <vector>
int
main() {
double value;
std::vector<double> values;
// Read in values
while (std::cin >> value) {
values.push_back(value);
}
// Print them back out
for (std::size_t i(0), len(values.size()); i != len; ++i) {
std::cout << values[i];
}
}
You should use a collection class to do this for you rather than managing it yourself. Have a look at the "vector" class. It's essentially a dynamic array that resizes automatically as required.
In your situation you would use "vector" with the "double" type. You may also need to read up on templates in C++.
http://www.cplusplus.com/reference/stl/vector/
Or, if you don't want to use STL or another dynamic thing, you can just create the array with the correct size from the beginning: x = new double[2];
Of course the problem there is how big to make it. If you don't know, then you'll need to just create it "big enough" (like a hundred, or a thousand)... which, at some point, won't be big enough and it will fail in some random looking way. So then you'll need to resize it. And once you get to that point, you'll wish you'd used the STL from the start, like the other answers are telling you to do.
#include <iostream>
using namespace std;
int main() {
double *x = new double[2];
x[0]=5;
x[1]=6;
cout << x[0] << "," << x[1] << endl;
return 0;
}
Here's an example though for good measure, so you can see the pattern:
#include <iostream>
using namespace std;
int main() {
// Allocate some memory for a double array of size 1 and store
// an address to the beginning of the memory in mem_address.
double* mem_address = new double[1];
// Assign 5 to the first element in the array.
mem_address[0] = 5;
// Save the address of the memory mem_address is currently
// referencing.
double* saved_address = mem_address;
// Allocate some memory for a double array of size 2 and store
// an address to the beginning of the memory in mem_address.
mem_address = new double[2];
// Copy over the 1 element from the first memory block
// to the new one.
mem_address[0] = saved_address[0];
// Done with the old memory, so clean it up.
delete [] saved_address;
// Assign 6 to the second element in the new array.
mem_address[1] = 6;
// Print out the 2 elements in the new array.
cout << mem_address[0] << "\n";
cout << mem_address[1] << "\n";
// Done with the new array memory now, so clean it up.
delete [] mem_address;
}
If for some reason you don't have access to STL -- or want to learn how to do this yourself -- you could use an algorithm like this:
Allocate your array as some arbitrary size, and remember how many elements are in it and how big it is:
int *a = malloc(int * ARBITRARY_SIZE);
int size = 0;
int allocated = ARBITRARY_SIZE;
each time you add a new element, increase "size". If size equals ARBITRARY_SIZE, multiply 'allocated' by 2, and reallocate the array. Either way, assign the new value to a[size].
void addElement(int value) {
++size;
if (size == allocated) {
allocated *= 2;
a = realloc(sizeof(int) * allocated);
a = new_a;
}
a[size] = value;
}
Note that your code above has at least one bug -- you aren't allocating enough space for x[1] in either case.
Also obviously in real code you'd check that the return from malloc & realloc isn't null.
An array always needs a contiguous block of memory. In a situation where you might need to resize the array later on, reallocation is probably the only solution. This is what Moishe and Shadow2531 do above.
The problem with reallocation is that it can be a costly operation. So if you need adding 5 more elements to a 5000 element array, you might end up copying all the 5000 elements across memory.
Using a linked list instead can be considered for such a scenario.