I wanted to write a function which upon being called deletes an element from an array given that the parameters passed in the deleteArray function were the array, its length and the value of the element to be deleted.
Tried breaking out of the for loop while transversing through the array if the element was found and then tried using i's value in another for loop to replace the current elements with their next element.
like array[j] = array[j + 1]
Here is the code:
#include <iostream>
using namespace std;
void deleteElement(int[], int, int);
int main() {
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
cout << "\nIn main function\n";
for (int i = 0; i < length; i++) {
cout << array1[i];
}
return 0;
}
void deleteElement(int array2[], int length, int element) {
int i = 0;
for (int i; i < length; i++) {
if (array2[i] == element) {
for (int j = i; j < length; j++) {
array2[j] = array2[j + 1];
}
break;
}
}
if (i == (length - 1)) {
cout << ("Element doesn't exist\n");
}
cout << "Testing OP in deleteElement\n";
for (int i = 0; i < length; i++) {
cout << array2[i];
}
}
Expected:
Testing OP in deleteElement
14356
In main function
1356
Actual:
Testing OP in deleteElement
14356
In main function
14356
The problem is rather silly:
At the beginning of deleteElement(), you define i with int i = 0;, but you redefine another variable i as a local index in each for loop. The for loop introduces a new scope, so the int i definition in the first clause of the for loop defines a new i, that shadows the variable with the same name defined in an outer scope.
for (int i; i < length; i++) {
And you do not initialize this new i variable.
There are 2 consequences:
undefined behavior in the first loop as i is uninitialized. The comparison i < length might fail right away.
the test if (i == (length - 1)) { tests the outer i variable, not the one that for iterated on. Furthermore, the test should be if (i == length) {
There are other issues:
the nested for loop iterates once too many times: when j == length - 1, accessing array[j + 1] has undefined behavior.
you do not update length, so the last element of the array is duplicated. You must pass length by reference so it is updated in the caller's scope.
Here is a corrected version:
#include <iostream>
using namespace std;
void deleteElement(int array2[], int& length, int element);
int main() {
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, &length, 4);
cout << "\nIn main function\n";
for (int i = 0; i < length; i++) {
cout << array1[i] << " ";
}
return 0;
}
void deleteElement(int array2[], int& length, int element) {
int i;
for (i = 0; i < length; i++) {
if (array2[i] == element)
break;
}
if (i == length) {
cout << "Element doesn't exist\n";
} else {
length -= 1;
for (; i < length; i++) {
array2[i] = array2[i + 1];
}
}
cout << "Testing OP in deleteElement\n";
for (i = 0; i < length; i++) {
cout << array2[i] << " ";
}
}
If you use the algorithm function std::remove, you can accomplish this in one or two lines of code without writing any loops whatsoever.
#include <algorithm>
#include <iostream>
void deleteElement(int array2[], int& length, int element)
{
int *ptr = std::remove(array2, array2 + length, element);
length = std::distance(array2, ptr);
}
int main()
{
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
for (int i = 0; i < length; ++i)
std::cout << array1[i];
}
Output:
1356
Note that we could have written the deleteElement function in a single line:
void deleteElement(int array2[], int& length, int element)
{
length = std::distance(array2, std::remove(array2, array2 + length, element));
}
Basically, std::remove moves the removed element to the end of the sequence, and returns a pointer to the beginning of the removed elements.
Thus to get the distance from the beginning of the array to where the removed elements are located, usage of std::distance is done to give us our new length.
To remove only the first found element, std::find can be used, and then std::copy over the elements, essentially wiping out the item:
void deleteElement(int array2[], int& length, int element)
{
int *ptr = std::find(array2, array2 + length, element);
if ( ptr != array2 + length )
{
std::copy(ptr+1,array2 + length, ptr);
--length;
}
}
int main()
{
int array1[] = { 1, 4, 3, 5, 4, 6, 9 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
for (int i = 0; i < length; ++i)
std::cout << array1[i];
}
Output:
135469
There is no need for multiple loops in deleteElement. Additionally, your removal will fail to remove all elements (e.g. 4 in your example) if your array contains more than one 4, e.g.
int array1[] = { 1, 4, 3, 4, 5 };
You can simplify your deleteElement function and handle removing multiple occurrences of element simply by keeping a count of the number of times the element is found and by using your counter as a flag to control removal, e.g.:
void deleteElement(int array2[], int& length, int element)
{
int found = 0; /* flag indicating no. element found */
for (int i = 0; i < length; i++) { /* iterate over each element */
if (array2[i] == element) { /* check if matches current */
found += 1; /* increment number found */
continue; /* get next element */
}
if (found) /* if matching element found */
array2[i-found] = array2[i]; /* overwrite elements to end */
}
length -= found; /* update length based on no. found & removed */
}
Updating your example main() to show both pre-delete and post-delete, you could do something like the following:
int main (void) {
int array1[] = { 1, 4, 3, 4, 5 };
int length = sizeof array1 / sizeof *array1; //For length of array
cout << "\nBefore Delete\n";
for (int i = 0; i < length; i++)
cout << " " << array1[i];
cout << '\n';
deleteElement(array1, length, 4);
cout << "\nAfter Delete\n";
for (int i = 0; i < length; i++)
cout << " " << array1[i];
cout << '\n';
}
Example Use/Output
Which in the case where you array contains 1, 4, 3, 4, 5 would result in:
$ ./bin/array_del_elem
Before Delete
1 4 3 4 5
After Delete
1 3 5
While you are using an array of type int (of which there are many in both legacy and current code), for new code you should make use of the containers library (e.g. array or vector, etc...) which provide built in member functions to .erase() elements without you having to reinvent the wheel.
Look things over and let me know if you have further questions.
This is because the length of the array is never updated after deleting. Logically the length should decrease by 1 if the element was deleted.
To fix this, either
Pass the length by reference and decrease it by 1 if the element is actually deleted. OR
Return from the deleteElement some value which indicates that the element was deleted. And based of that, decrease the value of length in the main function.
Recalculating the array length will not help because the element is not actually deleted in memory. So the memory allocated to he array remains same.
Other issues:
The first for loop in deleteElement should run till j < length - 1.
The for loop creates a local variable i, which shadows the i variable in outer scope, so the outer i is never updated and always remains = 0
Related
Completely new to C++. Programmed selection sort on 1D array of arbitrary length. Want to allow user to keep inputting integers into console to make an array of desired length, to be subsequently sorted.
Can only seem to make arrays of length 2 using a while loop for adding elements. Code and example of erroneous result when inputting 6, 2, 3, and 9 shown below.
Script:
// Preprocessor directives and namespace declaration
#include <iostream>
#include <vector>
using namespace std;
// Function
void SelectionSort(int *arr, int len)
{
// Loop through index j in arr
for (int j = 0; j < len; j++) {
// Assume element j is minimum, and initialise minIndex
int min = arr[j];
int minIndex = j;
// Loop through comparisons to determine actual minimum
// (of elements after and including j)
for (int i = j; i < len; i++)
{
if (min > arr[i])
{
min = arr[i];
minIndex = i;
}
}
// Swap minimum with element j
int temp = arr[j];
arr[j] = min;
arr[minIndex] = temp;
}
// Display resulting array
for (int i = 0; i + 1 < len; i++)
{
cout << arr[i] << ", ";
}
cout << arr[len - 1] << endl;
}
// Main
int main()
{
// Explain program to user
cout << "Sort 1D array of user-inputted length/contents" << endl;
cout << "To finish array, enter -999" << endl;
// Initialise dynamic array
vector<int> vDyn (1);
vDyn[0] = 0;
cout << "Enter first element of array: ";
int firstElement = 0;
cin >> firstElement;
vDyn[0] = firstElement;
// Loop to define elements until desired length reached
bool keepGoing = true;
while (keepGoing == true)
{
cout << "Enter another element: ";
int newElement = 0;
cin >> newElement;
if (newElement != -999)
{
vDyn.push_back(newElement);
} else
{
keepGoing = false;
}
}
// Convert vector to array (dynamic to static)
int* v = &vDyn[0];
// Get array length
int len = sizeof(v) / sizeof(v[0]);
// Run SelectionSort function
SelectionSort(v, len);
return 0;
}
Terminal:
Sort 1D array of user-inputted length/contents
To finish array, enter -999
Enter first element of array: 6
Enter another element: 2
Enter another element: 3
Enter another element: 9
Enter another element: -999
2, 6
This declaration
int len = sizeof(v) / sizeof(v[0]);
is equivalent to the declaration
int len = sizeof( int * ) / sizeof( int );
because the variable v is declared like
int* v = &vDyn[0];
The size of a pointer is equal usually to 4 or 8 bytes. So the variable length will have the value either 1 or 2 and does not depend on the number of elements stored in the vector..
Instead you should use for example
size_t len = vDyn.size();
You could declare the function like
void SelectionSort(int *arr, size_t len);
and call it like
SelectionSort( vDyn.data(), vDyn.size() );
Also as in C++ there is standard function std::swap declared in the header <utility> then instead of this code snippet
// Swap minimum with element j
int temp = arr[j];
arr[j] = min;
arr[minIndex] = temp;
you could just write
if ( j != minIndex ) std::swap( arr[j], arr[minIndex] );
And the inner for loop could look like
for ( size_t i = j + 1; i < len; i++)
^^^^^
In fact your function SelectionSort is a C function. A C++ function should be more general and use iterators. In this case it could sort arrays along with other containers.
Here is a demonstration program that shows a more general function called for an array based on a vector.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
template <typename ForwardIterator>
void SelectionSort( ForwardIterator first, ForwardIterator last )
{
for ( ; first != last; ++first )
{
auto current_min = first;
for ( auto next = std::next( first ); next != last; ++next )
{
if ( *next < *current_min ) current_min = next;
}
if ( current_min != first )
{
std::iter_swap( current_min, first );
}
}
}
int main()
{
std::vector<int> v = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
SelectionSort( v.data(), v.data() + v.size() );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
In general you need also to write an overloaded function that accepts also a comparison function.
// Convert vector to array (dynamic to static)
int* v = &vDyn[0];
This line doesn't convert the array to anything. You merely take address of the first element in the vector.
If you want to take an underlying c-array from std::vector you are supposed to use data property of it.
Also, since the array is decayed into a pointer, it no longer contains data of its size. You should rely on std::vector properties (i.e. std::vector::size) to pass this information forward
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;
}
This should be really simple, but I'm used to higher level languages and am missing something. I'm just trying to make sure the input is five numbers long, and then find the highest number. Unfortunately, something goes wrong in that second part.
#include <iostream>
#include <string>
bool isFiveDigits(int num) {
if (std::to_string(num).length() == 5) {
return true;
} else {
return false;
}
}
int highestInArr(int *nums) {
int highest = nums[0];
for (int i = 1; i < sizeof(nums); i++) {
int temp = nums[i];
if (temp > highest) {
highest = temp;
}
}
return highest;
}
int main() {
using namespace std;
int num;
int nums [5];
cout << "Enter a five digit number!\n";
cin >> num;
if (!isFiveDigits(num)) {
cout << "Not five digits, can you even count?";
return 1;
}
string numstr = to_string(num);
for (int i = 0; i < numstr.length(); i++) {
cout << numstr[i] << " ";
nums[i] = (int)numstr[i];
}
cout << "\n" << highestInArr(nums);
}
When this runs, I get:
Enter a five digit number!
12345
1 2 3 4 5
1424080487
Of course, 1,424,080,487 is not in [1, 2, 3, 4, 5].
You cannot pass a pointer into a function and get the size of it without template deduction. At runtime, all the function receives is a pointer. When you call sizeof(nums), you are not getting the size of the original array. You are simply getting the size of the pointer, which is the same as saying sizeof(int_ptr). Instead, you should be using a std::vector when using collections whose sizes are dynamic.
Now, you CAN receive the size by doing something like this:
#include <iostream>
template<typename num_t, size_t N>
num_t max_num(num_t(&arr)[N]) {
num_t m = (num_t)0;
for (size_t i = 0; i < N; ++i)
if (arr[i] > m)
m = arr[i];
return m;
}
int main(){
int foo[] = { 1, 5, 2, 4, 3 };
int m = max_num(foo);
std::cout << m << std::endl;
std::cin.get();
return 0;
}
However, this is not necessarily preferred and assumes that the array was created on the caller's stack. It does not work for dynamically allocated arrays that were created with new[]. If you do this multiple times with different sizes, you will have multiple implementations of the same function (that's what templates do). The same goes for using an std::array<int, N>. If you use N as a size_t template parameter, it will do the same thing.
There are two preferred options:
Send the size of the array into the function so that the caller is responsible for the size.
Use a different container such as std::vector so the callee is responsible for the size.
Example:
#include <vector>
#include <iostream>
#include <algorithm>
int main(){
std::vector<int> vec{ 1, 5, 2, 4, 3 };
int m = *std::max_element(std::cbegin(vec), std::cend(vec));
std::cout << m << std::endl;
std::cin.get();
return 0;
}
As for the is_5_digits, you should use the base-10 logarithm function.
#include <cmath>
// ...
int i = 12345;
size_t length = (i > 0 ? (int)log10(i) : 0) + 1;
std::cout << length << std::endl; // prints 5;
First of all, you can't simply convert a char to int just like (int)numstr[i] assuming that it will return the digit which it contains.
See, if you have a char '0', it means it's ASCII equivalent is stored, which is 48 in case of 0, 49 in case of '1' and so on.
So in order to get that digit (0,1,2,...,9), you've to substract 48 from the ASCII value.
So change this line:
nums[i] = (int)numstr[i];
to:
nums[i] = (int)numstr[i] - 48; // or nums[i] = (int)numstr[i] - '0';
And another thing, in your highestInArr function, you're getting a pointer as parameter, and in the function, you're using sizeof to determine the size of the array. You can't simply do that, the sizeof will return the size of int*, which is not the size of the array, so you've to pass size as the second argument to the function, and use it in the loop.
Like this:
int highestInArr(int *nums, int size) {
// ...
for (int i = 1; i < size; i++) {
// ...
}
// ...
}
My program have to sort an array in another array.
When I run the program it prints 1 2 3 -858993460 5 -858993460 7.
I can not understand where the mistake is in the code.
#include <iostream>
using namespace std;
int main()
{
const int N = 7;
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int max = arr[0];
for (int i = 1; i < N; i++)
{
if (max < arr[i])
max = arr[i];
}
int sort_arr[N];
for (int j = 0; j < N; j++)
{
sort_arr[arr[j] - 1] = arr[j];
}
for (int i = 0; i < N; i++)
{
cout << sort_arr[i] << " ";
}
return 0;
}
Okay lets face the problems in your code.
The "weird" numbers you see there, came from the uninitialzied array sort_arr. What do I mean by uninitialized? Well sort_arr is a little chunck somewhere in your memory. Since a program usually does not clear its memory and rather claims the memory it used as free, the chunk of sort_arr may contain bits and bytes set by another program. The numbers occure since these bytes are interpreted as an integer value. So the first thing to do would be to initialize the array before using it.
sort_arr[N] = { 0, 0, 0, 0, 0, 0, 0 };
Now why did these numbers occure? Well you're probably expecting your algorithm to set all values in sort_arr which would result in an sorted array, right? Well but your algorithm isn't working that well. See this line:
sort_arr[arr[j] - 1] = arr[j];
What happens when j is 1? arr[1] is then evaluated to 17 and 17 - 1 equals 16. So sort_arr[arr[1] - 1] is the same as sort_arr[16] which exceeds the bounds of your array.
If you want to program a sorting algorithm by your self than I would recommend to start with an simple bubble sort algorithm. Otherwise, if you only need to sort the array have a look at the algorithm header. It is fairly simple to use:
#include <iostream>
#include <algorithm>
#include <iterator> // << include this to use begin() and end()
using namespace std;
int main()
{
const int N = 7;
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int sort_arr[N] = { 0, 0, 0, 0, 0, 0, 0 };
copy(begin(arr), end(arr), begin(sort_arr));
sort(begin(sort_arr), end(sort_arr));
for (int i = 0; i < N; i++)
{
cout << sort_arr[i] << " ";
}
cout << endl;
}
By the way. You're looking for the biggest value in your array, right? After you have sorted the array sort_arr[N - 1] is the biggest value contained in your array.
If you want to sort a array into another array then one way is you make a copy of the array and then use the sort function in the standard library to sort the second array.
int arr[10];
int b[10];
for(int i=0;i<10;i++)
{
cin>>arr[i];
b[i]=arr[i];
}
sort(b,b+10);
// this sort function will sort the array elements in ascending order and if you want to change the order then just add a comparison function as third arguement to the sort function.
It seems that you think that sort_arr[arr[j] - 1] = arr[j] will sort arr into sort_arr. It won't.
Sorting is already written for you here: http://en.cppreference.com/w/cpp/algorithm/sort You can use that like this:
copy(cbegin(arr), cend(arr), begin(sort_arr));
sort(begin(sort_arr), end(sort_arr));
Live Example
My guess is this is an attempt to implement a type of counting sort. Note that variable length arrays aren't normally allowed in C++ or some versions of C. You could use _alloca() to allocate off the stack to get the equivalent of a variable length array: int * sort_arr = (int *)_alloca(max * sizeof(int)); .
#include <iostream>
using namespace std;
int main()
{
const int N = 7;
// assuming range of values is 1 to ...
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int max = arr[0];
for (int i = 1; i < N; i++)
{
if (max < arr[i])
max = arr[i];
}
int sort_arr[max];
for (int i = 0; i < max; i++)
{
sort_arr[i] = 0;
}
for (int j = 0; j < N; j++)
{
sort_arr[arr[j] - 1]++;
}
for (int i = 0; i < max; i++)
{
while(sort_arr[i])
{
cout << i+1 << " ";
sort_arr[i]--;
}
}
return 0;
}
With the help of SO members, the following program successfully converts a static 1D array into a 2D vector by considering below criteria:
Each time an element with value = 0 is encountered, a new row is created. Basically when a 0 is encountered, row value is increased and column value is reset to 0. If a non-zero value is encountered, the row value is maintained and column value is increased.
// declarations
int givenArray[9] = {1, 2, 3, 0, 4, 0, 1, 2, 1};
std::vector<int>::size_type j;
std::vector<int>::size_type i;
vector<vector<int>> my2dArray;
vector<int> dArray;
void calc(vector<int>&, int);
int task;
int sum = 0;
int main() {
for (int i = 0; i < 9;
i++) // iterate through all elements of the given array
{
if (i == 0) // adding the first element
{
my2dArray.resize(my2dArray.size() + 1);
my2dArray.back().push_back(givenArray[i]);
continue;
}
if (givenArray[i] == 0) // re-size if 0 is encountered
{
my2dArray.resize(my2dArray.size() + 1);
}
my2dArray.back().push_back(givenArray[i]);
}
for (std::vector<std::vector<int>>::size_type i = 0; i < my2dArray.size();
i++) {
for (std::vector<int>::size_type j = 0; j < my2dArray[i].size(); j++) {
std::cout << my2dArray[i][j] << ' ';
if (my2dArray[i].size() > 2) {
task = my2dArray[i].size();
calc(my2dArray[i], task);
}
}
std::cout << std::endl;
}
}
void calc(vector<int>& dArray, int task) {
int max = 0;
for (unsigned int j = 0; j < task; j++) {
if (dArray[i] > max)
dArray[i] = max;
}
cout << "\nMax is" << max;
}
However, I want to pass a single row of 2D vector 2dArray to function calc if the number of columns for each row exceeds 2. Function calc aims to find maximum value of all the elements in the passed row. The above program doesn't yield the desired output.
Some improvements:
i and j global variables are not needed, you are declaring the variables of the loops in the loop initialization (ex: for (int i = 0; i < 9; i++), the same for the other loops).
It's better not to used global variables, only when strictly necessary (with careful analysis of why). In this case it's not necessary.
The typedef are for more easy access to inner typedef of the type (ex: size_type).
You were doing the call to calc method in every iteration of the inner loop, and iterating over the same row multiple times, this call should be executed once per row.
Using the size of array givenArray as constant in the code is not recommended, later you could add some elements to the array and forgot to update that constant, it's better to declare a variable and calculated generally (with sizeof).
There is no need to pass the size of the vector to method calc if you are passing the vector.
As recommended earlier it's better to use std::max_element of algorithm header.
If you could use C++11 the givenArray could be converted to an std::vector<int> and maintain the easy initialization.
Code (Tested in GCC 4.9.0)
#include <vector>
#include <iostream>
using namespace std;
typedef std::vector<int> list_t;
typedef std::vector<list_t> list2d_t;
void calc(list_t& dArray, long& actual_max) {
for (unsigned int j = 0; j < dArray.size(); j++) {
if (dArray[j] > actual_max) {
actual_max = dArray[j];
}
}
cout << "Max is " << actual_max << "\n";
}
void calc(list_t& dArray) {
long actual_max = 0;
for (unsigned int j = 0; j < dArray.size(); j++) {
if (dArray[j] > actual_max) {
actual_max = dArray[j];
}
}
cout << "Max is " << actual_max << "\n";
}
int main() {
int givenArray[9] = {1, 2, 3, 0, 4, 0, 1, 2, 1};
int givenArraySize = sizeof(givenArray) / sizeof(givenArray[0]);
list2d_t my2dArray(1);
list_t dArray;
for (int i = 0; i < givenArraySize; i++) {
if (givenArray[i] == 0) {
my2dArray.push_back(list_t());
} else {
my2dArray.back().push_back(givenArray[i]);
}
}
long max = 0;
for (list2d_t::size_type i = 0; i < my2dArray.size(); i++) {
for (list_t::size_type j = 0; j < my2dArray[i].size(); j++) {
std::cout << my2dArray[i][j] << ' ';
}
std::cout << "\n";
if (my2dArray[i].size() > 2) {
// if you need the max of all the elements in rows with size > 2 uncoment bellow and comment other call
// calc(my2dArray[i], max);
calc(my2dArray[i]);
}
}
}
Obtained Output:
1 2 3
Max is 3
4
1 2 1
Max is 2
You have a few problems:
You don't need to loop over j in the main function - your calc function already does this.
Your calc function loops over j, but uses the global variable i when accessing the array.
Your calc function assigns the current max value to the array, rather than assigning the array value to max
Function calc aims to find maximum value of all the elements in the passed row. The above program doesn't yield the desired output.
Instead of writing a function, you could have used std::max_element.
#include <algorithm>
//...
int maxVal = *std::max_element(my2dArray[i].begin(), my2dArray[i].begin() + task);
cout << "\Max is " << maxVal;