ThePiercingPrince
ThePiercingPrince

Reputation: 1921

How to get ASCII code of C `char` portably in ANSI C

As you all know, ANSI C does not require implementations to use ASCII code points for the char type. However it does define a basic character set with alphanumeric characters, whitespace characters and other printable characters. Are there library functions to portably convert a char to its ASCII code and back?

Upvotes: 5

Views: 1443

Answers (3)

M.M
M.M

Reputation: 141586

Here are some functions to do the job, which return 0 if the character is not found; hopefully they are self-explanatory:

char const ascii_table[] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

int char_to_ascii(int ch)
{
    char const *p = strchr(ascii_table, ch);
    return p ? p - ascii_table + 32 : 0;
}

int ascii_to_char(int a)
{
     return (a >= 32 && a < 128) ? ascii_table[a-32] : 0;
}

Expanding this to cover 0-127 instead of 32-127 is left as an exercise to the reader 😉

Upvotes: 5

S.S. Anne
S.S. Anne

Reputation: 15576

There are no ANSI C library functions that can do this.

However, I recently created an ASCII table that does exactly this. It maps most of the characters (including escape codes) available in ANSI C, and also escape ('\e', available in GNU C). The rest are mapped to zero:

unsigned int othertoascii[UINT_MAX+1] = {
  ['\a'] = 0x07, ['\b'] = 0x08, ['\t'] = 0x09,
  ['\n'] = 0x0a, ['\v'] = 0x0b, ['\f'] = 0x0c,
  ['\r'] = 0x0d, ['\e'] = 0x1b, [' ']  = 0x20,
  ['!']  = 0x21, ['"']  = 0x22, ['#']  = 0x23,
  ['$']  = 0x24, ['%']  = 0x25, ['&']  = 0x26,
  ['\''] = 0x27, ['(']  = 0x28, [')']  = 0x29,
  ['*']  = 0x2a, ['+']  = 0x2b, [',']  = 0x2c,
  ['-']  = 0x2d, ['.']  = 0x2e, ['/']  = 0x2f,
  ['0']  = 0x30, ['1']  = 0x31, ['2']  = 0x32,
  ['3']  = 0x33, ['4']  = 0x34, ['5']  = 0x35,
  ['6']  = 0x36, ['7']  = 0x37, ['8']  = 0x38,
  ['9']  = 0x39, [':']  = 0x3a, [';']  = 0x3b,
  ['<']  = 0x3c, ['=']  = 0x3d, ['>']  = 0x3e,
  ['?']  = 0x3f, ['@']  = 0x40, ['A']  = 0x41,
  ['B']  = 0x42, ['C']  = 0x43, ['D']  = 0x44,
  ['E']  = 0x45, ['F']  = 0x46, ['G']  = 0x47,
  ['H']  = 0x48, ['I']  = 0x49, ['J']  = 0x4a,
  ['K']  = 0x4b, ['L']  = 0x4c, ['M']  = 0x4d,
  ['N']  = 0x4e, ['O']  = 0x4f, ['P']  = 0x50,
  ['Q']  = 0x51, ['R']  = 0x52, ['S']  = 0x53,
  ['T']  = 0x54, ['U']  = 0x55, ['V']  = 0x56,
  ['W']  = 0x57, ['X']  = 0x58, ['Y']  = 0x59,
  ['Z']  = 0x5a, ['[']  = 0x5b, ['\\'] = 0x5c,
  [']']  = 0x5d, ['^']  = 0x5e, ['_']  = 0x5f,
  ['`']  = 0x60, ['a']  = 0x61, ['b']  = 0x62,
  ['c']  = 0x63, ['d']  = 0x64, ['e']  = 0x65,
  ['f']  = 0x66, ['g']  = 0x67, ['h']  = 0x68,
  ['i']  = 0x69, ['j']  = 0x6a, ['k']  = 0x6b,
  ['l']  = 0x6c, ['m']  = 0x6d, ['n']  = 0x6e,
  ['o']  = 0x6f, ['p']  = 0x70, ['q']  = 0x71,
  ['r']  = 0x72, ['s']  = 0x73, ['t']  = 0x74,
  ['u']  = 0x75, ['v']  = 0x76, ['w']  = 0x77,
  ['x']  = 0x78, ['y']  = 0x79, ['z']  = 0x7a,
  ['{']  = 0x7b, ['|']  = 0x7c, ['}']  = 0x7d,
  ['~']  = 0x7e
};

unsigned int asciitoother[UINT_MAX+1] = {
  [0x07] = '\a', [0x08] = '\b', [0x09] = '\t',
  [0x0a] = '\n', [0x0b] = '\v', [0x0c] = '\f',
  [0x0d] = '\r', [0x1b] = '\e', [0x20] =  ' ',
  [0x21] =  '!', [0x22] =  '"', [0x23] =  '#',
  [0x24] =  '$', [0x25] =  '%', [0x26] =  '&',
  [0x27] = '\'', [0x28] =  '(', [0x29] =  ')',
  [0x2a] =  '*', [0x2b] =  '+', [0x2c] =  ',',
  [0x2d] =  '-', [0x2e] =  '.', [0x2f] =  '/',
  [0x30] =  '0', [0x31] =  '1', [0x32] =  '2',
  [0x33] =  '3', [0x34] =  '4', [0x35] =  '5',
  [0x36] =  '6', [0x37] =  '7', [0x38] =  '8',
  [0x39] =  '9', [0x3a] =  ':', [0x3b] =  ';',
  [0x3c] =  '<', [0x3d] =  '=', [0x3e] =  '>',
  [0x3f] =  '?', [0x40] =  '@', [0x41] =  'A',
  [0x42] =  'B', [0x43] =  'C', [0x44] =  'D',
  [0x45] =  'E', [0x46] =  'F', [0x47] =  'G',
  [0x48] =  'H', [0x49] =  'I', [0x4a] =  'J',
  [0x4b] =  'K', [0x4c] =  'L', [0x4d] =  'M',
  [0x4e] =  'N', [0x4f] =  'O', [0x50] =  'P',
  [0x51] =  'Q', [0x52] =  'R', [0x53] =  'S',
  [0x54] =  'T', [0x55] =  'U', [0x56] =  'V',
  [0x57] =  'W', [0x58] =  'X', [0x59] =  'Y',
  [0x5a] =  'Z', [0x5b] =  '[', [0x5c] = '\\',
  [0x5d] =  ']', [0x5e] =  '^', [0x5f] =  '_',
  [0x60] =  '`', [0x61] =  'a', [0x62] =  'b',
  [0x63] =  'c', [0x64] =  'd', [0x65] =  'e',
  [0x66] =  'f', [0x67] =  'g', [0x68] =  'h',
  [0x69] =  'i', [0x6a] =  'j', [0x6b] =  'k',
  [0x6c] =  'l', [0x6d] =  'm', [0x6e] =  'n',
  [0x6f] =  'o', [0x70] =  'p', [0x71] =  'q',
  [0x72] =  'r', [0x73] =  's', [0x74] =  't',
  [0x75] =  'u', [0x76] =  'v', [0x77] =  'w',
  [0x78] =  'x', [0x79] =  'y', [0x7a] =  'z',
  [0x7b] =  '{', [0x7c] =  '|', [0x7d] =  '}',
  [0x7e] =  '~'
};

Here's an example program that uses this:

#include <stdio.h>

int main(void)
{
    unsigned char c = othertoascii['0'];
    c += 5;
    c = asciitoother[c];
    putchar(c);
    return 0;
}

Upvotes: 3

HolyBlackCat
HolyBlackCat

Reputation: 96276

Are there library functions to portably convert a char to its ASCII code and back?

There are no such functions in the standard library.

Hovewer, let's be realistic: It's very unlikely that your code will ever be used on a platform that doesn't use ASCII.

I would do this:

char char_to_ascii(char ch)
{
    return ch;
}

char ascii_to_char(char ch)
{
    return ch;
}

And then, if you need to compile the code for an exotic platform that doesn't use ASCII, you write proper implementations for those functions.

Upvotes: 3

Related Questions