I'm working on a program that modifies the data of an array using only pointers. I'm trying to return the index where array[ix]==0. However, I keep getting stuck in an infinite loop. What am I doing wrong?
int firstprime(int size, int arr[]){
int* end = arr + size;
int* begin = arr;
while(begin<end){
if(*begin==0)
return *begin;
begin++;
}
return -1;
}
You can use std::distance quite easily to get the index.
More info on std::distance here
Btw, the function name is also very misleading. If the function is meant to return the index of a value in the array, then consider changing that function name, like getIndex() or find(). Just pick something more meaningful.
#include <iostream>
int firstprime(int size, int *arr)
{
int *begin = arr;
int *end = begin + size;
while( begin < end )
{
if(*begin==0)
return std::distance(arr, begin);
begin++;
}
return -1;
}
int main()
{
int array[10] = {1,2,3,4,0,6,7,8,9,10};
int p = firstprime(10, array);
std::cout<< "0 found at index: " << p <<std::endl;
}
The result is:
0 found at index: 4
Online example: https://rextester.com/KVCL75042
To get the "distance" between two pointers (in the number of elements) you can either use std::distance:
return std::distance(arr, begin); // Return the distance between current element and the beginning of the array
You can also subtract the pointers:
return begin - arr; // Return the distance between the current element and the beginning of the array
The "distance" returned by the above two statements will be in the number of elements, and since you take the distance from the first element it will be the index of the "current" element.
Related
I am trying to merge two sorted arrays using pointers. The third loop is working food upto first arr[5] but then show garbage values afterwards. is the sorting techniqure wrong or am I using pointers incorrectly?
#include<iostream>
using namespace std;
int main() {
int arr1[] = { 1,3,4,6 };
int arr2[] = { 2,3,4,5 };
int n1 = 4;
int n2 = 4;
int arr3[10];
int* endptr = &arr1[0];
int* endptr2 = &arr2[0];
int* endptr3 = arr3;
int k = 0;
while (endptr < &arr1[n1-1] &&endptr2 < &arr2[n2-1]) {
if (endptr[0] < endptr2[0]) {
endptr3[k++] = endptr[0];
endptr++;
}
else {
endptr3[k++] = endptr2[0];
endptr2++;
}
}
while (endptr < &arr1[n1 - 1]) {
endptr3[k++] = endptr[0];
endptr++;
}
while (endptr2 < &arr2[n2 - 1]) {
endptr3[k++] = endptr[0];
endptr2++;
}
cout << arr3[5];
}
I got the results up to first 6 elements and then get garbage values.
The way you are using the pointers is negatively affecting your thought process.
Let’s abstract it to a function to help make it cleaner:
void merge(
int * first1, int * last1, // elements of array1
int * first2, int * last2, // elements of array2
int * dest ) // where to put sorted data
This is the “iterator” idiom used by C++ algorithms. first points to the first element. last points to one-past the last element. (And we assume that dest points to enough space to contain the results.) So:
int array1[] = { 1,3,4,6 };
int array2[] = { 2,3,4,5,7 };
int array3[9]; // enough room for array1+array2
merge(
array1, array1+4, // first array has 4 elements
array2, array2+5, // second array has 5 elements
array3 ); // destination array has 4+5=9 elements
C++ actually gives us a couple of functions to get the first and last pointers to whatever underlying sequence container you’ve got:
merge(
std::begin(array1), std::end(array1),
std::begin(array2), std::end(array2),
std::begin(array3) );
Now we can reconsider our merge algorithm.
void merge(...)
{
// while both array1 and array2 have elements:
while ((first1 != last1) and (first2 != last2))
{
if (*first2 < *first1)
*dest++ = *first2++;
else
*dest++ = *first1++;
}
// if array1 has any leftover elements:
while (first1 != last1)
*dest++ = *first1++;
// if array2 has any leftover elements:
while (first2 != last2)
*dest++ = *first2++;
}
In particular, notice:
We can easily check whether an array has elements by comparing the first and last pointers directly. When first == last, there are no elements, since last is one-past the end of the source array.
Comparison is simple enough. We could have written that as if (first2[0] < first1[0]) but that is less idiomatic than just using the * operator.
Copying a value is as simple as a dereference and increment on both sides of the assignment.
The three loops of the merge all work on a simple “are there elements left?” check.
Note also how we kept the test condition to a strict less-than comparison. That has ramifications for generic programming (for example, merge sorting in non-increasing order), but I’ll leave it at that for today...
So I have a C++ lab that requires me to print out an array, remove some digits, and then insert some digits. I've managed to remove the correct digits and then insert the digits at the end but I need to sort the array into ascending order, Ex:1,2,3,4. I thought this would be the easy part but it is giving me more trouble than I thought. I tried using a for loop with nested if loops that would work for a normal array but I guess involving pointers in the mix has stumped me. The current code runs and does everything but sort. Any hints or help is appreciated. Code and output is posted below. This is an image of the assignment description
#include <iostream>
using namespace std;
class Array //The array class
{
private:
//Data members capacity, size, arr (a pointer that points to the first element of the array in the heap)v and two functions to move integers in the array.
int capacity{};
int size{};
int* arr{};
void moveTowardFront(int index);
void moveTowardEnd(int index);
public:
Array(int capacity);//parameter
~Array();//destructor
//two member function declarations
void insert(int num);
void print() const;
void remove(int num);
};
//insert method
void Array::insert(int num)
{
{
//if size is 0, then move number taken from insert call into the first element of the array and increment size before returning
if (size == 0)
{
arr[0] = num;
size++;
return;
}
int index = 0;
while (&num < &arr[index] && index < size) //while the address of the number taken from insert function call is less than the address of the element [index] in the arr array
//and the index is less than the size of the array
{
index++; //then we increment the index
}
moveTowardEnd(index); //move value of element toward the end
//after the while loop we move the value of the number taken from main insert call into the arr element [index] after it has been incremented so we don't overwrite values
arr[index] = num;
size++;
//then we increment the size of the array because a new value has been inserted
}
}
// Delete member function
void Array::remove(int num)
{
int index = 0; //start index at 0
//while number from main is not equal to the array element of index and the index is smaller than the size, we increment the index
while (num != arr[index] && index < size)
{
index++;
}
//if index is equal to the size then output the number from main and say it isn't on the list so no removal
if (index == size)
{
cout << num << " is not in the list. ";
cout << "No removal." << endl;
return;
}
//move toward front function call on index value and post-increment. Then post-decrement size
moveTowardFront(index++);
size--;
}
//print method
void Array::print() const
{
//rearrange the digits in ascending order
for (int i = 0; i < size; i++)
{
//print out values based on value of size taken from insert method
cout << *(arr+i) << " "; //arr points to first element in heap and then moves over by i to the next element for each iteration
}
}
// Helper function to move the elements of array towards end
void Array::moveTowardEnd(int index)
{
int* temp = &arr[index];
int* temp2 = &arr[size-1];
arr[index] = *temp2;
arr[size] = *temp;
return;
}
// Helper function to move the elements of array towards front
void Array::moveTowardFront(int index)
{
int* temp = &arr[index];
int* temp2 = &arr[size-1];
arr[index] = *temp2;
arr[size] = *temp;
return;
}
//Destructor to clean up by deleting the space allocated
Array::~Array()
{
delete[]arr;
}
//Parameter constructor to allocate space
Array::Array(int cap)
:capacity(cap)
{
//move space allocated by array with capacity being taken from main into the arr pointer so pointer can point to first element in heap
arr = { new int[capacity] {} };//allocating memory with the new operator
size = 0;//initialize size to 0
}
int main()
{
// Declaration of any array of capacity 20
Array array(20);
// Inserting some elements and printing array
array.insert(15);
array.insert(13);
array.insert(10);
array.insert(14);
array.insert(11);
array.insert(17);
array.insert(14);
cout << "Printing array after insertions: " << endl;
array.print();
cout << endl;
// Removing two elements and printing array
array.remove(13);
array.remove(11);
cout << "Printing array after removals: " << endl;
array.print();
cout << endl;
// Inserting two more elements and printing array
array.insert(8);
array.insert(22);
cout << "Printing array after more insertion" << endl;
array.print();
cout << endl;
// Try to remove an element, which is not in the array
array.remove(31);
return 0;
}
There are many ways to sort an array. Commonly used is the algorithm known as quicksort: https://en.wikipedia.org/wiki/Quicksort
Psuedo-code taken from the wikipedia page:
algorithm quicksort(A, lo, hi) is
// first we check if the lo and hi
// are natural numbers (without this check, you
// will get an overflow error because, at some point
// the program will access something like A[-1]
// which does not exists !
if lo >= 0 && hi >= 0 then
// if the indexes are in correct order, continue
if lo < hi then
// we find the index of the pivot and...
p := partition(A, lo, hi)
// ...apply quicksort for the left side and the
// right side of the array
quicksort(A, lo, p - 1)
quicksort(A, p + 1, hi)
algorithm partition(A, lo, hi) is
// we set the pivot value to the
// final value of the array
pivot := A[hi]
// we set the pivotIndex (i) to
// the start of the array
// ! NOTICE that A[i] != pivot
// aka. A[pivotIndex] != pivotValue
i := lo - 1
// we traverse the array from the start
// to the end (inclusive) aka. we traverse
// the array in this interval: [lo, hi]
for j := lo to hi do
// if the current element is
// less than the value of the pivot
// (or equal to it), then increment the i
// and swap it with the element at i (pivotIndex)
// ! NOTICE that j is automatically incremented
if A[j] <= pivot then
i := i + 1
swap A[i] with A[j]
return i
You would have to translate the pseudo-code to C++ yourself. They appear to be using the name algorithm to denote a function definition, and the := operator to do assignment, but otherwise it's not terribly different from C++ syntax. They have written in one place swap A[i] with A[j], which would for you probably look more like:
int temp = A[i];
A[i] = A[j];
A[j] = temp;
I intend to create a recursive merge sort function that returns a pointer to the sorted array. Below is my implementation of the program.
The output produced by the code mostly consists of garbage memory locations. Since it is a recursive function, I'm having trouble debugging it. What scares me is whether I have understood pointers, arrays and their interconversion incorrectly. It would be really helpful if someone could take a look at the code and tell me my mistake.
Function that prints an array given a pointer to its first element
void printArr(int *arr, int n){
int *ptr = arr;
for(int i = 0; i < n; i++){
cout << *ptr << " ";
ptr++;
}
cout << endl;
}
Merge Sort function
Here p is the pointer to the given array, n is the length of the array. l and r are the indices of the first and last element of the array respectively.
// returns pointer to the sorted array
int* mergeSort(int *p, int n, int l, int r){
if(l >= r){
return &p[l];
}
int mid = l + (r-l)/2;
int *leftArray = mergeSort(p, n, l, mid);
int *rightArray = mergeSort(p, n, mid+1, r);
int n1 = mid - l + 1;
int n2 = r - mid;
int sortedArray[n1+n2];
int *ptr = sortedArray; // pointer to the sorted array
int p1 = 0; // left array index pointer
int p2 = 0; // right array index pointer
int idx = 0; // sorted array index pointer
int flag = 0; /* flag = 1 => all elements of left array have been placed into the sorted array ; flag = 2 => all elements of right array have been placed into the sorted array */
// putting elements into the sorted array
for(int i = 0; i < n1+n2; i++){
if(p1 == n1){
flag = 1;
break;
}
if(p2 == n2){
flag = 2;
break;
}
if(*(leftArray+i) > *(rightArray+i)){
sortedArray[i] = *(leftArray+p1);
p1++;
idx++;
}
else{
sortedArray[i] = *(rightArray+p2);
p2++;
idx++;
}
}
if(flag == 1){
// put remaining elements of right array into the sorted array
for(int i = idx; i < n1+n2; i++){
sortedArray[i] = *(rightArray+p2);
p2++;
}
}
if(flag == 2){
// put remaining elements of left array into the sorted array
for(int i = idx; i < n1+n2; i++){
sortedArray[i] = *(leftArray+p1);
p1++;
}
}
// return the sorted array
return ptr;
}
Main function
int main(){
int arr[] = {7,2,1,5};
int n = sizeof(arr)/sizeof(int);
int *p = arr;
cout << "Original array: ";
printArr(arr, n);
int *f = mergeSort(arr, n, 0, 3);
cout << "New array: ";
printArr(f, n);
}
Your code have returned the local array's address, which is invalidated after function returned. Then gabarage data is printed:
int sortedArray[n1+n2];
int *ptr = sortedArray; // pointer to the sorted array
Change into
int *ptr = new int[n1 + n2];
auto sortedArray = ptr;
Then we get a non-garbage value, but we hit memory leak and it's hard to deal with memory deallocation since the retuned pointer may point to the array p under certain boundary conditions.
So return pointer is not a good design, and it just wastes the API call to allocate memory and deallocate memory. It's better to split the function into two: the first one allocates a temporary buffer, and the second one handles sorting with the buffer as a parameter and calls itself with a recursive. Or just sort in place, totally avoid the temporary buffer.
Question
I do not want to pass the size of the array as an index parameter.
For my merge_sort, I want to optimize my parameters using the iterator range concept. I can't seem to figure out how to deference the iterator range and access my array. I can deference to access the indices like low and high in recursive_merge_sort, but there does not seem to be an intuitive way to access the array itself. I've been using this great guide on C++ Pointers and Arrays as a starting point.
My Merge Sort C++11 C++17 question brought this concept to light and I like the idea of using iterator ranges to reduce the number of parameters for my sort.
Code
void recursive_merge_sort(int* low, int* high) {
// deference to get starting index "low" and ending index "high"
if(*(low) >= *(high) - 1) { return; }
int mid = *(low) + (*(high) - *(low))/2;
// what's the correct syntax to access my array from the iterator range
// int* d = some how deference low or how to get the data array they iterate on
recursive_merge_sort_v(d + low, d + mid);
recursive_merge_sort_v(d + mid, d + high);
merge(d + low, mid, d + high);
// delete d;
}
void merge_sort(int* data) {
// what's the correct syntax to access my array from the passed in iterator range
// is this event possible? incorrect syntax below
recursive_merge_sort(data + 0, data + std::size(*(data)));
}
int main()
{
int data[] = { 5, 1, 4, 3, 65, 6, 128, 9, 0 };
int num_elements = std::size(data);
std::cout << "unsorted\n";
for(int i=0; i < num_elements; ++i) {
std::cout << data[i] << " ";
}
merge_sort(data);
std::cout << "\nsorted\n";
for(int i=0; i < num_elements; ++i) {
std::cout << data[i] << " ";
}
}
Comment section Solution from the bayou
Remy Lebeau: "When you pass an array by pointer, you lose all information about it. You can't get back to the original array given only a pointer/iterator, as dereferencing will only give you a single element of the array, not the array itself. When passing an array by pointer, you have no choice but to pass the array size as another parameter. Otherwise, pass the array by reference instead, and if you need to support arrays of different sizes then use a template so the compiler can deduce the array size for the reference."
Iterators are modeled to act like pointers. They have the same type of overloaded operators: dereferencing and increment at the very least (some also have decrement, random access, etc.).
The most advanced iterator interface is random access, which functions exactly like a raw pointer (by design).
So all (raw) pointers are basically random access iterators into a C-style (contiguous) array. Look at the following to visualize begin/end iterators for a C-style array:
int vals[] = { 0, 1, 2, 3, 4 };
int *begin = vals;
int *end = vals + 5;
v vals[]
0 1 2 3 4 ...
^ begin ^ end (1 past the end of array)
vals[2] == begin[2]
vals[4] == begin[4]
etc.
So basically, you just treat the begin iterator as the front of the array, and you just don't dereference anywhere before the begin iterator, nor at or past the end iterator, as standard C++ convention dictates the end iterator is 1 past the end of the range.
Here's an example of using pointers like iterators:
void print(int *begin, int *end)
{
// for each element in the range (starting at begin, up to but not including end)
for (; begin != end; ++begin)
{
// print the element
std::cout << *begin << '\n';
}
}
int main()
{
// declare a C-style array
int arr[] = { 10, 5, 2, 6, 20 };
// for the sake of example, print only the middle 3 elements
// begin = arr + 1
// end = arr + 4
print(arr + 1, arr + 4);
return 0;
}
my aim is to reverse an array 3,12,2,1 to 1,2,12,3. when i run this code i get garbage before my actually result. i can't seem to see where the problem is please assit
#include<iostream>
using namespace std;
int rev (int arr[], int a){
//int r;
for(int i =a-1; i>=0; i--){
cout<<arr[i]<<" ";
}
return 0;
}
int main(){
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
cout<<rev(arr, sizeof(arr))<<endl;
system("pause");
return 0;
}
Use sizeof(arr)/sizeof(arr[0]) instead of sizeof(arr).
sizeof(arr) gives the total size of the array. sizeof(arr[0]) is the size of one array element (all elements have the same size). So sizeof(arr)/sizeof(arr[0]) is the number of elements.
An optimized answer to the question would be using reverse () from STL if you are allowed to use it:
std::reverse
http://www.sgi.com/tech/stl/reverse.html
int main()
{
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
reverse(arr, arr + 5);
copy(arr, arr + 5, ostream_iterator<int>(cout, ", "));
}
sizeof return the size in bytes. In your example, if sizeof(int) = 4, it returns 20.
Because you're using an array, you have to keep the size of the array handy as well. sizeof computes the size of a value in memory, in this case the size of all the memory used to represent arr. You can do sizeof(arr)/sizeof(int) to get the number of elements in an array. This makes sense because it's taking the total size of the array and dividing it by the size of an element in the array. Beware however that this only works for arrays (int arr[4] = {6,41,12,5,2};). If it's a pointer to a heap-allocated array via something like int* i = new int[4]; you'll need to keep the size of the array hanging around.
Also, you're calling your reverse function from within a cout<< call, which will print the function's return value (in this case it's hard-coded to 0).
It also turns out there is a function in the C++ standard library (std::reverse) that can do this.
If I may speak subjectively and in an off-topic manner about your approach, it is very un-C-like. My personal favorite way to reverse an array goes like this:
void reverse(int *a, int n)
{
int *p = a, *q = a + n - 1;
while (p < q)
{
int swap = *p;
*p++ = *q;
*q-- = swap;
}
}
// Usage:
int a [] = { /* ... */ };
reverse(a, sizeof(a)/sizeof(*a));
Of course, since your question is tagged c++, there's always std::reverse().
Sizeof operator return the one extra (arrayLength + 1) here 6 will return when passs 6 it store in a when a-1 you get 5 but array index start from 0 length-1 that from 0 to 4 here i pointing to index 5 that is not last element last+1 that why you got garbage value