This question already has answers here:
Comparing arrays for equality in C++
(11 answers)
Closed 9 years ago.
I am trying to do function which compare to arrays and returns true if they are same. Now the arrays are simple, it will be advanced later but I am stuck on the testEqual function.
So here is code
int n = 5;
int array[5] = {5,10,3,4,7};
bubbleSort(pole,n);
int array2[5] = {3,4,5,7,10};
testEqual( array , array2 , "bubbleSort");
And here is testEqual function I need to remake on arrays but I don't know how.
bool testEqual(int i1, int i2, const string testName) {
bool myresult = (i1 == i2);
return myresult;
}
The other functions like bubbleSort are fine I just need to remake testEqual.
Following may help:
template <typename T, std::size_t N>
bool isEqual(const T (&lhs)[N], const T (&rhs)[N])
{
return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
}
If you use std::array, you have that for free. (And the syntax is more friendly).
To compare two arrays you could use standard algorithm std::equal.
For example
bool testEqual( const int *first1, const int *last1, const int *first2, const int *last2 )
{
return std::equal( first1, last1, first2, last2 );
}
It can be called the following way
testEqual( array, array + 5, array2, array2 + 5 );
As for your function then it is invalid.
It simply compares two integers and it is not clear what is the meaning of the third parameter
bool testEqual(int i1, int i2, const string testName) {
bool myresult = (i1 == i2);
return myresult;
}
i see it the same as H2CO3 "what qualifies as equal?"
the approach with std::equal does not match to the arrays you are providing...std::equal will take same elements AND order.
I modified the example from cplusplus.com
int main () {
int myints[] = {20,40,60,80,100};
int myints2[] = {20,100,60,40,100};
std::vector<int>myvector (myints2,myints2+5); // myvector: 20 40 60 80 100
// using default comparison:
if ( std::equal (myvector.begin(), myvector.end(), myints) )
std::cout << "The contents of both sequences are equal.\n";
else
std::cout << "The contents of both sequences differ.\n";
return 0;
}
resulting in
The contents of both sequences differ.
so for using std::equal, you should sort them before
You can also use std::equal. For example :
#include <algorithm>
int *ints;
ints = new int[10];
bool EqualArray(const Object& obj)
{
return std::equal(ints,ints + 10, obj.ints);
}
Of course you can also overload the operator== for other things. Unfortunately you can't overload it for primitive arrays, because overloading operators is only allowed if at least one argument is a class (or struct) type. But you could override it to compare vector with array. Something like:
template<typename T, typename Alloc, size_t S>
bool operator==(std::vector<T, Alloc> v, const T (&a)[S])
{
return v.size() == S && std::equal(v.begin(), v.end(), a);
}
(this takes reference to array not degraded to pointer to check it's declared size first and is therefore safe).
Related
This question already has answers here:
May I treat a 2D array as a contiguous 1D array?
(6 answers)
Closed 3 years ago.
Can I be certain the following code will work?
int sum_array(int *array, size_t size)
{
int i;
int sum = 0;
for (i=0;i<size;i++)
sum += *(array+i);
return sum;
}
int main()
{
int two_d_array[4][3] = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}};
int sum = sum_array(&two_d_array[0][0], 12);
printf("%d", sum);
}
While it makes sense for a 4-by-3 array to be laid out in memory exactly as a 12 element array, is it guaranteed? Since I seem to be cheating the type system, I am not so sure something could go wrong (for example, padding being added to int[3]).
Bonus points if you can elaborate on what happens if I use something other than ints in my array, and provide the relevant quote from the standard.
for example, padding being added to int[3]
There's no danger of that. Arrays are guaranteed to not have padding. The memory layout itself is guaranteed, while the pointer arithmetic is technically undefined, as per this quote mentioned in the comments: expr.add/4 Thus:
Is 2D array (T[N][M]) traversal by pointer (T*) guaranteed to work?
Technically not according to my understanding of the standard, unfortunately.
Here is a version of standard std::accumulate that iterates the innermost elements of a multi dimensional array of any dimension count as if it were a flat array:
template<class T, unsigned size, class BinOp = std::plus<>>
auto arr_accumulate(
T (&arr)[size], std::remove_all_extents_t<T> init = {}, BinOp op = {})
{
if constexpr (std::is_array_v<T>) {
return std::accumulate(std::begin(arr), std::end(arr), init,
[&](const auto& l, const auto& r) {
return arr_accumulate(r, l, op);
}
);
} else {
return std::accumulate(std::begin(arr), std::end(arr), init, op);
}
}
// usage
int sum = arr_accumulate(two_d_array, 0);
I haven't benchmarked this to see if there's any overhead. With compile time constant input such as in your example, the sum was calculated at compile time.
Another implementation; only for trivial types:
template<class T, unsigned size>
constexpr auto flat_size (T (&arr)[size]) {
using E = std::remove_all_extents_t<T>;
return sizeof arr / sizeof (E);
}
template<class T, unsigned size, class BinOp = std::plus<>>
auto arr_accumulate_trivial(
T (&arr)[size], std::remove_all_extents_t<T> init = {}, BinOp op = {})
{
using E = std::remove_all_extents_t<T>;
static_assert(std::is_trivially_copyable_v<E>);
std::array<E, flat_size(arr)> flat;
std::memcpy(flat.data(), arr, sizeof arr);
return std::accumulate(std::begin(flat), std::end(flat), init, op);
}
I would like to compare a vector with an array assuming that elements are in different order.
I have got a struct like below (this struct hasn't got "operator==" and "operator<" -> so I can't use sort):
struct A
{
int index;
A(int p_i) : index(p_i) {}
};
The size of the vector and the array is the same:
std::vector<A> l_v = {A(1), A(2), A(3)};
A l_a[3] = {A(3), A(1), A(2)};
I am looking for some function from std like below "some_function_X" which can find element in specific way using lambda, or function which can compare only specific field like "lhs.index == rhs.index" -> by specific field in class without "operator==" and "operator>" etc.
bool checkIfTheSame(const std::vector<A>& l_v, const A& l_a)
{
for(usigned int i=0; i< 3; ++i)
{
if(!std::some_function_X(l_v.begin(), l_v.end(), l_a,
[](const A& lhs, const A& rhs){
return lhs.index == rhs.index;
})) return false;
}
return true;
}
Thanks.
this struct hasn't got "operator==" and "operator<" -> so I can't use sort
Firstly, only operator< is required. Secondly, it doesn't have to be defined as a member function. The following free function works with std::less (which is what std::sort uses if you don't pass a functor for comparison).
bool operator<(const A& a, const A& b) {...}
Or, you can use a custom comparison functor instead of std::less.
Sorting the array and the vector and then comparing should have better asymptotic runtime complexity than trivially iterating one and checking if the element exists in the other using linear search.
Another idea would be to sort only one of them, iterate the unordered and test the existence in sorted container with binary search. That has same asymptotic complexity as sorting both.
If you can't modify either container, then you can make a copy for sorting. That costs some memory, but is still asymptotically faster than the trivial approach. std::partial_sort_copy can save you a few copies by sorting directly to the copy.
look here : http://www.cplusplus.com/reference/algorithm/
find with lambda expression find if
function which can compare only specific field like "lhs.index == rhs.index" -> by specific field in class without "operator==" and "operator>" etc.
to check if your 2 containers contains same datas with a predicate : equal with a custom predicate
if you just want to check if your container container a specific value, have a look here : How to find if an item is present in a std::vector?
I'm not sure I fully understand what you want but I'll take a guess that you want to check whether two arrays (which have different container types) are equivalent, that is for each item in array A there is a corresponding item somewhere in array B for which some predicate returns true.
You want to do this on two arrays that are not only of different types, but also possibly in a different order.
This is one way to do it:
struct Foo
{
Foo(int i) : _index { i } {}
int index() const {
return _index;
}
private:
int _index;
};
// params:
// first1, last1 bound the first array
// first2, last2 bound the second array
// pred is a predicate that checks for equivalents
// order is a predicate that performs weak ordering
template<class Iter1, class Iter2, class Pred, class Order>
bool checkIfTheSame(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred, Order order)
{
const auto len1 = last1 - first1;
const auto len2 = last2 - first2;
if (len1 != len2)
return false;
using namespace std;
using item1_type = typename std::iterator_traits<Iter1>::value_type;
using item2_type = typename std::iterator_traits<Iter2>::value_type;
std::vector<std::reference_wrapper<item1_type>> refs1 { first1, last1 };
std::sort(begin(refs1), end(refs1), order);
std::vector<std::reference_wrapper<item2_type>> refs2 { first2, last2 };
std::sort(begin(refs2), end(refs2), order);
for (size_t i = 0 ; i < len1 ; ++i) {
if (!pred(refs1[i], refs2[i]))
return false;
}
return true;
}
simple example:
using namespace std;
bool same_indexes(const Foo& f1, const Foo& f2) {
return f1.index() == f2.index();
}
bool sort_indexes(const Foo& f1, const Foo& f2) {
return f1.index() < f2.index();
}
int main(int argc, const char * argv[])
{
vector<Foo> x { 1, 2, 3 };
Foo y[] = { 3, 2, 1 };
cout << checkIfTheSame(begin(x), end(x), begin(y), end(y), same_indexes, sort_indexes) << endl;
return 0;
}
If you do not have any way to sort the array or the vector, but you are only able to know if two elements are equal, the only method is an exhaustive search.
Quite often I have two variables foo1 and foo2 which are numeric types. They represent the bounds of something.
A user supplies values for them, but like a recalcitrant musician, not necessarily in the correct order!
So my code is littered with code like
if (foo2 < foo1){
std::swap(foo2, foo1);
}
Of course, this is an idiomatic sort with two elements not necessarily contiguous in memory. Which makes me wonder: is there a STL one-liner for this?
I suggest to take a step back and let the type system do the job for you: introduce a type like Bounds (or Interval) which takes care of the issue. Something like
template <typename T>
class Interval {
public:
Interval( T start, T end ) : m_start( start ), m_end( end ) {
if ( m_start > m_end ) {
std::swap( m_start, m_end );
}
}
const T &start() const { return m_start; }
const T &end() const { return m_end; }
private:
T m_start, m_end;
};
This not only centralizes the swap-to-sort code, it also helps asserting the correct order very early on so that you don't pass around two elements all the time, which means that you don't even need to check the order so often in the first place.
An alternative approach to avoid the issue is to express the boundaries as a pair of 'start value' and 'length' where the 'length' is an unsigned value.
No, but when you notice you wrote the same code twice it's time to write a function for it:
template<typename T, typename P = std::less<T>>
void swap_if(T& a, T& b, P p = P()) {
if (p(a, b)) {
using std::swap;
swap(a, b);
}
}
std::minmax returns pair of smallest and largest element. Which you can use with std::tie.
#include <algorithm>
#include <tuple>
#include <iostream>
int main()
{
int a = 7;
int b = 5;
std::tie(a, b) = std::minmax({a,b});
std::cout << a << " " << b; // output: 5 7
}
Note that this isn't the same as the if(a < b) std::swap(a,b); version. For example this doesn't work with move-only elements.
if the data type of your value that you're going to compare is not already in c++. You need to overload the comparison operators.
For example, if you want to compare foo1 and foo2
template <class T>
class Foo {
private:
int value; // value
public:
int GetValue() const {
return value;
}
};
bool operator<(const Foo& lhs, const Foo& rhs) {
return (lhs.GetValue() < rhs.GetValue());
}
If your value is some type of int, or double. Then you can use the std::list<>::sort member function.
For example:
std::list<int> integer_list;
int_list.push_back(1);
int_list.push_back(8);
int_list.push_back(9);
int_list.push_back(7);
int_list.sort();
for(std::list<int>::iterator list_iter = int_list.begin(); list_iter != int_list.end(); list_iter++)
{
std::cout<<*list_iter<<endl;
}
I have a problem that requires me to count the number of instances within this array that uses either std::count() or std::find(). I'm aware of how to do this using a standard data (see bottom code) type but not with the NameContainer that I'm using.
//Type
struct NameContainer{
char name [32];
}
//An array of containers
NameContainer *_storedNames = new NameContainer[_numberOfNames];
//An example of what I'm trying to do with a string rather than the NameContainer
std::vector<string> v(_storedNames, _storedNames + _numberOfNames);
//returns an numeric value
return std::count(v.begin(), v.end(), nameToSearch))
You can use a functor
struct names_equal {
string comp_to;
names_equal(string a) : comp_to(a) {}
bool operator()(NameContainer& p) {
return p.name == comp_to;
}
};
And count like
cout << std::count_if(v.begin(), v.end(), names_equal(nameToSearch));
This way nameToSearch doesn't have to be hard coded.
EDIT
If you can not use count_if, and has to be count then modify NameContainer and overload == for it.
struct NameContainer{
string name;
bool operator==(string str) {
return name == str;
}
};
Then count like this
cout << std::count(v.begin(), v.end(), nameToSearch);
you can use count_if and you provide a predicate (Unary function that accepts an element in the range as argument, and returns a value convertible to bool)
for example
bool myPred(NameContainer n){
return (strcmp(n.name, "name") == 0); }
std::vector<NameContainer> v(_storedNames, _storedNames + _numberOfNames);
int i=std::count_if(v.begin(), v.end(), myPred))
you can use strcmp() to compare character arrays.
if using only std::count or std::find:
both count and find takes the same type argument to compare as the type of conatainer, in your case NameContainer. std::count will execute following to compare searched values:
if (*first == val)
what means you have to overload operator== taking your class as arguments.
inline bool operator == (const NameContainer &first,const NameContainer &second){
return (strcmp(first.name,second.name)==0);
}
and then call std::count(v.begin(), v.end(), myObjectPredicate))
with myObjectPredicate being your NameContainer class object with name to be searched in vector.
so here is working solution. you might improve it in details:
struct NameContainer{
char name [32];
};
inline bool operator== (const NameContainer &first,const NameContainer &second){
return (strcmp(first.name,second.name)==0);
}
int main(int argc, char** argv) {
NameContainer* _storedNames = new NameContainer[1];
std::vector<NameContainer> vn(_storedNames, _storedNames + 1);
const char* cc="piotr";
NameContainer nc;
memcpy(nc.name,cc,strlen(cc)+1);
vn.push_back(nc);
NameContainer myObjectPredicate;
memcpy(myObjectPredicate.name,cc,strlen(cc)+1);
int count=std::count(vn.begin(), vn.end(), myObjectPredicate);
std::cout<<count;
return 2400;
}
output:
1
Read the docs on std::count, you'll see that it uses operator== for it's comparisons. Therefore, if you want to use std::count, the thing you want to compare MUST have an operator== defined for it. In your case, you could add one to your NameContainer pretty easily.
I have in memory an array of 16 byte wide entries. Each entry consists of two 64 bit integer fields. The entries are in sorted order based upon the numerical value of the first 64 bit integer of each entry. Is it possible to binary search this with the STL without first loading the data into a std::vector?
I have seen that I can use the STL lower_bound() method on plain arrays, but I need it to ignore the second 64 bit field of eachy entry. Is this possible?
You don't need to use std::vector<>, but it is easiest if you get your data into a proper data type first:
#include <cstdint>
struct mystruct
{
std::int64_t first, second;
};
Your question is unclear as to the way you're storing this data now, but I'm assuming it's something like the above.
Then you can either overload operator< for your data type:
#include <algorithm>
bool operator <(mystruct const& ms, std::int64_t const i)
{
return ms.first < i;
}
int main()
{
mystruct mss[10] = { /*populate somehow*/ };
std::int64_t search_for = /*value*/;
mystruct* found = std::lower_bound(mss, mss + 10, search_for);
}
Or you can define a custom comparator and pass that to std::lower_bound:
#include <algorithm>
struct mystruct_comparer
{
bool operator ()(mystruct const& ms, std::int64_t const i) const
{
return ms.first < i;
}
};
int main()
{
mystruct mss[10] = { /*populate somehow*/ };
std::int64_t search_for = /*value*/;
mystruct* found = std::lower_bound(mss,
mss + 10,
search_for,
mystruct_comparer());
}
Naturally, in C++11, a lambda can be used instead of a full-fledged functor for the comparator.
struct Foo {
int64_t lower;
int64_t upper;
};
Foo arr[N];
Foo f;
f.lower = 42;
auto it = std::lower_bound(arr, arr + N, f,
[](const Foo& lhs, const Foo& rhs){ return lhs.lower < rhs.lower; });
Yes, it's possible. You need to create a class which satisfies the requirements for a ForwardIterator that iterates your elements in the proper way (a pointer of a 16 byte structure will probably do the trick). Then you need to define your own Compare to compare elements ignoring the second 64 bit field.
more info.
template <class ForwardIterator, class T, class Compare>
ForwardIterator lower_bound ( ForwardIterator first, ForwardIterator last,
const T& value, Compare comp );