#include <iostream>
using namespace std;
int main()
{
int *array1 = new int [5]();
int *array2 = new int [7]();
array1[2] = 3;// or anychange
array2[2] = 3;// to both arrays
if (array1==array2)
{
//if all values of the both arrays are equal
}
else
{
//if all values of the both arrays are not equal
}
return 0;
}
I have two dynamically allocated array using new (the size may or may not be same). Now I want to compare all elements of array (if size and elements are same, then true, if not either of these then false).
How to do in C++? (not interested using vector in my problem scenario)
First off, I would like to encourage you to use std::vector for dynamically allocated arrays. They will free the allocated memory safely and automatically and you can always retrieve their size without extra manual book-keeping.
Once you have that, you can compare the two arrays in the following way:
#include <vector>
int main()
{
std::vector<int> v1 = { 1, 2, 3 };
std::vector<int> v2 = { 1, 2, 3, 4 };
const bool theyAreEqual = v1 == v2;
}
Comparing two pointers as you did, only compares the addresses of the first elements and not the sizes and the contents of the dynamic arrays elementwise. That's one of the reasons, that it's much safer to use std::vector instead of C-style arrays.
array1 == array2 compares pointers. They will never be equal. Furthermore, you can't know how many elements is in a dynamically allocated array, unless you're:
having its size stored separately
using sentinel value to determine its end - you choose a value (e.g. -1) to represent end of the array (like c-style strings usually use \0)
Then you'll be able to know how many elements to iterate over, comparing the elements of both arrays.
Here is a way to resolve it, but I highly recommend vectors, in cases like this.
You need the length and a bool for checking. check is true for default and arrays should be allocated with length1 and length2.
//...
if (length1 != length2) check = false;
else for (int i = 0; i < length1; i++)
{
if (array1[i] != array2[i])
{
check = false;
break;
}
}
if (check)
//...
I followed up on Ralph comment, because I also wanted to see what std::equal did, and the == operator of std::vector does the right thing, and surprisingly simpler to use than the std::equal operator. If you use the latter, you will need to make sure to user begin()/end() for both arrays (It is a C++14 version of std::equal), or add v1.size() == v2.size() &&...
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v1 = { 1, 2, 3 };
std::vector<int> v2 = { 1, 2, 3, 4 };
std::vector<int> v3 = { 1, 2, 3 };
const bool theyAreEqualv1v2 = v1 == v2;
const bool theyAreEqualv1v3 = v1 == v3;
const bool theyAreEqualStdv1v2 = std::equal(v1.begin(),v1.end(), v2.begin(),v2.end());
const bool theyAreEqualStdv1v2bad = std::equal(v1.begin(),v1.end(), v2.begin());
const bool theyAreEqualStdv1v3 = std::equal(v1.begin(),v1.end(), v3.begin(),v3.end());
// std::equal according to http://en.cppreference.com/w/cpp/algorithm/equal actually
// only compares the first range thus you would really need begin()/end() for both arrays
printf("equal v1v2: %d\n",theyAreEqualv1v2);
printf("equal v1v3: %d\n",theyAreEqualv1v3);
printf("std::equal v1v2: %d\n",theyAreEqualStdv1v2);
printf("std::equal v1v2 bad: %d\n",theyAreEqualStdv1v2bad);
printf("std::equal v1v3: %d\n",theyAreEqualStdv1v3);
return 0;
}
clang++ -std=c++14 -stdlib=libc++ c.cpp
output:
equal v1v2: 0
equal v1v3: 1
std::equal v1v2: 0
std::equal v1v2 bad: 1
std::equal v1v3: 1
Related
If I have a vector of values and want to check that they are all the same, what is the best way to do this in C++ efficiently? If I were programming in some other language like R one way my minds jumps to is to return only the unique elements of the container and then if the length of the unique elements is more than 1, I know all the elements cannot be the same. In C++ this can be done like this:
//build an int vector
std::sort(myvector.begin(), myvector.end());
std::vector<int>::iterator it;
//Use unique algorithm to get the unique values.
it = std::unique(myvector.begin(), myvector.end());
positions.resize(std::distance(myvector.begin(),it));
if (myvector.size() > 1) {
std::cout << "All elements are not the same!" << std::endl;
}
However reading on the internet and SO, I see other answers such using a set or the find_if algorithm. So what is the most efficient way of doing this and why? I imagine mine is not the best way since it involves sorting every element and then a resizing of the vector - but maybe I'm wrong.
You need not to use std::sort. It can be done in a simpler way:
if ( std::adjacent_find( myvector.begin(), myvector.end(), std::not_equal_to<>() ) == myvector.end() )
{
std::cout << "All elements are equal each other" << std::endl;
}
you can use std::equal
version 1:
//assuming v has at least 1 element
if ( std::equal(v.begin() + 1, v.end(), v.begin()) )
{
//all equal
}
This will compare each element with the previous one.
version 2:
//assuming v has at least 1 element
int e = v[0]; //preferably "const auto& e" instead
bool all_equal = true;
for(std::size_t i = 1,s = v.size();i<s && all_equal;i++)
all_equal = e == v[i];
Edit:
Regarding performance, after testing with 100m elements i found out that in Visual Studio 2015 version 1 is about twice as fast as version 2. This is because the latest compiler for vs2015 uses sse instructions in c++ std implementations when you use ints, float , etc..
if you use _mm_testc_si128 you will get a similar performance to std::equal
using std::all_of and C++11 lambda
if (all_of(values.begin(), values.end(), [&] (int i) {return i == values[0];})){
//all are the same
}
Given no constraints on the vector, you have to iterate through the vector at least once, no matter the approach. So just pick the first element and check that all others are equal to it.
While the asymptotic complexity of std::unique is linear, the actual cost of the operation is probably much larger than you need, and it is an inplace algorithm (it will modify the data as it goes).
The fastest approach is to assume that if the vector contains a single element, it is unique by definition. If the vector contains more elements, then you just need to check whether all of them are exactly equal to the first. For that you only need to find the first element that differs from the first, starting the search from the second. If there is such an element, the elements are not unique.
if (v.size() < 2) return true;
auto different = std::find_if(v.begin()+1, v.end(),
[&v](auto const &x) { x != v[0]; });
return different == v.end();
That is using C++14 syntax, in an C++11 toolchain you can use the correct type in the lambda. In C++03 you could use a combination of std::not, std::bind1st/std::bind2nd and std::equal in place of the lambda.
The cost of this approach is distance(start,different element) comparisons and no copies. Expected and worst case linear cost in the number of comparisons (and no copies!)
Sorting is an O(NlogN) task.
This is easily solvable in O(N), so your current method is poor.
A simple O(N) would be as Luchian Grigore suggests, iterate over the vector, just once, comparing every element to the first element.
if(std::all_of(myvector.begin()+1, myvector.end(), std::bind(std::equal_to<int>(),
std::placeholders::_1, myvector.front())) {
// all members are equal
}
You can use FunctionalPlus(https://github.com/Dobiasd/FunctionalPlus):
std::vector<std::string> things = {"same old", "same old"};
if (fplus::all_the_same(things))
std::cout << "All things being equal." << std::endl;
Maybe something like this. It traverses vector just once and does not mess with the vector content.
std::vector<int> values { 5, 5, 5, 4 };
bool equal = std::count_if(values.begin(), values.end(), [ &values ] (auto size) { return size == values[0]; }) == values.size();
If the values in the vector are something different than basic type you have to implement equality operator.
After taking into account underscore_d remarks, I'm changing possible solution
std::vector<int> values { 5, 5, 5, 4 };
bool equal = std::all_of(values.begin(),values.end(),[ &values ] (auto item) { return item == values[0]; });
In your specific case, iterating over vector element and finding a different element from the first one would be enough. You may even be lucky enough to stop before evaluating all the elements in your vector. (A while loop could be used but I sticked with a for loop for readability reasons)
bool uniqueElt = true;
int firstItem = *myvector.begin();
for (std::vector<int>::const_iterator it = myvector.begin()+1; it != myvector.end() ; ++it) {
if(*it != firstItem) {
uniqueElt = false;
break;
}
}
In case you want to know how many different values your vector contains, you could build a set and check its size to see how many different values are inside:
std::set mySet;
std::copy(mySet.begin(), myvector.begin(), myvector.end());
You can simply use std::count to count all the elements that match the starting element:
std::vector<int> numbers = { 5, 5, 5, 5, 5, 5, 5 };
if (std::count(std::begin(numbers), std::end(numbers), numbers.front()) == numbers.size())
{
std::cout << "Elements are all the same" << std::endl;
}
LLVM provides some independently usable headers+libraries:
#include <llvm/ADT/STLExtras.h>
if (llvm::is_splat(myvector))
std::cout << "All elements are the same!" << std::endl;
https://godbolt.org/z/fQX-jc
for the sake of completeness, because it still isn't the most efficient, you can use std::unique in a more efficient way to decide whether all members are the same, but beware that after using std::unique this way the container is useless:
#include <algorithm>
#include <iterator>
if (std::distance(cntnr.begin(), std::unique(cntnr.begin(), cntnr.end()) == 1)
{
// all members were the same, but
}
Another approach using C++ 14:
bool allEqual = accumulate(v.begin(), v.end(), true, [first = v[0]](bool acc, int b) {
return acc && (b == first);
});
which is also order N.
Here is a readable C++17 solution which might remind students of the other constructors of std::vector:
if (v==std::vector(v.size(),v[0])) {
// you guys are all the same
}
...before C++17, the std::vector rvalue would need its type provided explicitly:
if (v==std::vector<typename decltype(v)::value_type>(v.size(),v[0])) {
// you guys are all the same
}
The C++ function is defined in library in STL. This function operates on whole range of array elements and can save time to run a loop to check each elements one by one. It checks for a given property on every element and returns true when each element in range satisfies specified property, else returns false.
// C++ code to demonstrate working of all_of()
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> v(10, 2);
// illustrate all_of
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; }))
{
std::cout << "All numbers are even\n";
}
}
I think it is a trivial question, but I couldn't find a specific solution to it. I'm trying to append array into a vector, using push_back() function. Here is the code:
int main()
{
std::vector<int*> matchVector;
int msmTemp[3];
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
matchVector.push_back(msmTemp);
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
matchVector.push_back(msmTemp);
for(auto i : matchVector)
{
for(int j = 0; j<3; j++)
{
cout<<i[j]<<", ";
}
cout<<"\n";
}
return 0;
}
The output I'm getting is 4,7,0 two times. I don't understand as to why I'm not able to see the previous values, namely 1,2,3? Is it because of the type of vector matchVector defined above? I think it needs to be array only.
A int* is a pointer to an integer.
An int[3] is an array of 3 integers.
An array of 3 integers "decays" at the drop of a hat to a pointer to the first element.
When you do push_back(msmTemp), you push a pointer to the first element of msmTemp into the vector.
Pointers in C++ do not own what they point to. The vector afte the two push_backs contains two pointers, both to the same array msmTemp.
When you later iterate over the vector, you get two pointers in turn. Each points to msmTemp.
You then use [] to index those pointers. When you have a pointer to the first element of an array, you can use [] to access the other elements of the array. [0] is the first element, [1] the second, etc.
So you look at the 3 elements in msmTemp (luckily it has 3) and look at them twice, because you have two pointers into it in the vector.
You can inject elements like this:
std::vector<int> matchVector;
int msmTemp[3];
msmTemp[0]={1};
msmTemp[1]={2};
msmTemp[2]={3};
matchVector.insert( matchVector.end(), std::begin(msmTemp), std::end(msmTemp) );
etc. This ends up with a vector containing 6 elements, not two arrays.
If you want arrays as values you need std::array:
std::vector< std::array<int,3> > matchVector;
std::array<int, 3> msmTemp;
and then your code works as written. std::array is a library type that acts sort of like a raw array, but it doesn't have the decay-to-pointer problems of a raw array.
Forget that int[3] names a type. C arrays don't behave like sensible values. Arrays are named std::array<type, count>.
#include <vector>
#include <array>
int main()
{
std::vector<std::array<int, 3>> matchVector;
std::array<int, 3> msmTemp;
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
matchVector.push_back(msmTemp);
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
matchVector.push_back(msmTemp);
for(auto & arr : matchVector)
{
for(auto i : arr)
{
std::cout << i <<", ";
}
std::cout<<"\n";
}
return 0;
}
The other answers already explain how to fix your code. I think it's also good to explain why your code behaves the way it does:
Here you tell your compiler to create an std::vector that holds pointers to int:
std::vector<int*> matchVector;
Here you tell your compiler to allocate some space on the stack that fits 3 ints:
int msmTemp[3];
Here you tell your compiler to write the values 1, 2 and 3 into the memory previously allocated:
msmTemp[0] = 1;
msmTemp[1] = 2;
msmTemp[2] = 3;
Here you tell your compiler to take the address of that allocated space, treat it as a pointer and pass it to push_back. This is called array decaying:
matchVector.push_back(msmTemp);
Your matchVector now contains 1 element, which is a pointer to the address of the memory on your stack that was allocated to hold 3 ints.
Here you tell your compiler to write the values 4, 7 and 0 in the memory previously allocated. Note that this is still the same memory block as before:
msmTemp[0] = 4;
msmTemp[1] = 7;
msmTemp[2] = 0;
Here you tell your compiler to again take the address of the allocated space, treat it as a pointer and pass it to push_back:
matchVector.push_back(msmTemp);
Thus matchVector now contains 2 identical values, each a pointer to the same memory location. Specifically the memory location that you last wrote 4, 7 and 0 into.
I was asked the following question in a 30-minute interview:
Given an array of integers, remove the duplicates without using any STL containers. For e.g.:
For the input array [1,2,3,4,5,3,3,5,4] the output should be:
[1,2,3,4,5];
Note that the first 3, 4 and 5 have been included, but the subsequent ones have been removed since we have already included them once in the output array. How do we do without using an extra STL container?
In the interview, I assumed that we only have positive integers and suggested using a bit array to mark off every element present in the input (assume every element in the input array as an index of the bit array and update it to 1). Finally, we could iterate over this bit vector, populating (or displaying) the unique elements. However, he was not satisfied with this approach. Any other methods that I could have used?
Thanks.
Just use std::sort() and std::unique():
int arr[] = { 1,2,3,4,5,3,3,5,4 };
std::sort( std::begin(arr), std::end(arr) );
auto end = std::unique( std::begin(arr), std::end(arr) );
Live example
We can first sort the array then check if the next element is equal to the previous one and finally give the answer with the help of another array of size 2 larger than the previous one like this.
Initialize the second array with a value that first array will not take (any number larger/smaller than the limit given) ,suppose 0 for simplicity then
int arr1[] = { 1,2,3,4,5,3,3,5,4 };
int arr2[] = { 0,0,0,0,0,0,0,0,0,0,0 };
std::sort( std::begin(arr1), std::end(arr1) );
int position=1;
arr2[0] = arr1[0];
for(int* i=begin(arr1)+1;i!=end(arr1);i++){
if((*i)!=(*(i-1))){
arr2[position] = (*i);
position++;
}
}
int size = 0;
for(int* i=begin(arr2);i!=end(arr2);i++){
if((*i)!=(*(i+1))){
size++;
}
else{
break;
}
}
int ans[size];
for(int i=0;i<size;i++){
ans[i]=arr2[i];
}
Easy algorithm in O(n^2):
void remove_duplicates(Vec& v) {
// range end
auto it_end = end(v);
for (auto it = begin(v); it != it_end; ++it) {
// remove elements matching *it
it_end = remove(it+1, it_end, *it);
}
// erase now-unused elements
v.erase(it_end, end(v));
}
See also erase-remove idiom
Edit: This is assuming you get a std::vector in, but it would work with C-style arrays too, you would just have to implement the erasure yourself.
I am having another problem with manipulating data in a C++ array. I now want to decimate the array by removing all the zeros from it.
So for example say before I had array[4] = {1,2,0,0,4} It would become array[3] = {1,2,4}.
I know that I will need to use a for loop to iterate through the array storing the main data and that I will most likely need to initialize a new array to store the decimated data but I am not quite sure how to go about it.
You cannot resize a plain array, since it is statically allocated. Thus, it is probably better to use a vector from the standard library (STL). In such a way you would not need to create a new array. Actually, unless there is a strong reason, it is typically better to use std::vector or std::array (in C++11) than plain C-like arrays.
By using vector, you can do something like:
std::vector<int> v{1,2,0,0,4};
v.erase(
std::remove(v.begin(), v.end(), 0),
v.end());
After erasing the zero elements, the vector still has capacity 5, though (of course v.size() would return 3, as expected). If you can use C++11 then you can go a little bit further:
v.shrink_to_fit();
The call to shrink_to_fit reduces the vector's capacity to accommodate it to the actual number of elements in it (3 in the example). That could lead to memory savings (especially if there are many elements in the vector).
If you have to resize array's why not simply use std::vector. The example does it.
#include <vector>
#include <algorithm>
bool isZero (int i)
{
return i == 0;
}
int main()
{
std::vector<int> myarray;
myarray.push_back( 0 );
myarray.push_back( 1 );
myarray.push_back( 0 );
myarray.push_back( 3 );
myarray.push_back( 9 );
std::vector<int>::iterator newIter = std::remove_if( myarray.begin() , myarray.end() , isZero);
myarray.resize( newIter - myarray.begin() );
return 0;
}
If you don't know the content of the array, you cannot know how many
values will be non-zero, so your memory must be dynamically
allocated. Use std::vector.
std::vector<int> v;
std::copy_if(begin(array), end(array), std::back_inserter(v),
[](int x) { return x != 0; });
If you would start with a vector to begin with, you could manipulate the data in-place with erase-remove.
v.erase(std::remove(begin(v), end(v), 0), end(v));
If you really want to do it the hard way:
// count
auto non_zero_count = std::count_if(begin(array), end(array),
[](int x) { return x != 0;});
// allocate
int* new_array{new int[x]};
std::copy_if(begin(array), end(array), new_array,
[](int x) { return x != 0; });
There is really no solution to arrive at fixed size array here, unless you know all your inputs.
Suppose you have an array and you want to remove the 0 value in the array and resize it.
int toResize[] = {4,3,2,0,8,7,9,0,5,4,7,0}; //12 elements
vector<int>resized;
vector<int>::iterator it;
for(int i=0;i<12;i++){
int check = toResize[i];
if(check!=0){
resized.push_back(check);
}
}
for ( it=resized.begin() ; it < resized.end(); it++ )
cout << " " << *it;
Feel free to mark the question answered if you are satisfied.
OK, I am trying to get a sub array from an existing array and I'm just not sure how to do it. In my example I have a very large array, but I want to create an array from the last 5 elements of the array.
An example of what I am talking about would be:
int array1 = {1,2,3,...99,100};
int array2[5] = array1+95;
I know this isn't correct, but I am having some trouble getting it right. I want to get the elements 96 through 100 in array1 and put them into array2 but I don't want to copy the arrays. I just want array2 to start at the 96 element such that array1[96] and array2[0] would be pointing to the same location.
for this:
"such that array1[96] and array2[0] would be pointing to the same location."
you can do:
int *arr2 = arr1 + 96;
assert(arr2[0] == arr1[96] == 97);
A reference hack from a C programmer willing to subvert the type system to get what works:
int (&array2)[5] = (int (&)[5])(*(array1 + 5));
Now array2 will be an array for all intents and purposes, and will be a sub-array of array1, and will even be passable to that famous C++ array_size template function. Though the best way to handle this hackery is to hide it with more hackery!
#define make_sub_array(type, arr, off, len) (type (&)[len])(*(arr + off));
int (&array2)[5] = make_sub_array(int, array1, 5, 5);
Nice. Terrible by some standards, but the end result a) looks pretty neat, b) does exactly what you want, c) is functionally identical to an actual array, and d) will also have the added bonus (or mis-feature) of being an identical reference to the original, so the two change together.
UPDATE: If you prefer, a templated version (sort of):
template <typename T, size_t M>
T (&_make_sub_array(T (&orig)[M], size_t o))[]
{
return (T (&)[])(*(orig + o));
}
#define make_sub_array(type, array, n, o) (type (&)[n])_make_sub_array(array, o)
int (&array2)[5] = make_sub_array(int, array1, 5, 5);
We still have to pass the type. Since one of our arguments must be used as part the cast, we cannot cleanly (IMHO) avoid the macro. We could do this:
template <typename T, size_t M, size_t N>
T (&make_sub_array(T (&orig)[M], size_t o))[N]
{
return (T (&)[N])(*(orig + o));
}
int (&array2)[5] = make_sub_array<int, 15, 5>(array1, 5);
But the goal here is to make the calling code as clean as possible, and that call is a bit hairy. The pure-macro version probably has the least overhead and is probably the cleanest to implement in this case.
You can use boost::iterator_range to represent "slices" of arrays/containers:
#include <iostream>
#include <boost/range.hpp>
int main()
{
int array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// Create a "proxy" of array[5..7]
// The range implements the concept of a random sequence containter
boost::iterator_range<int*> subarray(&array[5], &array[7]+1);
// Output: 3 elements: 5 6 7
std::cout << subarray.size() << " elements: "
<< subarray[0] << " "
<< subarray[1] << " "
<< subarray[2] << "\n";
}
Note that the iterator range "knows" about the size of the sub-array. It will even do bounds checking for you. You cannot get that functionality from a simple pointer.
The usefulness of Boost.Range will become more apparent once you learn about STL containers and iterators.
If you're into linear algebra, Boost.uBlas supports ranges and slices for its matrices and vectors.
For a completely different approach you could do something like.
vector<int> v0(array1 + 95, array1 + 100);
or
vector<int> v1(array1, array1 + 100);
vector<int> v2(v1.begin() + 95, v1.end());
This would make a real copy of the elements of your vector.
In C++ you can use an int pointer as an int array, so getting the array2 to start at item 96 in array1 is easy, but there isn't any way to give array2 a size limit, so you can do this
int array2[] = &array1[96];
or this
int *array2 = &array1[96];
but NOT this
int array2[5] = &array1[96]; // this doesn't work.
On the other hand, C++ doesn't enforce array size limits anyway, so the only real loss is that you can't use sizeof to get the number of elements in array2.
note: &array1[96] is the same thing as array+96
edit: correction - int array[] = &array[96] isn't valid, you can only use [] as a synonym for * when declaring a function parameter list.
so this is allowed
extern int foo(int array2[]);
foo (&array1[96]);
int array1[] = {1,2,3,...99,100};
int *array2 = &array1[96];
int arr[] = { 1, 2, 3, 4, 5};
int arr1[2];
copy(arr + 3, arr + 5, arr1);
for(int i = 0; i < 2; i++)
cout << arr1[i] << endl;
The code is not safe if the boundaries are not handled properly.
You said you don't want to copy the array, but get a pointer to the last five elements. You almost had it:
int array1[] = {1,2,3,...99,100};
int* array2 = &array1[95];