Why does an array of pointers initializes itself when function finishes? - c++

My weekend assignment was to make a function that gets an array of integers and the size of the array, and creates an array of pointers so that the pointers will be sorted using bubble sort (without changing the original array).
While debugging I found out that it works just fine, but when the function goes back to main() the pointers array gets initialized and everything's gone.
#include <iostream>
using namespace std;
void pointerSort(int arr[], int size, int* pointers[]);
void swap(int a, int b);
void main()
{
int arr[5]={7,2,5,9,4};
int size = 5;
int* pointers[5];
pointerSort(arr, size, pointers);
for (int i = 0; i < 5 ; i++)
cout << *pointers[i] << endl;
}
void pointerSort(int arr[], int size, int* pointers[])
{
int j, i;
bool change = true;
pointers = new int*[size];
for (i = 0; i < size; i++)
pointers[i] = &arr[i];
i = 0;
j = 1;
while (i <= size-1 && change == true)
{
change = false;
for (i = 0; i < size-j; i++)
{
if (*pointers[i] > *pointers[i+1])
{
swap(pointers[i], pointers[i+1]);
change = true;
}
}
j++;
}
}
void swap(int&a, int&b)
{
int temp;
temp = a;
a = b;
b = temp;
}

pointers = new int*[size];
At this point pointers is already an array of pointers, no allocation is needed.
After this line pointers IS NO LONGER THE ARRAY IN YOUR MAIN FUNCTION.
This is why your function is failing, because you are reassigning the array to which pointers is pointing to. The original array ISNT getting reinitialized, its just ignored throughout the entire code.
It is also a memory leak as ATaylor mentions, since you do not delete the allocated space, and cannot delete the space after the function finishes.
To fix everything: just remove the above line.

Related

return a dynamically allocated array of the same length but with the elements in the reverse order

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.

c++ Increase pointer size without return new pointer

My teacher has me complete this(the main is hidden) and i wonder why i got an infinite loop with this solution.
Task:
Complete this function:
void pad_left(char *a, int n) {
}
// if length of a greater than n, do nothing
// else insert '_' util a 's length is n
Some case i got an segmentfault
I try realloc but it return new ptr
My solution
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void printChar(char *a) {
int i = 0;
while(a[i] != '\0') cout << a[i];
cout << endl;
}
void insert_begin(char *a, int n) {
for(int i = n; i > 0; i--) {
a[i] = a[i-1];
}
a[n+1] = '\0';
}
void pad_left(char *a, int n) {
int len = n - strlen(a);
for(int i = 0; i < len; i++) {
insert_begin(a, strlen(a));
}
}
Here is full code
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void printChar(char *a) {
int i = 0;
while(a[i] != '\0') cout << a[i];
cout << endl;
}
void insert_begin(char *a, int n) {
for(int i = n; i > 0; i--) {
a[i] = a[i-1];
}
a[n+1] = '\0';
}
void pad_left(char *a, int n) {
int len = n - strlen(a);
for(int i = 0; i < len; i++) {
insert_begin(a, strlen(a));
}
}
int main() {
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char a[5] = "test";
pad_left(a, 10);
printChar(a);
return 0;
}
Okay, you need some background information.
void pad_left(char *a, int n) {
}
char a[5] = "test";
pad_left(a, 10);
This is going to be a significant problem. First, you can't realloc for two reasons. First, char a[5] is a fixed array -- not an allocated array. When you pass it to pad_left, that doesn't change. realloc() does a free of the old pointer, but you can't do that, and it will cause problems. So you cannot use realloc in your solution unless you make sure the strings came from allocated memory. And you can't assume that.
So put realloc aside. You can't use that.
Next, char a[5] only allocates 5 bytes. If you start writing beyond that range (by passing in 10 to your method), you're going to step on other places. This is absolutely bad.
So... Without testing it, the rest of your code seems reasonable. You can probably get a good test if you do this:
char a[100] = "test";
pad_left(a, 10);
You'll have allocated plenty of space for padding. Try this and see if you get further.

C++ Dynamic data – how to obtain it and how to get rid of it

The code below – it's a skeleton of a program operating on the dynamic collection of data. The idea is to use a structure containing two fields: the first stores the number of elements in collections, and the second is the actual collection (a dynamically allocated vector of ints). As you can see, the collection is filled with the required amount of pseudo-random data.
Unfortunately, the program requires completion, as the most important function.
Here's what i expect from the function:
if the collection is empty, it should allocate a one-element vector and store a new value in it.
if the collection is not empty, it should allocate a new vector with a length greater by one than the current vector, then copy all elements from the old vector to the new one, append a new value to the new vector and finally free up the old vector.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
struct Collection {
int elno;
int *elements;
};
void AddToCollection(Collection &col, int element) {
//the first part of the funtion
if (col.elno==0){
col.elements= new int[1];
col.elements[0]= element;
}
//this is the second part but i do not know how to do it.
//Please help me to complete***************
else {
int *temp;
temp = new[];
}
}
void PrintCollection(Collection col) {
cout << "[ ";
for(int i = 0; i < col.elno; i++)
cout << col.elements[i] << " ";
cout << "]" << endl;
}
int main(void) {
Collection collection = { 0, NULL };
int elems;
cout << "How many elements? ";
cin >> elems;
srand(time(NULL));
for(int i = 0; i < elems; i++)
AddToCollection(collection, rand() % 100 + 1);
PrintCollection(collection);
delete[] collection.elements;
return 0;
}
vector container is originally dynamic container. so u can use vector.
Just declare vector variable in structure and use it in AddToCollection function.
struct Collection {
int elno;
std::vector<int> elements;
};
void AddToCollection(Collection &col, int element) {
col.elements.push_back(element);
col.elno++;
}
like this.
Here is what you are looking for:
void AddToCollection(Collection &col, int element)
{
if(col.elements == NULL)
{
col.elements = new int[1];
col.elements[0] = element;
col.elno = 1;
}
else
{
int *newArr = new int[col.elno+1];
for(int i = 0; i < col.elno; i++)
{
newArr[i] = col.elements[i];
}
newArr[col.elno] = element;
delete[] col.elements;
col.elements = new int[col.elno+1];
for(int i = 0; i < col.elno+1; i++)
{
col.elements[i] = newArr[i];
}
delete[] newArr;
newArr = NULL; // avoid dangling pointer
col.elno++;
}
}
For sure using vector container is a great ideea but the exercise require no modification to the main function. The objective of this exercise is to help the student to understand dynamically allocated memory.

Return an array of compared char pointers in C++ [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
I'm at college and we're learning pointers. Our job was to input a char, compare it to an array and return a pointer to the first reference of that char in the array. But, as I don't like easy things, I've asked my teacher what about having that char more than once in the array.
That's where my headache begins.
So I have this code. The idea is: create a function that compares the input char to the entire array, get the pointers of the references and save them in an array and return that array.
Unfortunately it's not working as I wish :(
What can be wrong?
#include<iostream>
#include<cstdlib>
using namespace std;
char list [10];
int main()
{
initialize();
show();
cout<<search('1');
}
void initialize()
{
int i;
for(i=0; i<10;i++)
{
list[i]='1';
}
}
void show()
{
int i;
for(i=0; i<10;i++)
{
cout<<list[i];
}
}
int* search(char* input)
{
int* result[10];
int i;
char *temp;
for (i=0; i<10; i++)
{
*temp=list[i];
if(strcmp(temp, input) != NULL)
{
result[i]=i;
}
}
return result[];
}
I'm on a mobile device so I can't go into huge detail unfortunately, but you are returning a pointer to an array that you create in the function which goes out of scope at the end of the function.
My massive edit:
As everyone has already stated, a C++ array is actually only a pointer to the first element in the array. As a result, if you return a pointer to an array created in the scope of the function, you are returning a pointer to garbage. If I were doing this I would use a vector, but if I were to be forced into using an array, I would use something like the code below. Hope this helps!
#include <iostream>
#include <cstdlib>
void initialize(char* list) {
for(int i = 0; i < 10; ++i) {
if(i < 4) {
list[i] = '2';
} else {
list[i] = '1';
}
}
}
void show(char *list) {
for(int i = 0; i < 10; ++i) {
std::cout << list[i] << ' ';
}
std::cout << std::endl;
}
// Note the function requires an additional argument that is a pointer
// this is how you can avoid returning a pointer
int search(char input, char* list, char* result) {
int j = 0;
for(int i = 0; i < 10; ++i) {
// comparing characters can be done via ==
if(input == list[i]) {
*(result + j) = list[i];
// You could use result[j], but I used this to show that
// result really is just a pointer to the first element
// of the array. As a result saying result[j] is the same
// as saying I want to deference j elements past the first
// element or *(result + j)
++j; // increment j
}
}
// return how many elements matched
return(j);
}
int main(int argc, char *argv[]) {
char list[10];
char temp[10];
initialize(list);
show(list);
int size = search('1', list, temp);
// create a dynamically sized array containing space for each match
// because we don't know the size at compile time we must use
// a library type or a dynamically sized array
char *result = new char[size];
for(int i = 0; i < size; ++i) {
result[i] = temp[i];
// again you could use result[i]
std::cout << *(result + i) << std::endl;
}
delete[] result; // otherwise you'll get a memory leak
return(0);
}

copying elements from one array to another

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
}