Curnelious
Curnelious

Reputation: 1

Efficient way to match two arrays

I have 2 arrays , one is inputs pins names, the other is their actual numbers.

const char *pins[]={"d1","d2","d3","d4","d5","o1","o2","o3","o4"};
const int pinsNumbers[9]={1,2,19,4,14,6,12,15,17};

When I get as an input "d3" , I would like to find the corresponding - 19 .

  1. Is there more efficient way to save these "matches" ?
  2. How would one loop over the pins array with an input and find its match- as efficiently as possible ?

Upvotes: 2

Views: 136

Answers (4)

imbearr
imbearr

Reputation: 1019

As easy and fast as it is possible. And if you will use two consecutive symbols (for example 'a' and 'b') - you can calculate and check it just as offset inside groups in code bellow. Ideone online executable code.

#include <stdio.h>

#define D1_VAL  1
#define D2_VAL  2
#define D3_VAL  19
#define D4_VAL  4
#define D5_VAL  14

#define D_CNT   5
#define D_OFS   0

#define O1_VAL  6
#define O2_VAL  12
#define O3_VAL  15
#define O4_VAL  17

#define O_CNT   4
#define O_OFS   D_CNT

#define PIN_NUM_CNT     (D_CNT+O_CNT)
#define PIN_GRP_CNT     2

enum decode_res_e {
    DECODE_OK = 0,
    DECODE_ERR = !DECODE_OK
};

int const pin_num_tab[PIN_NUM_CNT] = {
    D1_VAL, D2_VAL, D3_VAL, D4_VAL, D5_VAL,
    O1_VAL, O2_VAL, O3_VAL, O4_VAL,
};

typedef struct { unsigned char chr, ofs, cnt; } pin_grp_t;

pin_grp_t const pin_grp_tab[2] = {
    { .chr = 'd', .ofs = D_OFS, .cnt = D_CNT },
    { .chr = 'o', .ofs = O_OFS, .cnt = O_CNT },
};

int pin_to_num(int * num, unsigned char * pin)
{
    unsigned char i = 0, tmp = pin[1] - 0x31;
    while (i < PIN_GRP_CNT) {
        if (pin_grp_tab[i].chr == pin[0]) {
            if (tmp >= pin_grp_tab[i].cnt) break;
            *num = pin_num_tab[pin_grp_tab[i].ofs + tmp];
            return DECODE_OK;
        }
        i++;
    }
    return DECODE_ERR;
}

int main(void) 
{
    int num;
    unsigned char const inp[] = "d3";
    printf("\f%s is ",inp);
    if (pin_to_num(&num,inp) == DECODE_OK) {
        printf("%d\r\n",num);
    } else {
        printf("err\r\n");
    }
    return 0;
}

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

If the array pins is ordered (otherwise you can sort it using for example qsort) then you can use the following approach as it is shown in the demonstrative program

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int cmp( const void *a, const void *b )
{
    const char *lhs = *( const char ** )a;
    const char *rhs = *( const char ** )b;

    return strcmp( lhs, rhs );
}

int main( void ) 
{
    const char *pins[]      = { "d1", "d2", "d3", "d4", "d5", "o1", "o2", "o3", "o4" };
    const int pinsNumbers[] = { 1, 2, 19, 4, 14, 6, 12, 15, 17 };

    const char *key = "d3";

    const char **p = bsearch( &key, pins, sizeof( pins ) / sizeof( *pins ), sizeof( const char * ), cmp );

    if ( p ) printf( "%d\n", pinsNumbers[p - pins] );

    return 0;
}

The program output is

19

Upvotes: 4

rocambille
rocambille

Reputation: 15996

You can structure your data like this to emulate a C++ map:

struct My_pair {
    const char* pin;
    int number;
};

const My_pair pairs[] = {
    {"d1", 1},
    {"d2", 2},
    ...
};

Upvotes: 3

Radinator
Radinator

Reputation: 1088

You can use a binary search...as long as the array above is sorted.

Upvotes: 1

Related Questions