Cplusplus std::set of bidimensional array - c++

I'm new to C++ and I need to use Set from the STL but I'm struggling with the concept.
I have an array like this int my_data[3]
I want to create (don't know if this is possible) a set with space for 3 ints and that the key for the set would be the int that is stored on the first column.
I also want to make a custom sort.
This is what I've tried but with no success.
struct sort_set {
bool operator() (const int& a, const int& b) const {
int* arr1 = (int*) a;
int* arr2 = (int*) b;
int diff = arr2[1] - arr1[1];
if (diff) {
return true;
} else if (diff == 0) {
int diff2 = arr2[2] - arr1[2];
if (diff2) {
return false;
}
}
return arr1[0] < arr2[0];
}
};
set<int[3],sort_set> data;
Can someone point me in the right direction?

You cannot have arrays as elements of containers. They're not assignable nor copyable.
Use std::array<int, 3> if you have C++11 avaliable, or define a custom class otherwise.

Related

Accessing array values within class, c++

I am implementing a set in C++ using an array where elements with values of 0 are not in the set and those with 1 are in the set. For example, if my set is {1,5} my array would look like: [0, 1, 0, 0, 0, 1]. I am overloading the "/" operator to show the set difference, so if x is in set A and x is not in set B then x is in A/B. I pass the second Set object to the overloaded function by reference, but I am unable to access it's member variable "arr" which stores the array.
This is the header file:
class Set
{
public:
Set();
virtual ~Set();
Set(int);
int* arr;
int len;
Set operator/(const Set&);
friend ostream& operator<<(ostream&, const Set&);
int* getArray() const;
};
And here is the .cpp file:
Set::Set(int n) {
arr = new int[n+1];
len = n+1;
}
Set Set::operator/(const Set &s){
int* arr2 = s.getArray();
for (int i = 0; i < this->len; i++) {
if (this->arr[i] == 1) {
if (arr2[i] == 0) {
this->arr[i] = 1;
}
else {
this->arr[i] = 0;
}
}
}
return *this;
}
int* Set::getArray() const { return arr; }
If I attempt to print the values of arr2 I get values that appear to be addresses. How do I access the actual values of arr2?
Edit: I have not learned the "Rule of 3" in any class I've taken so I have no understanding how this could make my code not work. I've just done some research on it, but I would appreciate a short explanation on how to implement that in this case. Also, I am not allowed to use containers, so I can't use a vector as suggested in the comments.

Function that checks if an array is sorted

So I'm just a beignner programmer when it comes to C++, and I have to write a function that checks if an int array is sorted using pointers (no index notations allowed), and here's what I have so far:
bool isSorted(const int *ar, int size) {
bool sorted = true;
const int *ptr1, *ptr2, *ptr3;
ptr1 = ar;
ptr2 = ar+1;
ptr3 = ar+size;
for (ptr1; ptr1 < ptr3; ptr1++) {
for (ptr2; ptr2 < ptr3; ptr2++) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
}
return sorted;
}
However, I can't seem to get it to work as it always returns true regardless of whether the array is sorted or not. Any help is appreciated, thanks.
"The more you overthink the plumbing, the easier it is to stop up the
drain" -- Scotty, Star Trek III.
You are making this much more complicated than it has to be.
Ask yourself a basic question: what is a sorted array?
Answer: an array in which each successive element is not less than its preceding element.
Therefore: to check if the array is sorted, just look for an element that's less than its previous element. If you found one, the array is not sorted. If you couldn't find one, the array must be sorted.
bool isSorted(const int *ar, int size) {
if (size == 0)
return true; // Edge case
int previous_value= *ar;
while (size)
{
if (*ar < previous_value)
return false;
previous_value= *ar;
++ar;
--size;
}
return true;
}
No index notations, just a single pointer. No need to do any kind of a nested search, etc... If you want to use only pointers, you could do this:
bool isSorted(const int *ar, int size) {
const int *previous_value=ar;
while (size)
{
if (*ar < *previous_value)
return false;
previous_value= ar;
++ar;
--size;
}
return true;
}
Actually, I like this version even better.
You should keep ptr2 always be ptr+1,so you need to initialize ptr2 in second for() .
And I think only one loop is better.
for(; ptr2 < ptr3; ++ptr1, ++ptr2) {
if (*ptr1 > *ptr2) {
sorted = false;
}
}
return sorted;

How to modify array inside function which doesn't take this array as parameter

What I need is to modify pTab array inside modifyAA(int a) function.
How can I achieve this?
Example Code:
int modifyAA(int a);
int main()
{
*pTab=new int[10]; int a=13;
for(int i=0;i<=9;i++)
pTab[i]=88;
modifyAA(a);
//I'd like to have pTab to be modified after function invoke
return 0;
}
modifyAA(int a){
for(int i=0;i<=9;i++)
pTab[i]=pTab[i]+1;
a=a+pTab[0];
return a;
};
Is it possible to modify array when function doesn't take it as parameter ?
You can use a global variable for the pointer to the first element of the dynamic array:
int * pTab;
int printAA(int a)
{
for (unsigned int i = 0 i != 10; ++i)
{
++pTab[i];
}
return a + pTab[0];
}
int main()
{
pTab = new int[10];
// populate
printAA(13);
}
You could use global variables. This could be practical especially if several functions like printAA() would need to call it.
However there is a risk of using *pTab before it's allocated. And also, you remember now the size, but if later you'd change the size to 10, you would have to find back all the places where you've hardcoded the 10 or the 9.
If the goal of not passing the parameter is mainly because you call the function a lot of times you could opt for a std::bind, creating a kind of dynamic function:
#include <iostream>
#include <functional>
int printDynArr(int* dynarr, size_t sz, int a) // proper function with all parameters
{
for (size_t i = 0; i < sz; i++)
dynarr[i]++; // It's a pointer, so you modify the data where it is stored
a += dynarr[0];
return a;
};
int main()
{
int *pTab = new int[10]; int a = 13; //declaring and alocating - dynamic array
auto printAA = std::bind<int>(printDynArr, pTab, 10, std::placeholders::_1); // dynamic function shortcut with predefind parameters
...
printAA(a); //using function without giving pTab as argument.
std::cin.get();
return 0;
}
If you were to do this "The C++ way", you could use a vector and iterators from stdlib, like so:
#include <vector>
typedef std::vector<int> PTab; // Defines a type for your pTab, it's a vector of integers
int printAA(PTab::iterator from, PTab::iterator until, int a); //declaring some func
int main()
{
PTab pTab(10, 88); // Initializes pTab vector to 10 elements all containing 88
int a = 0;
printAA(pTab.begin(), pTab.begin() + 10, a);
return 0;
}
int printAA(PTab::iterator from, PTab::iterator until, int a)
{
for (PTab::iterator i = from; i != until; ++i)
{
*i++; // Increments current element by 1
}
a += *from; // Adds the value of the from element to a
return a;
};
This way you don't pass the vector itself to the function, instead, you only pass a range of iterators, which gives the function a possibility to access the contents of the vector, but not to modify the vector object itself (ie. clear it, resize it, etc.).

Reading dynamically allocated arrays into lists

Currently, I have been reading lists of data from a binary data file programmatically as follows:
tplR = (double*) malloc(sampleDim[0]*sizeof(double));
printf("tplR = %d\n", fread(tplR, sizeof(double), sampleDim[0], dfile));
However, as I want to use find_if() function on those lists, I would need to get tplR into a list type in stl. In terms of general C++ programming practice, is it usually good practice to make tplR into a list only when I really have to?
If I do make another member variable, for example, tplRList, what would be the easiest way of pushing all sampleDim[0] number of double precision entries into tplRList from tplR? Pushing them one by one until the incremental counter is equal to sampleDim[0]?
Thanks in advance.
You can use find_if with the array like this:
bool equals(int p)
{
return p == 9;
}
int main(int argc,char *argv[])
{
int a[10];
for(int i = 0; i < 10; ++i)
{
a[i] = i;
}
int* p = std::find_if(a, a+10, equals);
cout<<*p;
return 0;
}
You're mistaken in your assumptions. std::find_if() merely requires an iterator, not necessarily an STL iterator. As it happens, double* supports both * and ++, so it too is an iterator.
bool checkValue(double val);
std::find_if(tplR, tplR + sampleDim[0], checkValue);
#include <boost/lambda/lambda.hpp\>
using namespace boost::lambda;
static const double whateverValueYouWant(12.);
double *const tplR = (double*) malloc(sampleDim[0]*sizeof(double));
const size_t actualItemsRead = fread(tplR, sizeof(double), sampleDim[0], dfile);
printf("tplR = %d\n", actualItemsRead );
const double *begin = tplR;
const double *const end = tplR + actualItemsRead;
const double *const foundItem = std::find_if( begin, end, _1== whateverValueYouWant);
if( foundItem!=end )
{
//value found
}
else
{
//no such value
}

How can I return an array?

Is there any way to return an array from a function? More specifically, I've created this function:
char bin[8];
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin[i]='1';
ascii=2^i-ascii;
}
else
{
bin[i]='0';
}
}
and I need a way to return bin[].
You can't do that but you can:
return a dynamicaly allocated array - best owned by a smart pointer so that the caller does not have to care about deallocating memory for it - you could also return something like an std::vector this way.
populate an array/vector passed to you as an argument by pointer (suggested) or a non const reference.
Your array is a local variable allocated on the stack. You should use new [] to allocate it on the heap. Then you can just say: return bin;. Beware that you will have to explicitly free it with delete [] when you are done with it.
You are really asking the wrong question. If you want to do string processing in C++, use the std::string and/or std::vector classes, not arrays of char. Your code then becomes:
vector <char> func() {
vector <char> bin(8);
for( int i = 7; i >= 0; i-- ) {
int ascii='a';
if ( 2 ^ i - ascii >= 0 ) {
bin[i] = '1';
ascii = 2^i - ascii;
}
else {
bin[i] ='0';
}
}
return bin;
}
I think your best bet is to use a vector. It can function in many ways like an array and has several upsides (length stored with type, automatic memory management).
void Calculate( std::vector<char>& bin) {
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin.push_back('1');
ascii=2^i-ascii;
}
else
{
bin.push_back('0');
}
}
}
If you want to return a copy of the array (might make sense for small arrays) and the array has fixed size, you can enclose it in a struct;
struct ArrayWrapper {
char _bin[8];
};
ArrayWrapper func()
{
ArrayWrapper x;
// Do your stuff here using x._bin instead of plain bin
return x;
}
Or just use a std::vector as has been already suggested.
Similar implemented to #ari's answer, i want to say there is already a boost solution, boost::array solving your problem:
boost::array<char, 8> f() {
boost::array<char, 8> bin;
for(int i = 7; i >= 0; i--) {
int ascii = 'a';
if(2 ^ i-ascii >= 0) {
bin[i] = '1';
ascii = 2 ^ i-ascii;
} else {
bin[i] = '0';
}
}
}
...
boost::array<char, 8> a(f());
[I'm not sure what you want to do with that algorithm though, but note that i think you want to do 1 << i (bit-wise shift) instead of 2 ^ i which is not exponentiation in C++.]
Boost array is a normal array, just wrapped in a struct, so you lose no performance what-so-ever. It will also be available in the next C++ version as std::array, and is very easy to do yourself if you don't need the begin()/size()/data()-sugar it adds (to be a container). Just go with the most basic one:
template<typename T, size_t S>
struct array {
T t[S];
T& operator[](ptrdiff_t i) { return t[i]; }
T const& operator[](ptrdiff_t i) const { return t[i]; }
};
But as usual, use the tools already written by other people, in this case boost::array. It's also got the advantage of being an aggregate (that's why it has no user declared constructor), so it allows initializing with a brace enclosed list:
boost::array<int, 4> a = {{ 1, 2, 3, 4 }};
you need to pass array bin as an argument in your function.
array always pass by address, therefore you dont need to return any value.
it will automatically show you all changes in your main program
void FunctionAbc(char bin[], int size);
void FuncationAbc(bin, size)
{
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin[i]='1';
ascii=2^i-ascii;
}
else
{
bin[i]='0';
}
}
}
You'll want to pass by reference, as follows:
void modifyBin(char (&bin)[8])
{
/* your function goes here and modifies bin */
}
int main()
{
char bin[8];
modifyBin(bin);
/* bin has been updated */
return 0;
}
I think that everyone else answered this one... use a container instead of an array. Here's the std::string version:
std::string foo() {
int ascii = 'a';
std::string result("00000000");
for (int i=7; i>=0; --i) {
if (2^i-ascii >= 0) {
result[i] = '1';
ascii = 2^i-ascii;
}
}
return result;
}
I'm not really sure if 2^i-ascii is want you want or not. This will be parsed as (2 ^ (i - ascii)) which is a little strange.