Comparing arrays

Is there any way to check if all of the elements of an array are equal to something at the same time?
Something like this:

switch(myarray[])  {
case { 9, 8, 6, 4, 7, 3}:
blahblah;
break;

or in an if statement:

if(myarray[] == {8, 2, 4})  {
blahblah;
}

If that's not possible, how could I accomplish the same thing. I won't tell why yet, but I want a switch structure to be able to do something depending on what combination of some buttons are pressed.

I know of two ways. Wrap it in a class:

[WARNING:UNTESTED CODE]

class Secret
{
    int *pArray;
    int iCount;

public:
    Secret(){pArray=NULL;iCount=0;};
    void Set(int *Array, int MemberCount){pArray=Array;iCount=MemberCount;};

    bool operator == (Secret &Other){ for(int i=0;i<iCount;i++){ if(Other.pArray[i]!=pArray[i]) return false;} return true;};
};

int Code[5] = {0,1,2,3,4};
int Pressed[5] = {0,0,0,0};

Secret s;
Secret current;

void setup()
{
   // join the class to the memory in the array.
   s.Set(Code,5);
   // join the class to the memory in the array.
   current.Set(Code,5);
}

void loop()
{
    // somehow alter current to set parts of it like:
    // Pressed[1] = 'c';

   // executes the class' == operator.
    if(current==s)
    {
         // matches!
    }
}code]


You can also do it with templates:
[WARNING: UNTESTED CODE]
[code]template <class T,int N> class MyArray 
{
    T datablock [N];

  public:
    MyArray()
    {
    }
    
    void setmember (int x, T value) {
       datablock[x]=value;
       return 0;
    }
    T getmember (int x) {
       return datablock[x];
    }
   bool operator == (const MyArray<T,N> &other) const  { for(int i=0;i<N;i++){ if(other.datablock[i]!=datablock[i]) return false;} return true;};
};

MyArray<int, 5> secret;
MyArray<int, 5> current;

void setup()
{
}

void loop()
{
    // somehow alter current to set parts of it like:
    // current.setMember(0, 'c');

    // do a compare.
    if(current==secret)
    {
         // matches!
    }
}

But, I haven't put this on the device or throught the compiler yet.

If you want to see if buttons are in particular states you can store the states as bits in an integer and then compare that integer to one or more values.

You can use the Arduino bit functions to set and get the bit values, here is some pseudocode:
for switch index from 0 to n-1, bitWrite( stateVariable, index, digitalRead(switchPins[index]);

stateVariable will hold a bitmask of the switches and you can compare this to the values you care about.

Could both of you explain more thouroughly? I'm not very advanced at c or c++. And I don't really understand too well what either of you are saying. :-?

If you post a sketch that illustrates the functionality you are looking for then it will be easier to show how you can implement a solution

Well I've just tested a rather monstrous function that I wrote to do this on g++ (though it only uses standard C libraries you'll need to specifically #include <stdarg.h>):

Disclaimer: This code seems horrible to me and should probably never be used.

#include <stdarg.h>

template <class type> bool arraysEqual(type array[], ...)
{
        int length = sizeof(array)/sizeof(type);
        bool result = true;
        type val;
        va_list vl;
        va_start(vl, length);
        for(int i=0; i<length; ++i)
        {
                val=va_arg(vl, type);
                if(val != array[i])
                {
                        result = false;
                        break;
                }
        }
        va_end(vl);
        return result;
}

void loop()
{
        int test[] = {1,2,3,4,5};
        if(arraysEqual(test, 1, 2, 3, 4, 5)
        {
                //should happen
        }
        if(arraysEqual(test, 1, 1, 1, 1, 1)
        {
                //shouldn't happen
        }
}

This will come up with a warning: "second parameter of 'va_start' not last named argument" due to not declaring the number of arguments in the parameters of arraysEqual() meaning that if you call it with a lower number of arguments than are in the array you pass all sorts of ugly things could happen. One easy fix for this is to declare length before calling the function and have it as a parameter, but I was mostly interested in making a function for an arbitrary length array.

The va_ functions use stdarg (documented here) and macros to allow an unlimited number of arguments in a function.

I would suggest that you try and implement something like c++ std::vector with templates similar to the second example Spinlock gave.

I suspect that the OP is not up for implementing template classes.

Here is a sketch that shows how to use the Arduino bit functions to check the states of switches. The showFlags function is only used to print values to the serial port to show what is going on, it would not be needed in the actual application.

// this code assumes that pull-down resistors are used - invert the state if using pull-ups.

int pins[] = {2,3,5,7,8,9}; // array holding the pins connected to switches
int number_of_pins = sizeof(pins)/ sizeof(pins[0]);  // determines how many pins in the above array

int switchStates = 0; // this will hold a bitmask of switch states 

void setup() 
{ 
  Serial.begin(9600);
}

void loop()
{
    // save the switch states as bits in the variable switchStates
    for(int i=0; i < number_of_pins; i++)
    {
      // set bits in switchState to represent the state of the switches
      int state = digitalRead( pins[i]);     
      bitWrite(switchStates, i, state);      
    }
    
    switch (switchStates)
    {
      // test for some combinations of switches we care about
      case  B000001: Serial.println("the first switch (pin 2) is pressed"); break;
      case  B000101: Serial.println("switches on pins 2 and 5 are pressed"); break;
      case  B111111: Serial.println("all switches are pressed"); break;      
    } 
    showFlags();   
    delay(1000);
} 

// reports flags that are set to see how the switchStates variable is used
void showFlags()
{
    Serial.println(switchStates, BIN);
    for(int sw = 0; sw < number_of_pins; sw++)
    {
      Serial.print("Switch ");
      Serial.print(sw);
      if( bitRead(switchStates, sw) == true)
         Serial.println(" is pressed ");
      else   
         Serial.println(" is not pressed");      
    }
    Serial.println();
}

As long as you're only comparing arrays of chars/bytes (8 bit data types), then you can use memcmp() (and memcmp_P()).

Here is an example:

#include <avr/pgmspace.h>

// Arrays we want to compare to
const byte array1[] PROGMEM = {1,2,3,4,5};
const byte array2[] PROGMEM = {6,7,8,9,10};

void setup()
{
  byte myarray[5];

  Serial.begin(9600);
  
  for(int i = 1; i <= 5; i++)
  {
    myarray[i - 1] = i;
  }
  
  if(memcmp_P(myarray, array1, 5) == 0)
  {
    Serial.println("YAY!");
  }
  
  if(memcmp_P(myarray, array2, 5) == 0)
  {
    Serial.println("Impossible!");
  }

}

void loop()
{
}

(memcmp() is in string.h, and memcmp_P() is in avr/pgmspace.h)

b

I think I'll be using mem's idea. His idea seems simple and effective for what I want to use it for. Just to be certain, that can be used if there are more than 8 buttons, right? The switchesstate can he more than 8 bits, right?

In the example posted up to 15 switches can be handled If you need more (up to 31) change switchStates from an int to a long:
long switchStates = 0;

Everything else can remain as is

Just a tip: If you use the Bnn..nn notation for binary numbers, [i]binary.h[/i] only handles 8 bit numbers. The compiler handles standard "0b" notation though, so instead use e.g. 0b0000000000000101 for larger variables (ints, longs).

b

Cool, thanks for the tips.