12

Is there a quick way to retrieve given character's position in the english alphabet in C?

Something like:

int position = get_position('g');
kluka
  • 271
  • 3
  • 16
goe
  • 5,207
  • 14
  • 45
  • 49

4 Answers4

40
int position = 'g' - 'a' + 1;

In C, char values are convertible to int values and take on their ASCII values. In this case, 'a' is the same as 97 and 'g' is 103. Since the alphabet is contiguous within the ASCII character set, subtracting 'a' from your value gives its relative position. Add 1 if you consider 'a' to be the first (instead of zeroth) position.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 6
    Note that ASCII isn't part of the C standard. It's just nearly ubiquitous enough for this to work on any system you could practically find. The standard guarantees that the digits are contiguous in the character set, but not the alphabet (which will mess you up in case of EBCDIC, but seriously, who cares about EBCDIC anymore?). – Chris Lutz Oct 24 '09 at 02:06
  • 2
    My dad still uses EBCDIC in COBOL. He maintains Boeing stuff. -_- – GManNickG Oct 24 '09 at 02:37
  • 4
    So A is the -31st letter of the alphabet? –  Oct 24 '09 at 03:16
  • how to print alphabet number in reverse order like.. 1 for z, 2 for y and so on. – ShankarAnand May 09 '21 at 18:31
4

You should also probably take into account upper/lower case. In my expereince, counting from 1, is often dangerous because it can lead to off-by-one bugs. As a rule of thumb I always convert to a 1-based index only when interacting with the user, and use 0-based counting internally, to avoid confusion.

int GetPosition(char c)
{
   if (c >= 'a' && c <= 'z') {
      return c - 'a';
   }
   else if (c >= 'A' && c <= 'Z') {
      return c - 'A';
   }
   else  {
      // Indicate that it isn't a letter.
      return -1;
   }
}
cdiggins
  • 17,602
  • 7
  • 105
  • 102
  • 3
    You could simplify it by using either `tolower()` or `toupper()` in the `ctype.h` header so that you don't have to check for both lower- and uppercase. – Chris Lutz Oct 24 '09 at 02:39
  • I appreciate this answer as it takes case into consideration. As we well know, ‘A’ is very different than ‘a’ in many logical contexts. – S3DEV Feb 11 '21 at 19:13
  • If you want to assume ASCII, you can get an alphabet index with `idx = (c|0x20) - 'a';` , then check `idx <= 25U;` - see [What is the idea behind ^= 32, that converts lowercase letters to upper and vice versa?](https://stackoverflow.com/a/54585515) for how this works. Subtract then compare is how compilers will implement the double `if` conditions that form a range-check, this just folds it down to one branch. – Peter Cordes Nov 30 '22 at 21:58
4

This will work with EBCDIC and is case-insensitive:

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

int getpos (char c)
{
    int pos;
    const char * alphabet = "abcdefghijklmnopqrstuvwxyz";
    const char * found;

    c = tolower ((unsigned char)c);
    found = strchr (alphabet, c);
    pos = found - alphabet;
    if (!found)
        pos = 0;
    else if (pos == 26)
        pos = 0;
    else
        pos++;
    return pos;
}

int main ()
{
    char tests[] = {'A', '%', 'a', 'z', 'M', 0};
    char * c;
    for (c = tests; *c; c++) {
        printf ("%d\n", *c - 'a' + 1);
        printf ("%d\n", getpos (*c));
    }
    return 0;
}

See http://codepad.org/5u5uO5ZR if you want to run it.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
0

Take the input of the alphabet:

scanf("%c",ch);

Just subtract 96 from the ascii value of the character. This can be done within the printf argument:

printf("%d",ch-96);
Antoine
  • 1,393
  • 4
  • 20
  • 26