Sinking
Sinking

Reputation: 95

How to simplify large conditional statement

This conditional statement compares letters with numbers according to the keyboard of old button-phones.

In this statement, every if-else condition is the same. How can I shorten this piece of code?

//compares every name and pattern character
//every number represents some letters from latin alphabet
    if(lowch >= 97 && lowch <= 99 && pattern[ptrch] == '2'){
        ptrch++;
        mir++;
    }
    else if(lowch >= 100 && lowch <= 102 && pattern[ptrch] == '3'){
        ptrch++;
        mir++;
    }
    else if(lowch >= 103 && lowch <= 105 && pattern[ptrch] == '4'){
        ptrch++;
        mir++;
    }
    else if(lowch >= 106 && lowch <= 108 && pattern[ptrch] == '5'){
        ptrch++;
        mir++;
    }
    else if(lowch >= 109 && lowch <= 111 && pattern[ptrch] == '6'){
        ptrch++;
        mir++;
    }
    else if(lowch >= 112 && lowch <= 115 && pattern[ptrch] == '7'){
        ptrch++;
        mir++;
    }
    else if(lowch >= 116 && lowch <= 118 && pattern[ptrch] == '8'){
        ptrch++;
        mir++;
    }
    else if(lowch >= 119 && lowch <= 122 && pattern[ptrch] == '9'){
        ptrch++;
        mir++;
    }
    else if(lowch == '+' && pattern[ptrch] == '0'){
        ptrch++;
        mir++;
    }
    else{
        ptrch = 0;
        mir = 0;
    }
}

**ptrch- pattern char
*mir - matches in a row

Upvotes: 0

Views: 144

Answers (3)

M Oehm
M Oehm

Reputation: 29126

All your characters (except the plus sign) are lower-case letters. In ASCII, these letters are in a contiguous range. You can therefore use an array to map lower-case letters to a number code:

//                     abcdefghijklmnopqrstuvwxyz
const char code[26] = "22233344455566677778889999";

if (lowch >= 'a' && lowch <= 'z' && code[lowch - 'a'] == pattern[ptrch]) {
    ptrch++;
    mir++;
} else if (lowch == '+' && pattern[ptrch] == '0') {
    ptrch++;
    mir++;
} else{
    ptrch = 0;
    mir = 0;
}

Before accessing the array, you must check whether lowch is a valid lower-case letter. The plus sign must be treated as special case here. (But you could make the array cover the whole 7-bit ASCII range, where the characters that don't have a umber code have a special value, perhaps '\0'.)

Upvotes: 0

paddy
paddy

Reputation: 63471

A solution you might consider is to map the letters in an array.

// . . . . . . . . . . abcdefghijklmnopqrstuvwxyz
const char* numbers = "22233344455566677778889999";

char digit = (lowch >= 'a' && lowch <= 'z') ? numbers[lowch - 'a'] : 0;
if (digit == pattern[ptrch]) {
    ptrch++;
    mir++;
}
else if(lowch == '+' && pattern[ptrch] == '0') {
    ptrch++;
    mir++;
}
else {
    ptrch = mir = 0;
}

Or (slightly overkill) you could build a full table to handle any character...

// Build the table once
char dialpad[1 << CHAR_BIT] = { 0 };
const unsigned char *map_from = "abcdefghijklmnopqrstuvwxyz+";
const char          *map_to   = "222333444555666777788899990";

for (int i = 0; map_from[i]; i++) dialpad[map_from[i]] = map_to[i];

// Later on...
if (dialpad[(unsigned char)lowch] == pattern[ptrch]) {
    ptrch++;
    mir++;
}
else {
    ptrch = mir = 0;
}

Upvotes: 1

Barmar
Barmar

Reputation: 781096

Define a macro that encapsulates the comparisons, and then use a single condition with ||.

#define MATCH(start, end, ch) (lowch >= start && lowch <= end && pattern[ptrch] == ch)
if (MATCH('a', 'c', '2') || 
    MATCH('d', 'f', '3') || 
    MATCH('g', 'i', '4') || 
    MATCH('j', 'l', '5') || 
    MATCH('m', 'o', '6') ||
    MATCH('p', 's', '7') ||
    MATCH('t', 'v', '8') ||
    MATCH('w', 'z', '9') ||
    MATCH('+', '+', '0')) {
    ptrch++;
    mir++;
} else {
    ptrch = 0;
    mir = 0;
}

Another option would be to use an array of structures.

struct key {
    char start,
    char end,
    char ch
} keys[] = {
    {'a', 'c', '2'},
    {'d', 'e', '2'},
    ...
    {'+', '+', '0'}
};

bool found = false;
for (int i = 0; i < sizeof keys/sizeof keys[0]; i++) {
    if (lowch >= keys[i].start && lowch <= keys[i].end && pattern[ptrch] == keys[i].ch) {
        ptrch++;
        mir++;
        found = true;
        break;
}
if (!found) {
    ptrch = 0;
    mir = 0;
}

Upvotes: 2

Related Questions