I have a task to remove the duplicates from a sorted array.
However, when I try this it doesn't remove anything and still gives me the same values in the output as the original.
I think I'm missing something in the removeDuplicates() function.
Also pointer notation would be recommended. Thank you!
void removeDuplicates(int *arr, int *size)
{
int s,*p,i,k=0;
p=arr;
s=*size;
int arr1[s];
for(i=0;i<s-1;i++)
{
if (*(p+i)!=*(p+i+1))
{
arr1[k++]=*(p+i);
}
}
arr1[k++]=*(p+s-1);
for(i=0; i<k; i++)
{
*(p+i) = arr1[i];
}
for(i=0; i<k; i++)
{
cout<<*(p+i)<<endl;
}
}
For starters variable length arrays as the array declared in your function
int arr1[s] = {};
is not a standard C++ feature. And moreover in C where variable length arrays exist you may not initialize them in their declarations.
Moreover if the source array contains only one or two different elements then the value of the variable k will be incorrect and equal to either 0 (instead of 1) or 1 (instead of 2).
Apart from this the function shall not output anything. It is the caller of the function decides whether to output the sub-array of unique elements. And as the second parameter is passed by reference in C meaning then it shall be changed within the function.
There is standard algorithm std::unique that can be used to do the task. Here is a demonstrative program.
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int a[] = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };
auto last = std::unique( std::begin( a ), std::end( a ) );
for ( auto first = std::begin( a ); first != last; ++ first )
{
std::cout << *first << ' ';
}
std::cout << '\n';
return 0;
}
The program output is
1 2 3 4 5
If you want to write a similar function for arrays yourself using pointers within the function then it can look for example the following way
#include <iostream>
template <typename T>
size_t removeDuplicates( T *a, size_t n )
{
T *dest = a;
if ( n != 0 )
{
++dest;
for ( T *current = a; ++current != a + n; )
{
if ( *current != *( dest - 1 ) )
{
if ( dest != current )
{
*dest = *current;
}
++dest;
}
}
}
return dest - a;
}
int main()
{
int a[] = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t last = removeDuplicates( a, N );
for ( size_t first = 0; first != last; ++first )
{
std::cout << a[first] << ' ';
}
std::cout << '\n';
return 0;
}
Again the program output is
1 2 3 4 5
This question already has answers here:
Size of an array C++ [duplicate]
(7 answers)
Closed 2 years ago.
I am just starting to learn C++ and I was playing around with functions. I am trying to pass an integer array as a parameter, and have the function print every element of the array. My issue however is that I have an array initialized to a seize of 10, but when I pass it to the function it only reads it as a size of 2. Any help would be appreciated! You can find my program below.
#include <iostream>
#include <cmath>
using namespace std;
void Max(int Arr[])
{
for (int i=0; i<sizeof(Arr)/sizeof(Arr[0]); i++)
{
cout<< Arr[i]<<endl;
}
}
int main()
{
int Arr[]={1,2,3,4,5,6,7,8,9,10};
Max(Arr);
return 0;
}
Thank you all for the help in advance!
When an array is passed by value it is implicitly converted to pointer to its first element.
On the other hand a function parameter declared as having an array type is adjusted by the compiler to pointer to the array element type.
So for example these function declarations
void Max(int Arr[]);
void Max(int Arr[1])
void Max(int Arr[10])
void Max(int Arr[100]);
declare the same function and are adjusted by the compiler to the declaration
void Max( int *Arr );
As a result within the function the parameter Arr is a pointer and this expression
sizeof(Arr)/sizeof(Arr[0])
is equivalent to
sizeof( int * ) / sizeof( int )
that yields either 1 or 2 depending on the size of the type int *.
When you passing an array by value to a function you should also pass its size explicitly.
So the function could be defined like
void Max( const int Arr[], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
cout << Arr[i] << endl;
}
}
And the function can be called like
Max(Arr, sizeof( Arr ) / sizeof( *Arr ) );
Another approach is to declare the function parameter as having a referenced type. In this case it is better to use a template function that it could be called for an array at least of any size.
template <size_t N>
void Max( const int ( &Arr )[N] )
{
for ( size_t i = 0; i < N; i++ )
{
cout << Arr[i] << endl;
}
}
Or the function could be defined like
template <typename T, size_t N>
void Max( const T ( &Arr )[N] )
{
for ( size_t i = 0; i < N; i++ )
{
cout << Arr[i] << endl;
}
}
And the both functions can be called like
Max(Arr);
Pay attention to that you could use the standard class template std::array declared in the header <array>. For example
#include <iostream>
#include <array>
const size_t N = 10;
std::ostream & Max( const std::array<int, N> &a, std::ostream &os = std::cout )
{
for ( const auto &item : a )
{
os << item << ' ';
}
return os;
}
int main()
{
std::array<int, N> a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Max( a ) << '\n';
return 0;
}
The program output is
1 2 3 4 5 6 7 8 9 10
void Max(int Arr[]) is equal to void Max(int* Arr).
In function Max(int Arr[]):
sizeof(Arr)/sizeof(Arr[0]) = sizeof(int*)/sizeof(int)
On x64 it is equal 2, on x86 it is equal 1
correct your code:
---------------------------------
#include <iostream>
#include <cmath>
using namespace std;
void Max(int Arr[], int len)
{
for (int i=0; i<len; i++)
{
cout<< Arr[i]<<endl;
}
}
int main()
{
int Arr[]={1,2,3,4,5,6,7,8,9,10};
Max(Arr, sizeof(Arr)/sizeof(Arr[0]));
return 0;
}
Write the find function, which takes a fixed integer vector reference and a single value integer and returns the index of the first occurrence of this value in the vector or the length of the vector if no value in it. The function should be adapted for use in the sample program
below. The function uses only the vector header file.
This is what I've done so far:
#include <vector>
#include <iostream>
using namespace std;
int find(const vector<int> &r ,int number)
{
int i=0;
int x;
for(i;i<r.size();++i)
{
if(r[i]==number)
{
break;
}
}
return 0;
}
int main()
{
int result = find(vector<int> {3, -1, 7, 12, -5, 7, 10}, 7);
cout << result << endl;
}
And, I'm stuck, I don't know how to return the index.
You should add return i; instead of breaking out of the loop
and maybe return -1 instead of 0 if the number is not found.
Return index i when found otherwise return 0 after the loop like this:
int find( const std::vector<int>& r, const int number )
{
for ( int i = 0; i < r.size(); ++i )
{
if ( r[i] == number )
{
return i;
}
}
return 0;
}
The x is unused in find function.
You should return i from your function
It seems to be a simply exercise, but something doesn't work with the following qsort algorithmus. The struct abcSort correctly shows all assigned values. Unfortunately, the qsort is not sorting anything.
typedef int(*compfn)(const void*, const void*);
struct ABCSort
{
int svSort[10];
string itemSort[10];
};
struct ABCSort abcSort;
int compare(struct ABCSort*, struct ABCSort*);
void mainSort()
{
for (int i = 0; i < 10; i++)
{
abcSort.svSort[i] = 100 - i;
abcSort.itemSort[i] = arrayREAD[i][2];
}
qsort( (void*)&abcSort, 10, sizeof(struct ABCSort), (compfn)compare );
}
int compare(struct ABCSort *elem1, struct ABCSort *elem2)
{
if (elem1->svSort< elem2->svSort)
return -1;
else if (elem1->svSort > elem2->svSort)
return 1;
else
return 0;
}
You have build two arrays of integer and strings and you want to sort them by the numbers, keeping the initial pairing. That's the first problem, you should have created one array of structs, each struct containg a number and a string and a function that compares the integer member of that struct to obtain the sort order.
You also tagged this question as C++ but you are using qsort, arrays and function pointers like C, so I'll present two complete C programs that solve your problem.
Let's see, using an array of structs, what your code could be like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 6
#define CMAX 15
typedef int(*cmp_fn)(const void*, const void*);
typedef struct {
int num;
char str[CMAX];
} numABC;
int comp_struct(const numABC *lhs, const numABC *rhs ) {
if ( lhs->num < rhs->num )
return -1;
if ( lhs->num > rhs->num )
return 1;
return 0;
}
int main(void) {
numABC myArray[MAX] = { {6, "cat"}, {4, "dog"}, {8, "panter"},
{2, "red fish"}, {1, "hawk"}, {6, "snake"} };
int i;
// sort the array of structs by int member
qsort(myArray, MAX, sizeof(numABC), (cmp_fn)comp_struct);
// print out the sorted array
printf("\nSort by numbers:\n");
for ( i = 0; i < MAX; ++i ) {
printf("%d %s\n",myArray[i].num,myArray[i].str);
}
return 0;
}
If you want to use this code, but you have a couple of arrays instead, one option is to convert those arrays:
int nums[MAX] = {6,4,8,2,1,3};
char str[MAX][CMAX] = {"cat","dog","panter","red fish","hawk","snake"};
int i;
// create the array of structs from the two arrays
numABC myArray[MAX];
for ( i = 0; i < MAX; ++i ) {
myArray[i].num = nums[i];
strcpy(myArray[i].str, str[i]);
}
Another option to sort two different arrays (mantaining the pairing or alignment between the two) is to use a more complicated method which consists in sorting an array of indeces instead. to keep the relationships between the two original arrays I'll have to use global variables which can be accessed inside the compare function(s). Once the indeces are sorted, the original arrays are changed accordingly.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 6
#define CMAX 15
const size_t I_DIM = MAX * sizeof(int);
const size_t SS_DIM = MAX * sizeof(char*);
const size_t S_DIM = MAX * CMAX;
// global variables needed to perform comparisons
int *pg_int;
char **pg_str;
typedef int(*cmp_fn)(const void*, const void*);
int comp_num(const int *lhs, const int *rhs ) {
if (pg_int[*lhs] < pg_int[*rhs])
return -1;
if (pg_int[*lhs] > pg_int[*rhs])
return 1;
return 0;
}
int comp_str(const int *lhs, const int *rhs ) {
return strcmp(pg_str[*lhs],pg_str[*rhs]);
}
int main(void) {
int nums[MAX] = {6,4,8,2,1,3};
char str[MAX][CMAX] = {"cat","dog","panter","red fish","hawk","snake"};
int i;
// create an array of indeces
int index[MAX];
for ( i = 0; i < MAX; ++i ) {
index[i] = i;
}
// set global copies
pg_int = malloc(I_DIM);
memcpy(pg_int,nums,I_DIM);
pg_str = malloc(SS_DIM);
pg_str[0] = malloc(S_DIM);
memcpy(pg_str[0],str[0],S_DIM);
for ( i = 1; i < MAX; i++ ) {
pg_str[i] = pg_str[0] + i * CMAX;
}
// sort the indeces ordering by ints
qsort(index, MAX, sizeof(int), (cmp_fn)comp_num);
//update the two arrays
for ( i = 0; i < MAX; ++i ) {
nums[i] = pg_int[index[i]];
strcpy(str[i],pg_str[index[i]]);
}
// print out sorted couples
printf("Sort by numbers:\n");
for ( i = 0; i < MAX; ++i ) {
printf("%d %s\n",nums[i],str[i]);
}
// sort the indeces ordering by strings
qsort(index, MAX, sizeof(int), (cmp_fn)comp_str);
//update the two arrays
for ( i = 0; i < MAX; ++i ) {
nums[i] = pg_int[index[i]];
strcpy(str[i],pg_str[index[i]]);
}
// print out sorted couples
printf("\nSort by strings:\n");
for ( i = 0; i < MAX; ++i ) {
printf("%d %s\n",nums[i],str[i]);
}
free(pg_int);
free(pg_str[0]);
free(pg_str);
return 0;
}
The output (sorry for the silly example) is:
Sort by numbers:
1 hawk
2 red fish
3 snake
4 dog
6 cat
8 panter
Sort by strings:
6 cat
4 dog
1 hawk
8 panter
2 red fish
3 snake
If you want to accomplish the same task in C++ you should take advantage of the Standard Library and use std::vector as a container and std::sort as algorithm:
#include <iostream>
#include <vector>
#include <algorithm>
using std::vector;
using std::string;
using std::cout;
struct numABC {
double num;
string str;
// instead of a compare function I can overload operator <
friend bool operator<( const numABC &lhs, const numABC &rhs ) {
return lhs.num < rhs.num;
}
};
// or use a lambda
auto cmp_str = []( const numABC &lhs, const numABC &rhs ) -> bool {
return lhs.str < rhs.str;
};
int main() {
vector<numABC> my_data = { {3.6, "cat"}, {5.7, "dog"}, {7.1, "panter"},
{0.2, "red fish"}, {1.8, "hawk"}, {1.1, "snake"}};
std::sort(my_data.begin(), my_data.end());
std::cout << "Sort by numbers:\n";
for ( auto & s : my_data ) {
std::cout << s.num << ' ' << s.str << '\n';
}
std::sort(my_data.begin(), my_data.end(), cmp_str);
// passing a lambda to specify how to compare ^^
std::cout << "Sort by strings:\n";
// if you don't like c++11 range for:
for ( int i = 0; i < my_data.size(); ++i ) {
std::cout << my_data[i].num << ' ' << my_data[i].str << '\n';
}
return 0;
}
Note that I have initialized my_data as a vector of objects of type numABC. If you have to start from two arrays, you can create the vector like this:
vector<double> nums = {3.6, 5.7, 7.1, 0.2, 1.8, 1.1};
vector<string> str = {"cat", "dog", "panter", "red fish", "hawk", "snake"};
vector<numABC> my_data;
for ( int i = 0; i < nums.size(); ++i ) {
my_data.push_back(numABC{nums[i],str[i]});
}
After sorting, if you have to extract the two vectors again (instead of simply looping through my_data) you can do something like this:
for ( int i = 0; i < my_data.size(); ++i ) {
nums[i] = my_data[i].num;
str[i] = my_data[i].str;
}
Alternatively you could implement an algorithm similar to the one I used before and sort the two vectors nums and srt using an auxiliary vector of indeces:
vector<double> nums = {3.6, 5.7, 7.1, 0.2, 1.8, 1.1};
vector<string> str = {"cat", "dog", "panter", "red fish", "hawk", "snake"};
// create the vector of indeces
vector<int> idx(nums.size());
std::iota(idx.begin(),idx.end(),0); // fill the vector, require #include <numeric>
// thanks to the lambda variable capture you don't need globals
auto cmp_ind = [ &nums ]
( const int &lhs, const int &rhs ) -> bool {
return nums[lhs] < nums[rhs];
};
// sort indeces
std::sort(idx.begin(), idx.end(),cmp_ind);
// create sorted arrays. It could be done in place but it's more difficult
vector<double> sorted_nums(nums.size());
vector<string> sorted_str(str.size());
for ( int i = 0; i < nums.size(); ++i ) {
sorted_nums[i] = nums[idx[i]];
sorted_str[i] = str[idx[i]];
}
std::cout << "Sort by numbers:\n";
for ( int i = 0; i < nums.size(); ++i ) {
std::cout << sorted_nums[i] << ' ' << sorted_str[i] << '\n';
}
You seem to intend to sort an array of integers (your compare function looks like that). But what you are actually handing over to qsort for sorting is a pointer to a structure that holds, among other stuff, an array.
So what you are actually trying to sort is one single struct ABCSort which is initialized and 9 other, uninitialized structures. This must fail.
Your qsort line should look like so:
qsort ((void*)&(abcsort.svsort), 10, sizeof (int), (compfn)compare);
Also, you should change the compare function so that it takes and works on two pointers to integers:
int compare (int * e1, int * e2) {
return *e1 - *e2;
}
EDIT:
After you have explained a bit better what you want, have a look at the following:
typedef int(compfn)(const void, const void*);
#define MAXCARS 5
struct car {
int sortKey;
double displacement;
char name[15]; /* Note I have decided this should be C */
};
/* This time we have an array of structs */
struct car cars [MAXCARS] = {
{ 0, 1.9, "BMW" },
{ 0, 6.3, "Audi" },
{ 0, 0.5, "Fiat" },
{ 0, 25.0, "Humvee" },
{ 0, 0.05, "Minibike" }
};
int compare(struct car*, struct car*);
void main(int argc, char *argv []) {
int i;
for (i = 0; i < MAXCARS; i++)
cars[i].sortKey = 100 - i;
qsort((void *)&cars, MAXCARS, sizeof(struct car), (compfn)compare);
}
/* Note we are comparing struct car-s in here, based on their displacement */
int compare(struct car *elem1, struct car *elem2) {
return elem1->sortKey - elem2->sortKey;
}
I have a simple array in c++ which show me a strange result for default values of array.
#include <iostream>
using namespace std;
int arr [] = {2,3};
int main ()
{
for ( int n=0 ; n<10 ; ++n ) {
cout<< arr[n]<<",";
}
}
The result of which I should receive is 2,3,0,0,0,0,0,0,0,0, but get this result 2,3,0,0,0,0,0,0,809998728,32588, can someone explain to me why?
Declare the array the following way
int arr [10] = {2,3};
Otherwise when it is declared like this
int arr [] = {2,3};
it has only two elements.
In any case the program would look better if it was written like
#include <iostream>
int main()
{
const size_t N = 10;
int arr[N] = { 2, 3 };
for ( size_t n = 0 ; n < N ; ++n ) std::cout << arr[n] << ",";
std::cout << std::endl;
}