Using dynamic memory, I am trying to make a class that stores numbers in a dynamic array (so 123 would be arr[0] = 1, arr[1] = 2, arr[2] = 3) and be able to append digits (e.g. if the number stored is 123, you could add more digits.. 45 and the new number would be 12345).
Here's my code so far: How would I go about making an append function?
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int *exampleArray; //new array into exsistence
exampleArray = new int[5]; // dynamically allocates an array of 5 ints
for (int i = 1; i < 5; i++)
{
exampleArray[i] = i;
cout << exampleArray[i] << endl;
}
delete exampleArray; // deleted from exsistence
system("pause"); // to show the output
return 0;
}
If you allocate an array with new[], the only way to "append" to it is to new[] a new array of larger size, copy the existing values from the old array into it, and then delete[] (not delete) the old array and update your array pointer to point at the new array.
Also, note that arrays are 0-indexed. Your loop is not populating exampleArray[0] with any data.
For example:
int *arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
...
int *newarr = new int[5];
std::copy(arr, arr+3, newarr);
newarr[3] = 4;
newarr[4] = 5;
delete[] arr;
arr = newarr;
...
delete[] arr;
You can optimize this a little by pre-allocating more memory than you actually need, and only "grow" when you actually exceed that memory. For example:
int *arr = NULL;
int num = 0, cap = 0;
void append(int digit)
{
if (num == cap)
{
int *newarr = new int[cap + 10];
std::copy(arr, arr+num, newarr);
delete[] arr;
arr = newarr;
cap += 10;
}
arr[num] = digit;
++num;
}
...
append(1);
append(2);
append(3);
...
append(4);
append(5);
...
delete[] arr;
That being said, what you are asking for would be best handled using std:vector instead. It is a dynamic-length container that handles these ugly details for you.
For example:
std::vector<int> arr;
void append(int digit)
{
arr.push_back(digit);
}
...
append(1);
append(2);
append(3);
...
append(4);
append(5);
...
An alternative solution that would not require you to use the std::vector container or any additional pointers would be to use the malloc()/realloc()/free() family of functions in the cstdlib C++ header as follows:
int *exampleArray;
exampleArray = (int *) malloc(5 * sizeof(int));
for (int i = 1; i < 5; i++)
{
exampleArray[i] = i;
cout << exampleArray[i] << endl;
}
// Now to add further elements
exampleArray = (int *) realloc(7 * sizeof(int)); // Added space for 2 new elements
for (int i = 5; i < 7; i++) {
exampleArray[i] = i;
cout << exampleArray[i] << endl;
}
free(exampleArray);
Related
Write a function, reverseArray, that when passed an int array of length greater than 0 will return a dynamically allocated array of the same length but with the elements in the reverse order. For example, if passed the array, {1,2,3,4,5,6,7,8,9,0} the function would return the array {0,9,8,7,6,5,4,3,2,1}.
Below is my code, but there is a bug in it.
This is my output.
1
2
3
4
5
6
4113
6
5
4
3
2
1
0x7fffe697ceb0
The 4113 and address are provided by the compiler.
#include <iostream>
using namespace std;
int * readNumbers() {
int * a = new int[6];
for (int i = 0; i < 6; i++) {
int x;
cin >> x;
a[i] = x;
}
// a++;
return a;
delete[] a;
}
int *reverseArray(int *numbers1,int length) {
for (int i = length; i >=0; i--) {
cout << numbers1[i] << endl;
}
return numbers1;
delete [] numbers1;
}
int main() {
int *arr1 = readNumbers();
cout << reverseArray(arr1,6) << endl;
return 0;
}
I think there may have been an issue with your wording. Assuming you want your function just to print the reverse of a passed array, you're off to a good start.
One issue is what was said in the comments: your for loop is indexing past your array. When you type int * a = new int[6]; you are creating a pointer 'a' which points to a location in memory. Since you chose size 6, the appropriate amount of memory is allocated. If you happen to index outside of that range, you will end up pointing to a random spot in memory, not allocated for your array. Hence why you are getting a weird number '4113'.
A fix for this could be:
int i = length changed to int i = length-1
Another issue is that your function returns an integer pointer, and you are trying to cout this pointer. As another commenter said, you have to think about what this does. If you try this code:
#include <iostream>
using namespace std;
int main() {
int arr[] = {1, 2, 3};
cout << arr << endl;
return 0;
}
your output would be something like 0xff09ba. This represents the location of the start of the array in memory. If you change arr to (arr + 1) you will get the location of the second index of the array.
So when you type cout << reverseArray(arr1,6) << endl; you are really just printing out the location of numbers1 in memory. This is why you are getting '0x7fffe697ceb0' in your output. To fix this, simply make your function
void reverseArray(int *numbers1,int length) {
for (int i = length; i >=0; i--) {
cout << numbers1[i] << endl;
}
}
and change your main to:
int main() {
int *arr1 = readNumbers();
reverseArray(arr1,6);
return 0;
}
Now, if you actually want to return this array, you would need to create a new array which holds the reverse numbers and then return that. An example of a function that does that is:
int* reverseArray(int *numbers1,int length) {
int j = 0;
int *numbers2 = new int[length];
for (int i = length-1; i >=0; i--) {
numbers2[j] = numbers1[i];
j++;
}
return numbers2;
}
There are probably better ways to do this, but this is just one solution. Regardless, you should always be careful when allocating memory yourself.
Write a function, equalsArray that when passed two int arrays of the same length that is greater than 0 will return true if every number in the first array is equal to the number at the same index in the second array. If the length of the arrays is less than 1 the function must return false. For example, comparing the two arrays, {1,2,3,4,5} and {1,2,3,4,5} would return true but the two arrays {3,7} and {3,6} would return false.
You should start by copying the function-1-1.cpp file and name it function-3-1.cpp. Then add the function equalsArray to the new file.
The main function for this problem must call your readNumbers function twice, then pass both new arrays to your equalsArray function, display the result as true or false and finally delete the array. The main function in the file main-3-1.cpp.
The signature for your new function is:
bool equalsArray(int *numbers1,int *numbers2,int length) ;
This is my code, and i try to use the int* readNumber two times.
#include <iostream>
using namespace std;
int* readNumbers()
{
int* a = new int[10];
for (int i = 1; i < 11; i++) {
int x;
cin >> x;
a[i] = x;
}
a++;
return a;
// delete[] a;
}
bool equalsArray(int* numbers1, int* numbers2, int length)
{
if (length >= 1) {
for (int i = 0; i < length; i++) {
if (numbers1[i] == numbers2[i]) {
}
else {
return false;
}
}
return true;
}
// delete[] numbers1;
// delete[] numbers2;
int main()
{
int* arr1 = readNumbers();
int* arr2 = readNumbers();
equalsArray(arr1, arr2, 10);
return 0;
}
There there is an error,control reaches end of non-void function.
How to improve my code?
Thank you all.
Expect result:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
True(1)
OK, first I will show you your code, with comments where the errors are.
Then I will show you a fixed version. And, at the end, a little bit more robust C++ soultion.
I know that you learn in school all this nasty stuff with pointers, decayed pointers for arrays, C-style arrays,pointers for owned memory, new and delete.
That is basically bad. It should never be used in C++.
Anyway. Teachers still think like that. What a pity . . .
OK. You code with comments:
#include <iostream>
using namespace std; // Should not be used
int* readNumbers()
{
int* a = new int[10]; // Do not use C-style arrays, pointer for owned memory, new and delete
for (int i = 1; i < 11; i++) { // Will lead to out of bound error
int x; // Why using additional variables?
cin >> x;
a[i] = x;
}
a++; // Wrong
return a;
// delete[] a; // Not here
}
bool equalsArray(int* numbers1, int* numbers2, int length)
{
if (length >= 1) {
for (int i = 0; i < length; i++) {
if (numbers1[i] == numbers2[i]) {
}
else {
return false;
}
}
return true;
}
// Here nothing will be returned
} // Closing bracket misding
// delete[] numbers1; // Not here
// delete[] numbers2; // Not here
int main()
{
int* arr1 = readNumbers();
int* arr2 = readNumbers();
equalsArray(arr1, arr2, 10);
return 0; // No output
} // No Release of memory
Next, your fixed code
#include <iostream>
using namespace std;
// Function to read a given numbers of values and returns them in a dynaimcally allocated array
int* readArrayOfNumbers(int numberOfValuesToRead) {
// Allocate a new array for the given amount of integers
int* dynamicArrayOfIntegers = new int[numberOfValuesToRead];
// Read all values in a loop from user via std::cin
for (int index = 0; index < numberOfValuesToRead; ++index) {
cin >> dynamicArrayOfIntegers[index];
}
return dynamicArrayOfIntegers;
}
// Compare 2 arrays with same size
bool equalsArray(int* numbers1, int* numbers2, int length) {
// We assume in the beginning that the arrays will be equal
bool result = true;
// We will only compare arrays, if they contain data
if (length >= 1) {
// Now compare arrays element by element
for (int i = 0; i < length; i++) {
if (numbers1[i] != numbers2[i]) {
// If not equal then set result to false and stop loop
result = false;
break;
}
}
}
else {
// No data in array. Consider as not equal
result = false;
}
return result;
}
int main()
{
// Define size of arrays
const int sizeOfArray = 10;
// Get 2 arrays in dynamically allocated arrays
int* array1 = readArrayOfNumbers(sizeOfArray);
int* array2 = readArrayOfNumbers(sizeOfArray);
// Compare both arrays
const bool arraysAreEqual = equalsArray(array1, array2, sizeOfArray);
// Show result
if (arraysAreEqual)
std::cout << "\nTrue(1)\n";
else
std::cout << "\nFalse(0)\n";
// Release memory
delete[] array1;
delete[] array2;
}
And finally, the C++ solution
#include <iostream>
#include <iomanip>
#include <array>
constexpr size_t NumberOfElements = 10u;
using MyType = int;
using MyArray = std::array<MyType, NumberOfElements>;
int main() {
// Define arrays
MyArray myArray1{};
MyArray myArray2{};
// Read values
for (size_t i{}; (i < NumberOfElements) and (std::cin >> myArray1[i]); ++i)
;
for (size_t i{}; (i < NumberOfElements) and (std::cin >> myArray2[i]); ++i)
;
// If all numbers could be read . . .
if (std::cin) {
// Show result of comparison
std::cout << '\n' << std::boolalpha << (myArray1 == myArray2) << '(' << (myArray1 == myArray2) * 1 << ")\n";
}
else std::cerr << "\n*** Error. Invalid input data\n";
}
I am took two arrays and then merged those two arrays to a newly created third array and it worked but when I output the size of the array, I was getting the size as '1'. I don't understand why the size of that array was '1' even though there are 5 elements in it.
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int arr1[] = { 1,2,3 };
int arr2[] = { 9,4 };
int size1 = sizeof(arr1) / sizeof(int);
int size2 = sizeof(arr2) / sizeof(int);
int *arr = new int[size1 + size2];
//merging the two arrays by transferinng the elements into the third array
for (int i = 0; i < size1; i++)
{
arr[i] = arr1[i];
}
for (int i = size1; i < (size1 + size2); i++)
{
arr[i] = arr2[i - size1];
}
//sorting the array
sort(arr, arr + (size1 + size2));
cout << endl;
//finding the size of newly merged array
int mergeSize = sizeof(arr) / sizeof(int);
cout << "The size of the array is " << mergeSize << endl; //why am I getting the size of the array as '1'
return 0;
}
sizeof(arr) gives you the size of the pointer arr, which does not depend on the number of elements you allocated for it.
Avoid the problem by using std::array. It doesn't have the overhead of std::vector and it's easier to use than C-style arrays.
int main()
{
array<int, 3> arr1 = { 1, 2, 3 };
array<int, 2> arr2 = { 9, 4 };
array<int, arr1.size() + arr2.size()> arr;
//merging the two arrays by transferinng the elements into the third array
for (int i = 0; i < arr1.size(); i++)
{
arr[i] = arr1[i];
}
for (int i = 0; i < arr2.size(); i++)
{
arr[i + arr1.size()] = arr2[i];
}
//sorting the array
sort(arr.begin(), arr .end());
cout << endl;
//finding the size of newly merged array
int mergeSize = arr.size();
cout << "The size of the array is " << mergeSize << endl; //why am I getting the size of the array as '1'
return 0;
}
arr is not an array, it's a pointer, Using sizeof on a pointer gives the size of the pointer not the size of the dynamic array it's pointing at. The sizeof a pointer is usually 4 or 8, depending on whether you have a 32 bit or 64 bit system.
You can avoid these problems by using vectors instead of arrays. Vectors have a size method which always gives the actual size. Arrays are quite poor in C++.
I have an assignment for class, in which I need to create 3 functions to test with constant arguments. I am also supposed to create and delete dynamic memory. I have attached the exact directions from the assignment, just in case, as well as my code.
I apologize if the code is messy. I am a beginning programmer and new to the site, so I'm not exactly sure how to format everything perfectly.
Directions from assignment:
Write a C++ program that will test three functions described below that use pointers and dynamic memory allocation.
Expand: takes an int array and the array's size as parameters. It should create a new array that is twice the size of the argument array. The function should copy the contents of the argument array to the new array, and initialize the unused elements of the new array with -1. The function should return a pointer to the new array.
concatenate: takes two int arrays and the arrays' sizes as parameters (that's 4 parameters). It should create a new array big enough to store both arrays. Then it should copy the contents of the first array to the new array, and then copy the contents of the second array to the new array in the remaining elements, and return a pointer to the new array.
subArray: It takes an int array, a start index and a length as arguments. It creates a new array that is a copy of the elements from the original array starting at the start index, and has length equal to the length argument. For example, subArray(aa,5,4) would return a new array containing only the elements aa[5], aa[6], aa[7], and aa[8].
My code:
#include <iostream>
using namespace std;
int* Expand(int [], int);
int* concatenate(int[], int, int[], int);
int* subArray(int[], int, int);
int main()
{
//Declare variables
const int SIZEAA = 10;
const int SIZEBB = 5;
int aa[SIZEAA] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int bb[SIZEBB] = { 11, 22, 33, 44, 55 };
//Output both original arrays
cout << "aa[10]: ";
for (int i = 0; i < SIZEAA; i++)
cout << aa[i] << " ";
cout << endl;
cout << "bb[5]: ";
for (int i = 0; i < SIZEBB; i++)
cout << bb[i] << " ";
cout << endl;
//Call the Expand function
int* aaExpand = Expand(aa, SIZEAA);
//Output expanded array
cout << "Testing Expand: ";
for (int i = 0; i < 20; i++)
cout << aaExpand[i] << " ";
//Release dynamic memory
delete[] aaExpand;
aaExpand = nullptr;
cout << endl;
//Call the concatenate function
int* concatenateArray = concatenate(aa, SIZEAA, bb, SIZEBB);
//Output concatenated array
cout << "Testing concatenate: ";
for (int i = 0; i < (SIZEAA + SIZEBB); i++)
cout << concatenateArray[i] << " ";
//Release dynamic memory
delete[] concatenateArray;
concatenateArray = nullptr;
cout << endl;
//Call subArray function
int* arraySub = subArray(aa, 5, 4);
//Output the sub array
cout << "Testing subArray: ";
for (int i = 0; i < 4; i++)
cout << arraySub[i] << " ";
//Release dynamic memory
delete[] arraySub;
arraySub = nullptr;
cout << endl;
}
int* Expand(int aa[], int size) /*This function takes in an array and
the size as parameters, creates a new array of double the size, and copies
the old array into it.It then adds -1 into all new spaces created.
It returns a pointer to the new array*/
{
//Declare new array
int* aaNew;
int newSize = size * 2;
aaNew = new int[newSize];
//Copy old array into new array
for (int i = 0; i < newSize; i++)
{
if (i >= 0 && i < size) //Check to see if it needs to copy an old value in or put -1 into the array
aaNew[i] = aa[i];
else
aaNew[i] = -1;
}
return aaNew;
}
int * concatenate(int aa[], int sizeAA, int bb[], int sizeBB) /*This
function takes in two different arrays, creates a new array, then copies
both arrays into the new array.It returns a pointer to the new array*/
{
//Create new array size
int newSize = (sizeAA + sizeBB);
//Create new array
int* concatArray;
concatArray = new int[newSize];
//Add elements of first and second array into new array
for (int i = 0; i < newSize; i++)
{
if (i >= 0 && i < sizeAA) //Check to see if a value from the first or second array is supposed to be added
concatArray[i] = aa[i];
else
concatArray[i] = bb[i - sizeAA];
}
return concatArray;
}
int * subArray(int a[], int start, int length) /* This function takes in
an array, a start value, and a length value. It creates a new array and
copies the values of the original array starting at the passed start value
and continues until the new array is the length of the passed length value.
It returns a pointer to the new array*/
{
//Create new array size
int subSize = length;
//Create a new array
int* sub;
sub = new int[subSize];
//Add elements of original array starting at the passed start value into new
array until the new array is the length specified by the argument
for (int i = 0; i < subSize; i++)
{
sub[i] = a[start];
start += 1;
}
return sub;
}
Your set up is very good. Glad to see you're getting the hang of it. Your functions could use some optimization, however. Before we begin, Id 'd like to note that C++ has a std::vector class which dynamically allocates memory as needed and supplies many powerful mod functions. I'd recommend checking that out as it would take your program to the next level.
To begin, Your Expand()function is pretty well set up. Just some minor modifications: to clean up your code,
int* aaNew;
int newSize = size * 2;
aaNew = new int[newSize];
can simply become:
int newSize = size * 2;
int *aaNew = new int[newSize];
and within your for loop, there is no need to check the complete range of i, only its upper bound:
if (i >= 0 && i < size)
can become:
if (i < size)
This will have the same result as your if-statement but is more elegant since i will never be less than 0.
Moving on, your concatenate() function could become a lot simpler. While what you are doing is technically correct and works, your concatenate() function could simplify to:
int * concatenate(int aa[], int sizeAA, int bb[], int sizeBB) {
int * result = new int[sizeAA + sizeBB];
copy(aa, aa + sizeAA, result);
copy(bb, bb + sizeBB, result + sizeAA);
return result;
}
Furthermore, in your subArray() function, you can reduce:
//Create new array size
int subSize = length;
//Create a new array
int* sub;
sub = new int[subSize];
to:
//Create new array size
int subSize = length;
int *sub = new int[subSize];
Lastly, your main function could use an overhaul. Consider adding a writeArray() function since you are repeating that task often:
string writeArray(int ar[], int arLength) {
string ret = "";
for (int i = 0; i < arLength; i++)
ret += " " + to_string(i);
return ret + "\n";
}
That way your main() can become:
int main() {
//Declare variables
const int SIZEAA = 10, SIZEBB = 5;
int aa[SIZEAA] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int bb[SIZEBB] = { 11, 22, 33, 44, 55 };
//Output both original arrays
cout << "aa[10]: " << writeArray(aa, SIZEAA);
cout << "bb[5]: " << writeArray(bb, SIZEBB);
//Call the Expand function
int *aaExpand = Expand(aa, SIZEAA);
cout << "Testing Expand: " << writeArray(aaExpand, SIZEAA * 2);
//Call the concatenate function
int *concatenateArray = concatenate(aa, SIZEAA, bb, SIZEBB);
cout << "Testing concatenate: " << writeArray(concatenateArray,
(SIZEAA + SIZEBB));
//Call subArray function
int *arraySub = subArray(aa, 5, 4);
cout << "Testing subArray: " << writeArray(arraySub, 4);
//Output the sub array
//Release dynamic memory
delete[] aaExpand;
delete[] concatenateArray;
delete[] arraySub;
aaExpand = nullptr;
concatenateArray = nullptr;
arraySub = nullptr;
}
The rest of your program looks decent. Keep up the good work!
int* Expand(int elements[], int size)
{
int* new_elements = new int[2 * size];
for (int i = 0; i < size; i++)
{
new_elements[i] = elements[i];
new_elements[i + size] = -1;
}
return new_elements;
}
int* concatenate(int first[], int firstSize, int second[], int secondSize)
{
int* elements = new int[firstSize + secondSize];
for (int i = 0; i < firstSize; i++)
{
elements[i] = first[i];
}
for (int j = 0; i < secondSize; j++)
{
elements[firstSize + j] = second[j];
}
return elements;
}
int* subArray(int elements[], int offset, int size)
{
int* new_elements = new int[size];
for (int i = 0; i < size; i++)
{
new_elements[i] = elements[offset + i];
}
return new_elements;
}
I am getting a crash error at run time and not sure what exactly to do with the function or how to get the data for it.
FUNCTION DETAILS
Write a function that accepts an int array and size as arguments, then create a new array that is one element bigger than the given. Setting the first element to 0, then copying over what is in the argument array to the new array.
MAIN DETAILS
Use in a program reading int n from input, then read int n from file data name data
passing it to element shifter, then printing it to output (one per line).
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
int main() {
fstream infile;
infile.open("D:\\data.txt");
int n, x;
infile >> x;
cout << "size of array: ";
cin >> n;
const int ARRAY_SIZE = n + x;
int elements[ARRAY_SIZE];
element_shift(elements, ARRAY_SIZE);
system("PAUSE");
return EXIT_SUCCESS;
}
First of all ARRAY_SIZE declared in the main function is not a constant variable but defined at run-time depending on user inputs. This means that the array elements should be created dynamically. On the other hand you read some x variable which is only used to define the size of the array and didn't initialized the array at all. I guess that the problem statement is to read the size of the array from the input, then the data of the array from the file.
There are also lot of mistakes in element_shift function.
Your code should look like something similar to this:
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
void element_shift(int* elmts, int size)
{
int new_size = size + 1;
int* shifter = new int[new_size];
shifter[0] = 0;
for(int i = 0; i < size; ++i)
{
shifter[i + 1] = elmts[i];
}
delete [] elmts;
elmts = shifter;
}
int main()
{
fstream infile;
infile.open("D:\\data.txt");
int n;
cout << "size of array: ";
cin >> n;
int* elements = new int[n];
for (int i = 0; i < n; ++i) {
infile >> elements[i];
}
element_shift(elements, n);
for (int i = 0; i < n; ++i) {
std::cout << elements[i] << std::endl;
}
return EXIT_SUCCESS;
}
First off, you spend alot of time creating the shifted array but don't return it back.
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
The elmt_sft pointer is never assigned. You are trying to access memory that is not there by using *elmt_sft. This may be causing your error. Also this function has no way of returning the new array shifter because that variable is locally declared and will disappear once the function exits. If you want to create something new in the function and still have it in memory once the function exits, I recommend creating the array dynamically and returning a pointer to it.
This is untested but should start you in the right direction. It will return a separate dynamically allocated array that will not override your other one.
int* element_shift(int elmts[], int size) {
int *result_array = new int[size + 1]; //dynamically create new array MAKE SURE TO DELETE
result_array[0] = 0; //set 0 index to 0
for (int i = 1; i < size + 1; i++)//start at 1 of the result and put value in
{
result_array[i] = elmts[i - 1];
}
return result_array; //returning pointer
}