ASCII

Characters are essentially just numerical values interpreted as characters. For instance, 'A' has the value 65, and 'B' has the value 66. This encoding can be looked up in an ASCII table. Alternatively, one can also write a program to output the numerical value!

Tasks

  • Modify the existing program as follows:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @ <stdio.hdr>
    
    fn main()
    {
        while (true) {
            local ch: int = getchar();
            printf("ch = %d\n", ch);
        }
    }
    

    Translate the program and test it. If you now input 'a', 'b', 'c', and then Return, you should get:

    1
    2
    3
    4
    5
    6
    MCL:session1 lehn$ ./a.out 
    abc
    ch = 97
    ch = 98
    ch = 99
    ch = 10
    
  • So, the ASCII value of 'a' is 97, that of 'b' is 98, that of 'c' is 99, and that of Return is 10. Determine the ASCII values of the digits '0', '1', ...,'9'.

  • It is unpleasant that our program needs to be terminated with Control-C each time. Modify the program as follows:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    @ <stdio.hdr>
    
    fn main()
    {
        while (true) {            
            local ch: int = getchar();
            if (ch == '.') {       
                break;           
            } else {
                printf("ch = %d\n", ch);
            }   
        }
    }
    

    Test it with an input that includes a '.', for example, abc.. Now the program terminates when the '.' character is read.

  • It would be even better if the program terminates when no further input from the user is expected. Change the if-condition in the program as follows:

    1
    if (ch == EOF) {
    

    Now you can terminate the program by entering Control-D. It doesn't seem better than Control-C at first, but wait.

  • EOF stands for “End Of File”. Try the following (if the file with your ABC program is not named ex1.abc, adjust accordingly):

    theon$ ./a.out < ex1.abc
    ch = 64
    ch = 32
    ch = 60
    ch = 115
    ch = 116
    ch = 100
    ch = 105
    ch = 111
    ch = 46
    ch = 104
    ch = 100
    ch = 114
    ch = 62
    ch = 10
    ch = 10
    ch = 102
    ch = 110
    ch = 32
    ch = 109
    ch = 97
    ch = 105
    ch = 110
    ch = 40
    ch = 41
    ch = 10
    ch = 123
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 119
    ch = 104
    ch = 105
    ch = 108
    ch = 101
    ch = 32
    ch = 40
    ch = 116
    ch = 114
    ch = 117
    ch = 101
    ch = 41
    ch = 32
    ch = 123
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 108
    ch = 111
    ch = 99
    ch = 97
    ch = 108
    ch = 32
    ch = 99
    ch = 104
    ch = 58
    ch = 32
    ch = 105
    ch = 110
    ch = 116
    ch = 32
    ch = 61
    ch = 32
    ch = 103
    ch = 101
    ch = 116
    ch = 99
    ch = 104
    ch = 97
    ch = 114
    ch = 40
    ch = 41
    ch = 59
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 105
    ch = 102
    ch = 32
    ch = 40
    ch = 99
    ch = 104
    ch = 32
    ch = 61
    ch = 61
    ch = 32
    ch = 39
    ch = 46
    ch = 39
    ch = 41
    ch = 32
    ch = 123
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 98
    ch = 114
    ch = 101
    ch = 97
    ch = 107
    ch = 59
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 125
    ch = 32
    ch = 101
    ch = 108
    ch = 115
    ch = 101
    ch = 32
    ch = 123
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 112
    ch = 114
    ch = 105
    ch = 110
    ch = 116
    ch = 102
    ch = 40
    ch = 34
    ch = 99
    ch = 104
    ch = 32
    ch = 61
    ch = 32
    ch = 37
    ch = 100
    ch = 92
    ch = 110
    ch = 34
    ch = 44
    ch = 32
    ch = 99
    ch = 104
    ch = 41
    ch = 59
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 125
    ch = 32
    ch = 32
    ch = 32
    ch = 10
    ch = 32
    ch = 32
    ch = 32
    ch = 32
    ch = 125
    ch = 10
    ch = 125
    ch = 10
    theon$ 

    With the < we tell the shell that a.out should get its input by reading file ex1.abc, and not by reading characters from the keyboard. So what you see is the ASCII code of the characters in file ex1.abc.

  • The compiler replaces EOF with a numerical value. The value is platform-dependent, but typically it is -1. Test whether the program behaves the same if you use -1 instead of EOF. However, then revert to using EOF instead of -1. It's more readable.

  • Change the format string and the printf statement as follows:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    @ <stdio.hdr>
    
    fn main()
    {
        while (true) {            
            local ch: int = getchar();
            if (ch == EOF) {       
                break;           
            } else {
                printf("ch = %d -> '%c'\n", ch, ch);
            }   
        }
    }
    

    Now the ASCII value (with the placeholder %d) and the corresponding character (with the placeholder %c) are output once each.

  • Modify the program as follows:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    @ <stdio.hdr>
    
    fn main()
    {
        while (true) {            
            local ch: int = getchar();
            if (ch >= '0' && ch <= '9') {
                printf("digit '%c'\n", ch);
            } else if (ch == EOF) {   
                break;           
            } else {
                printf("ch = %d -> '%c'\n", ch, ch);
            }   
        }
    }
    

    With this modification, the input digits '0' to '9' are treated specially. Test the program, for example, with an input like a1cd4. Then you should get the following output:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    MCL:session1 lehn$ ./a.out
    a1cd4
    ch = 97 -> 'a'
    digit '1'
    ch = 99 -> 'c'
    ch = 100 -> 'd'
    digit '4'
    ch = 10 -> '
    '
    
  • Now, in addition to the ASCII value of a digit, the numeric value of the digit is also output. By “numeric value of the digit”, we mean the following:

    • The character '0' has the ASCII value 48, but it should output 0.

    • The character '1' has the ASCII value 49, but it should output 1.

    • ...

    • The character '9' has the ASCII value 57, but it should output 9.

    This can be achieved by subtracting the ASCII value of '0' from each digit. Modify the line with the printf statement as follows:

    1
    printf("digit '%c', value = %d\n", ch, ch - '0');
    

    Test the program again with an input like a1cd4.