user7886490
user7886490

Reputation: 305

how to shift down alphabet characters in a cyclic way?

i want to find the alphabet charachter that is 7 charachters before mine ,so i wrote this function to do so and it works fine :

char find7_before(char letter){
    switch (letter){
        case 'g':
          return 'z';
          break;
        case 'f':
          return 'y';
          break;
        case 'e':
          return 'x';
          break;
        case 'd':
          return 'w';
          break;
        case 'c':
          return 'v';
          break;
        case 'b':
          return 'u';
          break;
        case 'a':
          return 't';
          break;
        default:
        return (char)(((int)letter) - 7);
    }
}

but i think i can do it in a smarter way without all of these cases but i just can't figure it out ! (i figured how to find 7 letters after in a cyclic way ) any help or an idea or a hint ? thank you :)

Upvotes: 1

Views: 883

Answers (3)

Sam Kumar
Sam Kumar

Reputation: 508

In my opinion, the clearest and simplest way is to use an if statement:

char find7_before(char letter) {
    char value = letter - 7;
    if (value < 'a') {
        value += 26;
    }
    return value;
}

The precondition here is the letter is between 'a' and 'z', inclusive.

This technique generalizes as well:

char findn_before(char letter, int n) {
    char value = letter - n;
    if (value < 'a') {
        value += 26;
    }
    return value;
}

Precondition on letter is the same as before; n must be between 0 and 26, inclusive.

Upvotes: 1

chux
chux

Reputation: 153358

Assuming ASCII with continuous ['a' , 'z']...

Simply "mod 26".

letter = ((letter - 'a' - 7) mod 26) + 'a';

Yet C does not have a Euclidean mod operator.
See What's the difference between “mod” and “remainder”?

So create a Euclidean mod function - save for later use.

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}



letter = modulo_Euclidean(letter - 'a' - 7, 26) + 'a';

Alternately code can take advantage that 'a' has a value of 97 and not subtract so much that letter - ('a'%26) - 7 becomes negative.

letter = (letter - ('a'%26) - 7)%26 + 'a';

Pedantic code would not assume continuous ['a' , 'z'] and perform more elaborate code.

Upvotes: 1

GaryO
GaryO

Reputation: 6338

subtract 'a' (so now it's in 0-25), subtract 7, and mod 26. Then add 'a' again so it's back to a char.

Upvotes: 1

Related Questions