views:

111

answers:

5

Hello, got a question regarding printing out the 128 first characters from the ascii table. I haven't gotten so far yet, because I already stumbled to a problem. The following code prints the correct value starting from 32-127. From 0 to 31 however it prints out some scrap values. I assume it is correct as well since I quick checkup on the asciitable.com those values represents something else beside the ABC...Z.

So my question is how I can print out those values as in the example output? And also I want to know how one should write a program which print out like the example output. Since the solutions I can think off would give me output e.g. 1 to 10 chars in a rows instead for in columns.

int main()
{
    int i =0;
    for(int rows = 0; rows < 16; rows++)
    {
        i = rows;
        while(i <= 127)
        {
            if(i <= 15)
                cout << hex << setw(2) << setfill('0') << i << "= " << setw(2) << setfill(' ') << toStr(i) << " | ";
            else
                cout << hex << setw(2) << setfill('0') << i << "= " << setw(2) << setfill(' ') << char(i) << " | ";
            i+=16;
        }

        cout << "\n";
    }

    return 0;
}

Example output

+--------+--------+--------+--------+--------+--------+--------+--------+
| 00     | 10     | 20 ' ' | 30 '0' | 40 '@' | 50 'P' | 60 '`' | 70 'p' |
| 01     | 11     | 21 '!' | 31 '1' | 41 'A' | 51 'Q' | 61 'a' | 71 'q' |
| 02     | 12     | 22 '"' | 32 '2' | 42 'B' | 52 'R' | 62 'b' | 72 'r' |
| 03     | 13     | 23 '#' | 33 '3' | 43 'C' | 53 'S' | 63 'c' | 73 's' |
| 04     | 14     | 24 '$' | 34 '4' | 44 'D' | 54 'T' | 64 'd' | 74 't' |
| 05     | 15     | 25 '%' | 35 '5' | 45 'E' | 55 'U' | 65 'e' | 75 'u' |
| 06     | 16     | 26 '&' | 36 '6' | 46 'F' | 56 'V' | 66 'f' | 76 'v' |
| 07'\a' | 17     | 27 ''' | 37 '7' | 47 'G' | 57 'W' | 67 'g' | 77 'w' |
| 08'\b' | 18     | 28 '(' | 38 '8' | 48 'H' | 58 'X' | 68 'h' | 78 'x' |
| 09'\t' | 19     | 29 ')' | 39 '9' | 49 'I' | 59 'Y' | 69 'i' | 79 'y' |
| 0a'\n' | 1a     | 2a '*' | 3a ':' | 4a 'J' | 5a 'Z' | 6a 'j' | 7a 'z' |
| 0b'\v' | 1b     | 2b '+' | 3b ';' | 4b 'K' | 5b '[' | 6b 'k' | 7b '{' |
| 0c'\f' | 1c     | 2c ',' | 3c '<' | 4c 'L' | 5c'\\' | 6c 'l' | 7c '|' |
| 0d'\r' | 1d     | 2d '-' | 3d '=' | 4d 'M' | 5d ']' | 6d 'm' | 7d '}' |
| 0e     | 1e     | 2e '.' | 3e '>' | 4e 'N' | 5e '^' | 6e 'n' | 7e '~' |
| 0f     | 1f     | 2f '/' | 3f '?' | 4f 'O' | 5f '_' | 6f 'o' | 7f     |
+--------+--------+--------+--------+--------+--------+--------+--------+

EDIT I got a quite ok solution now I think, edited the code. Beside understanding how to print in columns I also used the function which Martin nicely provided.

A: 

Check the gnu ascii program. It does something similar.

Daren Thomas
care to share the link? or is it this one http://www.gnu.org/graphics/gnu-ascii.html
starcorn
I'm afraid I couldn't find it either... must be hidden somewhere.
Daren Thomas
+1  A: 

Those characters don't have an ASCII-standardised graphical representation, though some fonts / character-sets do provide one. On old DOS systems (and my even-older Zilog Z-80 based one), for example, you could "poke" the values into video memory to see the associated characters. Similarly, 128-256 had extra graphics used to draw lines, boxes, do shading etc. But, only those you've been able to print are really meaningful as ASCII characters. If you really want to display more, then you have to make your program highly coupled to the display system that it's interacting with - finding some special escape sequences that it supports for displaying non-standard characters, writing via a graphics API, or go back to the "poke into memory" approach of yester-year....

For breaking the output into columns, you can add an extra statement in your loop to see if (i % num_columns == 0), then write a newline character '\0'. If you want columns to jump in value, use i += 16 instead of i++, then put "if (i > 0x70) { i -= 0x6F; std::cout << '\n'; }" to move to the start of the new row.

Tony
A: 

Some characters are not meant to be displayed ; for instance, the 7th, if I remember correctly is the "ring bell", that makes a beeping sound (because of typewriters, you know, when you've finished your line, it beeps).

Best portable way I know is to put a condition and not print between 0 and 31, or stock in a table the classical names of those caracters (BR, LF, etc., you can find them easily on the web) and display those instead of trying to display the character itself, since those are by definition non-displayable.

Raveline
+1  A: 

The characters before 32 are control characters. For example, ascii 7 is the "bell" character, 13 is linefeed and so on. So you have to find out how to print them.

As for printing by column instead of rows, here's a hint: note that the first row contains ascii chars 0, 10, 20, ... 70; the second has 1, 11,...71. You should be able to figure out the pattern and note that you need two loops (an outer and inner) where the inner loop prints the chars that belong on the row given by outer loop.

Hemal Pandya
I don't get how one can jump back to the start after printing out the first column. Or am I supposed to print everything in rows, e.g. on the first run I print out 00,10,20...70? I've updated my code.
starcorn
nvm I got the idea now
starcorn
There is a reason I didn't elaborate, I guess you figured that :)
Hemal Pandya
+2  A: 

If the character is smaller than 32 it is a special character and thus may not have a vueable glyph. So if the character is below 32 you should take this into account and put an appropriate character string in its place.

#include <iostream>

// An array of strings for all the special characters.
char const* data[] = {"", "", "", "", "", "", "", ""
                      "\\a","\\b","\\t","\\n","\\v","\\f","\\r"
                      // etc
                     };

char const* toStr(int loop)
{
    // Used by normal character.
    // Note buffer[0] is where we put the char. buffer[1] is always '\0'
    static char buffer[] = " ";

    if (loop < 32)
    {
        return data[loop];
    }
    else
    {
        buffer[0] = loop;
        return buffer;
    }
}

int main()
{
    for(int loop =0;loop < 128;++loop)
    {
        std::cout << loop << "=" << toStr(loop) << "\n";
    }
}
Martin York
I think you mean 'non printable' characters.
Chubsdad