Changing around arrays - c++

I'm doing a lot of different things with manipulating arrays without vectors, I was wondering if any one could help me with shifting elements in an array and expanding an array while initializing the new space with elements. I feel like I'm very close to completing this code, but I'm hitting a block.
#include <iostream>
using namespace std;
// Function prototypes
int *reverse(int *, int);
int *expand(int *, int);
int *shift(int *, int);
void display(int[], int);
void display2(int[], int);
void display3(int[], int);
int main()
{
int const SIZE = 5;
int myArray [SIZE] = {1, 2, 3, 4, 5};
int myArray2 [SIZE] = {1, 2, 3, 4, 5};
int myArray3 [SIZE] = {1, 2, 3, 4, 5};
int *arraPtr;
int *arraPtr2;
int *arraPtr3;
arraPtr = reverse(myArray, SIZE);
display(myArray, SIZE);
arraPtr2 = expand(myArray2, SIZE);
display2(myArray2, SIZE);
arraPtr3 = shift(myArray3, SIZE);
display3(myArray3, SIZE);
delete [] arraPtr;
delete [] arraPtr2;
delete [] arraPtr3;
return 0;
}
int *reverse(int *arr, int size)
{
int *copyArray;
int posChange;
if( size < 0)
return NULL;
copyArray = new int[size];
for (int index = 0; index < --size; index++)
{
posChange = arr[index];
arr[index] = arr[size];
arr[size] = posChange;
}
return copyArray;
}
int *expand(int *arr, int size)
{
int *newArray;
newArray = new int[size * 2];
memcpy( newArray, arr, size * sizeof(int));
for (int index = size; index < (size*2); index++)
newArray[index] = 0;
return newArray;
}
int *shift(int *arr, int size)
{
int *newArray;
newArray = arr;
newArray = new int [size + 1];
for (int index = 5; index > 0; index--)
newArray[index] = newArray[index - 1];
return newArray;
}
void display(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << arr[index] << " ";
}
cout << endl;
}
void display2(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << arr[index] << " ";
}
cout << endl;
}
void display3(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout <<arr[index] << " ";
}
cout << endl;
}

There are only two compile error: int newArray; should be int* newArray; and #include <cstring> is missing (necessary for memcpy())
Also, the line display(myArray, SIZE); was probably meant to be display(arraPtr, SIZE); and likewise display2(myArray2, SIZE); -- otherwise you're only displaying the original arrays, not the results of your function calls.
However, this could benefit from the safer and more generic C++ algorithms, std::copy() and std::reverse_copy() at least:
int *reverse(int *arr, int size)
{
int *copyArray = new int[size];
std::reverse_copy(arr, arr+size, copyArray);
return copyArray;
}
int *expand(int *arr, int size)
{
int *newArray = new int[size * 2]();
std::copy(arr, arr+size, newArray);
return newArray;
}
int *shift(int *arr, int size)
{
int* newArray = new int [size + 1]();
std::copy(arr, arr+size, newArray+1);
return newArray;
}
full program: https://ideone.com/RNFiV

This is mostly C code but I'll try to give you some tips on the methods of what you're doing more than the syntax:
In your reverse function, you never actually put anything into the new array. Instead of doing some swapping in the for loop, you can just run through the original loop backwards putting the elements into the new array.
In the expand function it looks like you're trying to do two opposite things, copy the memory from the input array to the new one and then overwrite the new array with all zeros. If you want to copy the memory manually you need to have the loop only go the original array copying its values into the new array (and not go through double the size of the original array or else you'll walk off the end of it!). If you want to use memcpy then get rid of the for loop.
I'm not sure what you want the shift function to do but it pretty much just copies the array now.

I don't know exactly what did you want to accomplish but I think it was something like this:
#include <iostream>
#include <cstring> // Needed to compile on most compilers(memcpy), dunno in yours
using namespace std;
// Function prototypes
int *reverse(int *, int);
int *expand(int *, int);
int *shift(int *, int);
void display(int[], int);
void display2(int[], int);
int main()
{
int const SIZE = 5;
int myArray [SIZE] = {1, 2, 3, 4, 5};
int myArray2 [SIZE] = {1, 2, 3, 4, 5};
int myArray3 [SIZE] = {1, 2, 3, 4, 5};
int *arraPtr;
int *arraPtr2;
arraPtr = reverse(myArray, SIZE);
display(arraPtr, SIZE);
arraPtr2 = expand(myArray2, SIZE);
display2(arraPtr2, SIZE * 2);
delete [] arraPtr;
delete [] arraPtr2;
return 0;
}
int *reverse(int *arr, int size)
{
int *copyArray;
int posChange;
if( size < 0)
return NULL;
copyArray = new int[size];
for (int index = 0; index <= --size; index++)
{
posChange = arr[index];
copyArray[index] = arr[size];
copyArray[size] = posChange;
}
return copyArray;
}
int *expand(int *arr, int size)
{
int *newArray;
newArray = new int[size * 2];
memcpy( newArray, arr, size * sizeof(int));
for (int index = size; index < (size*2); index++)
newArray[index] = 0;
return newArray;
}
int *shift(int *arr, int size)
{
int *newArray;
newArray = new int [size + 1];
memcpy( newArray, arr, size * sizeof(int));
return newArray;
}
void display(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << endl << arr[index] << " ";
}
}
void display2(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << arr[index] << " ";
}
}
As a side note, if you have problems with this kind of stuff you should take a look at any good C resource that talks about pointers and pointer arithmetics, it will come in handy when you have to do low level C++ code.

Related

Is it possible for a function to owerwrite the input array with a smaller one?

The task: Create a function that takes a list of numbers as a parameter, and returns a list of numbers where every number in the list occurs only once
As far as I know, functions can't return arrays. But if a function's parameter is an array, it will be automatically a reference parameter, so it will "overwrite" the input array even if it's a void function. Is there any way to overwrite (as reference parameter) the input array with a smaller one?
To be specific: in the code below I would like to overwrite the number[10] array with the newArray[6]
I just started to learn code this week, this is a practice task for me, so I would like to use C++ basics to solve this one, without pointers and more complex stuff. If it's not possible, it's okay too.
#include <iostream>
#include <string>
void selectionSort(int[], int);
void unique(int[], int);
void print(int[], int);
int main(int argc, char *args[]) {
int numbers[] = {1, 11, 34, 11, 52, 61, 0, 1, 34, 1, 61, 72};
int size = sizeof(numbers) / sizeof(int);
unique(numbers, size);
return 0;
}
void unique(int arr[], int size) {
selectionSort(arr, size);
int newSize = 1;
for (int i = 0; i < size - 1; ++i) {
if (arr[i] < arr[i + 1]) {
newSize++;
}
}
int newArray[newSize];
int index = 0;
for (int i = 0; i < size - 1; ++i) {
if (arr[i] < arr[i + 1]) {
newArray[index] = arr[i];
++index;
}
}
newArray[newSize - 1] = arr[size - 1];
print(newArray, newSize);
}
void selectionSort(int arr[], int size) {
for (int i = 0; i < size; i++) {
int min = i;
for (int j = i; j < size; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
std::swap(arr[i], arr[min]);
}
}
void print(int arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
This is not valid C++:
int newArray[newSize];
That's VLA, which is C99, only available with gcc.
Instead, do:
int* newArray = new int[newSize];
Return this:
return std::make_pair(newArray, newSize);
As you need to return the size as well!! Even if you can overwrite the input array (you can, obviously, depends on your contract, the documentation of your function), you need to return the new size.
But you may want to take a real C++ class.

Dynamic allocation of an array into a function with pointer parameters

I am having issues finishing passing an array via pointers through a series of functions. I create a function using dynamic allocation to create it. Even though that is successful I cannot get it to pass through functions that take pointers as arguments. The functions return the mean median and mode and have been completed. However I cannot pass them when converting them into pointer syntax. Thanks for the help in advance.
#include <iostream>
#include <cstdlib>
using namespace std;
int students;
int * studentarray;
int stumode;
double stuavg;
int stumed;
int arr;
int mode(int *[], int );
double average(int *[], int);
double median(int *[], int);
void selectSort(int [], int);
void swap(int *, int *);
int makeArray(int*, int);
int main()
{
studentarray = &arr;
cout << "How many students are there?" << endl;
cin >> students;
makeArray(studentarray, students);
for (int i = 0; i < students; i++) {
cout << "How many movies did student " << i + 1 << " view?" << endl;
cin >> studentarray[i];
}
selectSort(studentarray, students);
stumode = mode(&studentarray, students);
stuavg = average(&studentarray, students);
stumed = median(&studentarray, students);
cout << "The array has been sorted in ascending order." << endl;
cout << "The mode is " << stumode << "." << endl;
cout << "The mean is " << stuavg << "." << endl;
cout << "The median is " << stumed << "." << endl;
delete[] studentarray;
return 0;
}
int mode(int *arr, int size)
{
if (size <= 0) return 0;
int most = 0, position = 0, most_count = 0;
int counter = 1;
for (int i = 1; i < size; i++)
{
if (* (arr + i) != * (arr + position) )
{
if (counter > most)
{
most = counter;
most_count = 0;
}
else if (counter == most) most_count++;
position = i;
counter = 0;
}
else counter++;
}
if (most_count) return 0;
else return * ( arr + position );
}
double average(int *arr, int size)
{
if (size <= 0) return 0;
int total = 0;
for (int i = 0; i < size; i++) {
total += *(arr + i);
}
return (double)total / size;
}
double median(int *arr, int size)
{
if (size <= 0) return 0;
if (size % 2 == 0)
return (double) (* (arr + (size + 1) / 2));
else {
int mid = size / 2;
return (double)(* (arr + mid) + * (arr + mid + 1) / 2);
}
return 0;
}
void selectSort(int arr[], int size)
{
int min;
for (int i = 0; i < size - 1; i++)
{
min = i;
for (int j = i + 1; j < size; j++)
{
if ( arr[j] < arr[min])
{
min = j;
}
}
swap(&arr[min], &arr[i]);
}
}
void swap(int *one, int *two) {
int temp = *one;
*one = *two;
*two = temp;
}
int makeArray(int *arr, int size)
{
arr = new int[size];
return *arr;
}
Your implementation of makeArray is not right.
int makeArray(int *arr, int size)
{
// Allocates memory and assigns it to arr.
// This is a local change to arr. The value of the variable in
// main remains unchanged.
arr = new int[size];
// Returns an uninitialized value.
return *arr;
// The memory allocated in the previous line is now a memory leak.
}
You can make it simpler by using:
int* makeArray(int size)
{
return new int[size];
}
and use it in main as:
arr = makeArray(students);
However, I don't see how that is better than using:
arr = new int[students];
If you do that, makeArray becomes unnecessary. If makeArray needs to have additional code to fill up the array with some values, it will be useful. Otherwise, it does not add any useful functionality to your program.
Having said all of that, it is better to use std::vector instead of managing dynamically allocated memory in your own code. You would use:
std::vector<int> arr(students);
PS
I did not go through rest of your code. There might be other errors.

Reversing an array using pointers

I have this program that makes and populates an array. Then it is sent to a function called reverse, which reverses the order in the array. The compiler keeps giving errors. I'm not quite sure why.
CODE
void reverse(int* array, int size) {
for (int i = 0; i < size/2; i++) {
int temp = array[i];
array[i] = array[size-i];
array[size-i] = temp;
} // end of for loop
} // end of reverse
int main( int argc, char** argv ) {
int array[8];
// get and print size of the array
int size = sizeof(array) / sizeof(array[0]);
printf("Size is %d\n", size);
// populate array
for (int i = 0; i < size; i++) {
array[i] = i;
} // end of for loop
// display array before reversing
for (int i = 0; i < size; i++) {
printf("%d ", array[i]);
} // end of for loop
// new line
printf("\n");
// reverse the array
reverse(&array, size);
// display the array again after reversing
for (int i = 0;i < size; i++) {
printf("%d ", array[i]);
} // end of for loop
} // end of main
It keeps giving me this error
main.cc:17:14: error: indirection requires pointer operand ('int' invalid)
int temp = *array[i];
^~~~~~~~~
main.cc:18:3: error: indirection requires pointer operand ('int' invalid)
*array[i] = *array[size-i];
^~~~~~~~~
main.cc:18:15: error: indirection requires pointer operand ('int' invalid)
*array[i] = *array[size-i];
^~~~~~~~~~~~~~
main.cc:19:3: error: indirection requires pointer operand ('int' invalid)
*array[size-i] = temp;
^~~~~~~~~~~~~~
4 errors generated.
make: *** [main.o] Error 1
I did solve this problem a little differently, maybe you will use this code:
#include <iostream>
void displayArray(int table[], int size);
void rev(int table[], int size);
void fillTheArray(int table[], int size);
int main(int argc, char** argv) {
int myArray[8];
int size = sizeof(myArray) / sizeof(myArray[0]);
std::cout << "Array size is: " << size << std::endl;
fillTheArray(myArray, size);
displayArray(myArray, size);
std::cout << std::endl;
rev(myArray, size);
displayArray(myArray, size);
std::cin.get();
return 0;
}
void fillTheArray(int table[], int size) {
for (int i = 0; i < size; i++) {
table[i] = i;
}
}
void displayArray(int table[], int size) {
for (int i = 0; i < size; i++) {
std::cout << table[i] << " ";
}
std::cout << std::endl;
}
void rev(int table[], int size) {
int *start = table;
int *end = table + (size - 1);
for (int i = 0; i < size; i++) {
if (start < end) {
int temp = *end;
*end = *start;
*start = temp;
}
start++;
end--;
}
}
I can see two errors in this code. First is: wrong way of passing parametr to function:
// reverse the array
reverse(&array, size);
you should do this just like this(array name is pointer to first element of this array):
reverse(array, size);
Second problem is with reverser - you try to access some random memory outside arrar range:
array[i] = array[size-i];
Remember that in C++ array index's start with 0 not 1. So if your array is size of 8 - largest insext of this array is 7 (0, 1, 2, 3, 4, 5, 6, 7). Your code should look like this:
array[i] = array[size -i -1];
And it should work as you expected.
It is my solution with pointers:
void reverse(int arr[], int count)
{
int* head = arr;
int* tail = arr + count - 1;
for (int i = 0; i < count/2; ++i)
{
if (head < tail)
{
int tmp = *tail;
*tail = *head;
*head = tmp;
head++; tail--;
}
}
for (int i = 0; i < count; ++i)
{
std::cout << arr[i] << " ";
}
}
or just use functions build in C++: std::reverse in 'algorithm' library.
It's a lot of examples on stackoverflow with this kind of examples:
Reverse Contents in Array
You have fixed most of the compiler errors in your code except one.
The line
reverse(&array, size);
should be
reverse(array, size);
After that is fixed, you have to fix logic errors in reverse.
You are using the wrong index for accessing the upper half of the array.
void reverse(int* array, int size) {
for (int i = 0; i < size/2; i++) {
int temp = array[i];
array[i] = array[size-i]; // When i is 0, you are accessing array[size]
// That is incorrect.
array[size-i] = temp;
} // end of for loop
} // end
You need to use
void reverse(int* array, int size) {
for (int i = 0; i < size/2; i++) {
int temp = array[i];
array[i] = array[size-i-1];
array[size-i-1] = temp;
}
}
Another way to approach the algorithm would be to use two indices.
void reverse(int* array, int size) {
for (int i = 0, j = size-1; i < j; ++i, --j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
Working program: http://ideone.com/ReVnGR.
You're passing **int instead of *int to the reverse method:
reverse(&array, size);
Pass it like that:
reverse(array, size);

Removing a specified value from array

I'm trying to create a function which will copy elements from one array to another array, unless a specified variable is mentioned, in which case it will not be copied over. The function will then output the new array without the specified variables included.
int *NewArray(int array[], int len, int num){
int *array2 = new int[len];
int temp;
for(int i=0;i<len;i++){
temp = array[i];
if(temp != num){
array2[i]=temp;
}
else{
array2[i] = array[i+1];
}
}
return array2;
}
The problem with your for loop is that it uses only one index to access both the arrays. You need two indices.
Say the item you want to remove is at index 1. After that, you need to make sure that
array2[i] = array[i+1];
Even though you have such a line, that is used only for the matching item. It does not use that logic for subsequent items.
This is what you need:
for(int i=0, j = 0; i<len; ++j ){
if(num == array[j]){
++j;
// Don't increment i, increment j
// to skip the element from array
}
else {
array2[i] = array[j];
// Increment i since it is being assigned a value from array.
++i;
}
}
You could use std::copy_if as below:
int *NewArray(int array[], int &len, int num) {
int *array2 = new int[len];
auto it = std::copy_if(array, array + len, array2,
[&num](int const i){ return i != num; });
len = std::distance(array2, it);
return array2;
}
Live Demo
Using something like std::vector would be beneficial in your case, but seeing as you may have a valid reason for using arrays, you are going about it in a more complex way than is needed. This is definitely more c-esque syntax, but I think it performs what you want it to do without really getting into any STL libraries.
#include <iostream>
#include <cstdlib>
int *NewArray(const int const array1[], const size_t len, const int num, size_t *newlen) {
int *array2 = new int[len];
size_t counter = 0;
for (int i = 0; i < len; i++)
if (array1[i] != num)
array2[counter++] = array1[i];
*newlen = counter;
return array2;
}
int main(int argc, char **argv) {
int arr1[] = { 1, 2, 3, 4, 5, 6, 7};
size_t oldlen = sizeof arr1 / sizeof(int);
size_t newlen;
int *arr2 = NewArray(arr1, sizeof arr1 / sizeof(int), 3, &newlen);
int i;
for (i = 0; i < newlen; ++i)
std::cout << arr2[i] << std::endl;
delete arr2;
system("pause");
}
Here's how I would do it with a vector.
std::vector<int> NewVector(const std::vector<int> const vec1, const int num) {
std::vector<int> vec2 (vec1.size());
auto it = std::copy_if(
vec1.begin(), // where to start
vec1.end(), // where to end
vec2.begin(), // where to insert
[&num](const int i) { return i != num; } // lambda predicate
);
vec2.resize(std::distance(vec2.begin(), it));
return vec2;
}

Visual Studio pointer error

When I run this code:
#include <iostream>
using namespace std;
void makeArrayBigger(int*, int&, int);
void arrayIni(int*, int, int);
void displayArray(int*, int);
int main(){
int size = 5;
int *arr = new int[5];
arrayIni(arr, size, 0);
//displayArray(arr, size);
makeArrayBigger(arr, size, 8);
//displayArray(arr, size);
arrayIni(arr, size, 1);
system("pause");
return 0;
}
void makeArrayBigger(int *arr, int &size, int newSize){
int *newArr = new int[newSize];
for (int counter = 0; counter < size; counter++){
newArr[counter] = arr[counter];
}
delete[] arr;
arr = new int[newSize];
for (int index = 0; index < size; index++){
arr[index] = newArr[index];
}
delete[] newArr;
size = newSize;
}
void arrayIni(int *arr, int size, int ini){
for (int index = 0; index < size; index++){
arr[index] = ini;
}
}
void displayArray(int *arr, int size){
if(arr == NULL)
return;
for (int counter = 0; counter < size; counter++){
cout << arr[counter] << endl;
}
cout << endl;
}
I get this breakpoint error:
Windows has triggered a breakpoint in pointer.exe.
This may be due to a corruption of the heap, which indicates a bug in pointer.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while pointer.exe has focus.
The reason of this error is that you confused the conception 'Pass by value' with 'Pass by Reference'.
The answer of the following question might be an good reference:
What's the difference between passing by reference vs. passing by value?
The problem will be fixed by replacing the void makeArrayBigger() interface with the following codes
void makeArrayBigger(int* &arr, int &size, int newSize);
Update:
when I pass a pointer I'm passing a pointer that points to that same location.
It is the same location but not the same pointer. Whether delete or malloc the new pointer will not change the value of the actual parameter.
In this case, the arr pointer keeps the same size after makeArrayBigger(). But it will be assumed to be the new size(8) in arrInit().
Pass in a reference to the array (int*) just like you pass a reference to the array size (int). Then you can replace the array with a new array and update the size as you are currently doing:
void resize (int*& array, int& arraySize, int newSize)
{
delete [] array;
arraySize = newSize;
array = new int [arraySize];
}
int main() {
int testSize = 5;
int* testArray = new int [testSize];
// Do stuff
resize (testArray, testSize, 8);
// Do more stuff
delete [] testArray;
testArray = NULL;
testSize = 0;
return 0;
}