Trying to debug and correct a function - c++

#include <iostream>
#include <string>
using namespace std;
// Declaration of the function indexvalue()
int *maxArr(int [], const int);
// Another function used to print out an error message
void
problem(string str) {
cout << str << endl;
exit(1);
}
const int Size = 10;
int main()
{
int a[Size] = {23, 45, 12, 76, 9, 131, 10, 8, 23, 4};
int *b, i;
string error1("Problem with maxArr(), wrong subscript");
string error2("Problem with maxArr(), output should be NULL");
// Call the function multiple times with different input
// Note the use of pointer arithmetic
if (maxArr(a,Size)!= a+5) problem(error1);
if (maxArr(a,Size-5)!= a+3) problem(error1);
if (maxArr(a+6,4)!= a+8) problem(error1);
if (maxArr(a,0)!= NULL) problem(error2);
// The function passed all the tests
cout << "The function passed all the tests in this program\n" << endl;
exit(0);
}
int *maxArr(int arr[], int size){
int max = 0;
int index = 0;
if ( size < 0)
return NULL;
for (int i = 0; i < size; i++) {
if (arr[i] > max )
{
max = arr[i];
index = i;
}
return arr + i;
}
}
Specifications for maxArr()
The function accepts an integer array, and the number of elements as parameters.
The function returns the address of an int which points at the maximum value of the array.
i'm trying to figure out what's wrong with the maxArr() function and the only thing i've corrected so far is changing if(size < 0) to if (size <= 0) to handle the null case, I have no idea how to correct the function to account for the error1 message. Any help would be appreciated.

You have a brackets issue here:
for (int i = 0; i < size; i++) {
if (arr[i] > max )
{
max = arr[i];
index = i;
}
return arr + i;
}
Your return is within the for loop and therefore you will return on the first interation of the loop.
index is not used, you probably want to move the return statement outside the main loop and return arr + index;

You are returning from inside the for loop in the function maxArr. It will always return in the first iteration. Also you should return arr+index instead of arr+i.
for (int i = 0; i < size; i++)
{
if (arr[i] > max )
{
max = arr[i];
index = i;
}
//return arr + i;
// ^^^^ Wrong
}
return arr+index; //return from here
The check for returning NULL will fail with your current condition. You should check like this:
if ( size <= 0)
return NULL;

Related

wrong printed sorted array

I'm new to C++ and I've been doing bubbleSort, but when I want to show the numbers in the terminal, the leading number is a problem. Sorry for my bad english btw.
where am i doing wrong?
this is the code:
#include <iostream>
void printArray(int *myArr, int lenght) {
for (int i = 0; i < lenght; ++i) {
std::cout << myArr[i] << ", ";
}
}
int bubbleSort(int *myArr, int lenght) {
for (int i = 0; i < lenght; ++i) {
for (int j = 0; j < lenght-1; ++j) {
if (myArr[j] > myArr[j+1]) {
int temp = myArr[j];
myArr[j] = myArr[j+1];
myArr[j+1] = temp;
}
}
}
return *myArr;
}
int main() {
int myArr[] = {10,14,13,19,15,12,16,18,17,11};
int newArr = bubbleSort(myArr, 8);
printArray(&newArr, 8);
return 0;
}
this is what i get:
10, 10, 12, 13, 14, 15, 16, 18, there is no 19 and double 10s
and is there any eaiser way to get lenght of array in function? Thank you...
The problem is that you are confusing pointers with arrays with single integers.
int bubbleSort(int *myArr, int lenght) {
// ... not actually that important what happens here ...
return *myArr;
}
Your bubbleSort gets a pointer to first element of an array passed, you do some sorting and eventually you return the first element of that sorted array (return type is int!). This is wrong, or maybe not wrong but doesn't make much sense but the real drama will only come later...
...when here
int newArr = bubbleSort(myArr, 8);
printArray(&newArr, 8);
you copy that single integer returned from bubbleSort into newArr (an int), then take its address (still "ok") and then in printArray act like it points to an array which it doesn't (now it goes BooooM!).
myArr[i] in printArray is undefined behavior when i > 0, because myArr points to a single integer. It does not point to an array.
TL;DR: Do not use c-arrays. c-arrays are advanced C++, they are easy to get wrong and hard to get right. Use std::vector for dynamically sized arrays and std::array for compiletime sized arrays.
This is the idea that should work:
#include <iostream>
#include <vector>
using namespace std;
void printArray(vector<int> arr) {
for (auto & item : arr)
{
cout << item<<' ';
}
}
void bubbleSort(vector<int> &arr)
{
bool swapp = true;
while (swapp) {
swapp = false;
for (size_t i = 0; i < arr.size() - 1; i++) {
if (arr[i] > arr[i + 1]) {
arr[i] += arr[i + 1];
arr[i + 1] = arr[i] - arr[i + 1];
arr[i] -= arr[i + 1];
swapp = true;
}
}
}
}
void main() {
vector<int> arr = { 10,14,13,19,15,12,16,18,17,11 };
bubbleSort(arr);
printArray(arr);
}
Problem is - Wrong array size (i.e. 8) is passed to bubble sort function which produces wrong answer.
Use std::vector sothat superfluous length agrument can be avoided.
void bubbleSort(std::vector<int> & vec) {
for (int i = 0; i < vec.size(); ++i) {
...
}
}
bubbleSort(vec);

Removing odd numbers from an array

I am trying to remove odd numbers from an array, but I'm not allowed to create a new array to store the new values.
So, if I have arr[1,2,3,4,5,6,7,8,9]
then I need it to be arr[2,4,6,8] so that arr[0] will be 2 and not 1.
I can't seem to be able to drop the even numbers without creating a new array to store the values and then feed it back into the original array with the new values.
I have tried to make arr[i] = 0 if its an odd number but then I wasn't able to drop the 0 and replace it with the next even number.
So far, I have this:
void removeOdd(int arr[], int& arrSize){
int i, j = 0;
int temp;
int newArrSize;
for(i = 0, newArrSize = arrSize; i < arrSize; i++){
if(arr[i] % 2 != 0){
arr[i] = 0;
}
}
arrSize = newArrSize;
}
// Moves all even numbers into the beginning of the array in their original order
int removeOdd(int arr[], int arrSize) {
int curr = 0; // keep track of current position to insert next even number into
for (int i = 0; i < arrSize; ++i) {
if (arr[i] % 2 == 0) {
arr[curr++] = arr[i];
}
}
return curr;
}
int main() {
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int newSize = removeOdd(arr, 10);
for (int i = 0; i < newSize; ++i) {
std::cout << arr[i] << " ";
}
}
0 2 4 6 8
You might want to use std::vector:
void removeOdd(std::vector<int>& arr) {
int curr = 0;
for (int i = 0; i < (int)arr.size(); ++i) {
if (arr[i] % 2 == 0) {
arr[curr++] = arr[i];
}
}
arr.resize(curr);
}
int main() {
std::vector<int> arr = { 0,1,2,3,4,5,6,7,8,9 };
removeOdd(arr);
for (int number : arr) {
std::cout << number << " ";
}
}
Normally (unless this is homework of some sort), you should use the algorithms in the <algorithm> header.
Using std::remove_if with std::vector's erase member function, you will accomplish exactly what you want with less code:
std::vector<int> vec{ 1,2,3,4,5,6,7,8,10 };
vec.erase(std::remove_if(std::begin(vec), std::end(vec), [](auto const& i) {
return i % 2 != 0;
}), std::end(vec));
Demo

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.

find max and min of array c++ using recursion without changing function

I need help trying to find the min and max values in an array recursively in c++. the functions were given and cannot be changed.
I tried it out for both but for some reason nothing happens and the code does not enter the loop and I want to know what I am doing wrong. Here is my main and the min and max functions.
int main()
{
int array[] = { 46, 22, 7, 58, 91, 55, 31, 84, 12, 78 };
if (findMax(array, 10) == 91)
{
cout << "findMax is correct!" << endl;
}
if (findMin(array, 10) == 7)
{
cout << "findMin is correct!" << endl;
}
int findMax(int array[], int size)
{
int i = (size - 1);
int max = 0;
if (array[0] < array[i]) {
max = array[i];
findMax(array, size - 1);
}
return max;
return 0;
}
int findMin(int array[], int size)
{
int i = 0;
int j = size - 1;
if (i == j)
{
return array[i];
i++;
}
int temp = findMin(array, size);
if (array[i] < temp)
{
return array[i];
}
else
{
return temp;
}
}
}
Well, you simply go backwards, return the min of each pair of elements and then next level make array size one smaller. Example:
int findMin(int array[], int n)
{
// if size = 0 means whole array has been traversed
if (n == 1){
return array[0];
}
return min(array[n-1], findMin(array, n-1));
}
And you can do the findMax using the same methodology.

removing and shifting duplicates in array c++

I am trying to delete any duplicates but not having much success..
void deleatingRepeatingElement (int myArrayLength, int myArray[])
{
for (int i = 1 ; i < myArrayLength; i++){
// start at second index because you don't need to compare the first element to anything, it can't have duplicate that comes first
for (int j = 0; j < i ; j++){
if (myArray[i] == myArray[j]){
myArray[j] = myArray[j + 1];
myArrayLength--;
}
}
}
}
I think there were two main mistakes:
You didn't shift all of the following items when deleting.
You didn't "reset" after deleting.
Here is annotated code that seems to work:
#include <iostream>
/* Remove element at given index from array
* Returns the new array length
* (Note that "int array[]" means exactly the same as "int *array",
* so some people would consider "int *array" better style)
*/
int arrayRemoveAt(int index, int array[], int arrayLength)
{
// Check whether index is in range
if (index < 0 || index >= arrayLength)
return arrayLength;
for (int i = index + 1; i < arrayLength; i++)
{
array[i - 1] = array[i];
}
return arrayLength - 1;
}
/*
* Returns the new length of the array
*/
int deleatingRepeatingElement(int myArrayLength, int myArray[])
{
for (int i = 1; i < myArrayLength; i++)
{
// start at second index because you don't need to compare the first element to anything, it can't have duplicate that comes first
for (int j = 0; j < i; j++)
{
if (myArray[i] == myArray[j])
{
myArrayLength = arrayRemoveAt(i, myArray, myArrayLength);
// After deleting an entry, we must "reset", because now the index i
// might point to another number, which may be a duplicate
// of a number even before the current j.
// The i-- is so that after i++, we will end up with the same i
i--;
break;
}
}
}
// Important: The caller needs this for looping over the array
return myArrayLength;
}
int main(int argc, char **argv)
{
int array[] = {5, 6, 2, 1, 2, 6, 6};
int newSize = deleatingRepeatingElement(7, array);
for (int i = 0; i < newSize; i++)
{
std::cout << array[i] << std::endl;
}
return 0;
}
If you use a static array (such as in my example, as opposed to a dynamic one), you may consider using std::array or a template construction as shown in https://stackoverflow.com/a/31346972/5420386.
Here is the solution to your problem:
#include <iostream>
#include <set>
#define ARRAY_SIZE(array) (sizeof((array))/sizeof((array[0])))
using namespace std;
int *deleteRepeatedElements(int myArray[], int arrayLength) {
set<int> setArray (myArray, myArray+arrayLength);
int setLength = setArray.size();
static int myPointer[4];
int i = 0;
for (set<int>::iterator it = setArray.begin(); it != setArray.end(); ++it) {
myPointer[i] = *it;
i++;
}
return myPointer;
}
int main() {
int myArray[6] = {5, 3, 5, 6, 2, 4};
int arrayLength = ARRAY_SIZE(myArray);
int* myPointer = deleteRepeatedElements(myArray, arrayLength);
int pointerLength = sizeof(myPointer)/sizeof(*myPointer);
for (int* i = &myPointer[0]; *myPointer != 0; i = ++myPointer) {
cout << *i << " ";
}
cout << '\n';
return 0;
}