Thread: ASCII table border

  1. #1
    Registered User
    Join Date
    Sep 2012
    Posts
    6

    ASCII table border

    How would I go about printing an ascii table border to the screen? I have the characters using ALT-codes, but that doesnt print properly when using a printf. Do i need to individually print the ascii value for each character?

    Here's the table I'm trying to print:

    ╔═══════════════╦═══════════════╗
    ║ ║ ║
    ╟───────────────╫───────────────╢
    ║ ║ ║
    ╚═══════════════╩═══════════════╝

    Any help would be greatly appreciated.

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Maybe you can google for some code that does this print you want,because there is no standard one as far as i am concerned.
    When i want to output a table in C,
    i would play around with printf and this characters
    • -
    • |

    maybe more,depending on the occasion,just write a little code and start playing around.

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Those characters are not ASCII (despite what some other forum members might tell you ). They are present in some nonstandard extensions to ASCII, such as CP 437 as found on IBM PCs. Code page 437 - Wikipedia, the free encyclopedia

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You can use Unicode to avoid any codepage fun: Unicode Characters in the Box Drawing Block

    Code:
    #include <stdio.h>
    #include <wchar.h>
    #include <stdlib.h>
    #include <locale.h>
    
    #if (_MSC_VER >= 1500) || (__MSVCRT_VERSION__ >= 0x0800)
    #   define HAVE_O_U16TEXT
    #   include <fcntl.h>
    #   include <io.h>
    #elif defined(_WIN32)
    #   pragma message("this prob. won't work")
    #endif
    
    int main()
    {
    #if defined(HAVE_O_U16TEXT)
        // MS CRT supports UTF16 output using special mode
        int mode = _setmode(_fileno(stdout), _O_U16TEXT);
    #endif
        
        setlocale(LC_ALL, "");
    
        const wchar_t BoxBlockBegin = L'\u2550';
        const wchar_t BoxBlockEnd = L'\u2580';
    
        for (wchar_t c = BoxBlockBegin; c < BoxBlockEnd; ++c)
            wprintf(L"U+%04X = %lc\n", (unsigned)c, c);
    
    
    #if defined(HAVE_O_U16TEXT)
        // revert to original mode
        (void)_setmode(_fileno(stdout), mode);
    #endif
    
        return 0;
    }//main
    gg

  5. #5
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Codeplug's suggestion works for me (in Linux). I think I'll use those from now on!

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    You can simplify this a lot, but that's left as an exercise for the reader.

    Usually when I want a box, I use ASCII chars (and yes, ASCII is now a generic term defined to be your character set).

    It's far easier to just create the box top and lower rows, using printf():
    printf("----------\n"); kind of stuff, then just use your for loops to program the body of the box (which is easy, since it's usually empty).

    This one is bit more however:

    Code:
    #define VRT   186   // ║
    #define HRZ2  205   // ═
    #define HRZ1  196   // ─
    #define TUP   202   // ╩
    #define TDWN  209   // ╤
    #define INTR  215   // ╫
    
    #define LLCNR 200     
    #define LUCNR 201
    #define RLCNR 188
    #define RUCNR 187
    
    #define LINTR 199
    #define RINTR 182
    
    int main(void) {
       int r=0, c,width=35,height=5; 
    
       for(c=0;c<width;c++) { //upper row
          if(c==0) {
             printf("%c",LUCNR);
          }else if(c==(width/2)) {
             printf("%c",TDWN);
          }else if(c==width-1) {
             printf("%c",RUCNR);
          }else 
             printf("%c",HRZ2);
       }
       printf("\n");
       for(r=1;r<height-1;r++) {    //middle of the box
          for(c=0;c<width;c++) {
             if(r==height/2) {      //draw the middle line
                if(c==0)
                   printf("%c",LINTR);
                else if(c==width/2) 
                   printf("%c",INTR);
                else if(c==width-1 && r==height/2)
                   printf("%c",RINTR);
                else 
                   printf("%c",HRZ1);
             }else {
                if(c==0 || r==height/2 && c==width-1) {
                   printf("%c",VRT);
                }else if(r==1 && c==3 || r==1 && c==5) {
                   printf("%c",VRT);
                }else if(r==3 && c==3 || r==3 && c==5) {
                   printf("%c",VRT);
                }else if(r>0 && r<height-1) {
                   printf("%c",' ');
                }       
             }          
          }
          printf("\n");
       }
       for(c=0;c<width;c++) { //lower row
          if(c==0) {
             printf("%c",LLCNR);
          }else if(c==(width/2)) {
             printf("%c",TUP);
          }else if(c==width-1) {
             printf("%c",RLCNR);
          }else 
             printf("%c",HRZ2);
       }
       
       printf("\n");
       return 0;
    }
    The advantage to this, is you can change the dimensions of the box, and redraw the box at that new size. Usually, when I have something difficult to display I put all the chars into a char array, first. That way you don't have to worry about the cursor position while you're programming it. Then simply print out the entire array I've assembled. Saves a lot of work if it's anything difficult.
    Last edited by Adak; 11-03-2012 at 09:26 AM.

  7. #7
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Adak's suggestion doesn't work for me. His code is non-portable because it relies on a non-standard character set (CP 437), which he likes to call ASCII, that works only on DOS/Windows systems.

    No, ASCII still isn't a generic term any more than ISO-8859-1 is. It's a standard character set which defines exactly 128 characters, 94 of which are printable. Otherwise, how are people supposed to refer to the actual ASCII character set (the one defined by the standards bodies ANSI and ISO) and not to one of the many non-standard extensions like KOI8-R or CP437 if it became a generic term? "Real ASCII"? "Actual ASCII"?

  8. #8
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Quote Originally Posted by christop View Post
    Those characters are not ASCII (despite what some other forum members might tell you ).
    I thought he wanted to print out the ASCII table christop.

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    If you want to print an ASCII border then you can only reliably use the first 128 characters. The extended characters are not the same on all systems. These characters can be different even when running on two different Windows systems. It depends upon the character set being used by the system in question.

    Jim

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Any character set with the lower 7 bit values the same as the original ASCII set, can be called ASCII, (because it is). If your character set has different values in chars > 127, then you need to change some of the defines. You have an ASCII variant.

    If your lower 7 bit values don't match ASCII's values, then you have an entirely different character set, but the answer is the same, as for an ASCII variant - you need to edit the defines, with your character set's proper values.

    Um, um, what a nice box!


    ASCII table border-boxtoorder-png

    One correction to the code: TUP should be 207.
    Last edited by Adak; 11-03-2012 at 10:59 AM.

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    The ASCII character set is a 7 bit character set. The only valid values are 0 - 127 period. The "Extended" ASCII table is a non-standard extension to the 7 bit standard ASCII. These "Extended" characters are implementation defined. Windows has several different extended character sets defined, they are known as "code pages".



    Jim

  12. #12
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by Adak View Post
    Any character set with the lower 7 bit values the same as the original ASCII set, can be called ASCII, (because it is).
    Not quite. The character set would be a superset of the ASCII set, or an "ASCII extension" or "ASCII variant" (which you used correctly in this context).

    And this is what I get on my system. The character set is Unicode, and the character encoding is UTF-8:

    ASCII table border-not-ascii-png

    The question marks are printed because the bytes above 127 form invalid UTF-8 sequences when printed.
    Last edited by christop; 11-03-2012 at 11:13 AM. Reason: added screenshot

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is correct:
    Quote Originally Posted by Adak
    Any character set with the lower 7 bit values the same as the original ASCII set, can be called ASCII, (because it is).
    You don't get to change the definition of what the ASCII code is.

    You will have to change the values of the defines in the code, as previously mentioned. If you want to run the program on different systems, then you inherit the portability problems they bring with them - of course.

    And my eyes aren't the best, so keep TUP set to 202, and change TDWN to 203, in the code.

  14. #14
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by Adak View Post
    Any character set with the lower 7 bit values the same as the original ASCII set, can be called ASCII
    No, Adak. It can only be called ASCII-compatible.

    If you output data that only uses ASCII characters, that is codes 0..127, then your output is ASCII.

    If you output data that has codes > 127, it is no longer ASCII output, but something else. Your example program outputs CP437 or CP850 data.

    However, the principle behind the logic you showed is practical, if you switch from characters to strings. One can make a simple assumption that Windows users use CP437 or CP850, and everybody else has UTF-8.

    It's not perfect, but it is practical, since the other common alternatives (like windows-1252 "Western European" or ISO-8859 variants) do not have any box drawing characters anyway.

    For example, box.h:
    Code:
    #ifndef   BOX_H
    #define   BOX_H
    
    #define   CP437     437
    #define   CP850     850
    #define   UTF8      8
    
    #ifndef   CHARSET
    #ifdef    _WIN32
    #define   CHARSET   CP437
    #else
    #define   CHARSET   UTF8
    #endif
    #endif
    
    #if (CHARSET == CP437 || CHARSET == CP850)
    
    /* Windows code page 437 box drawing characters */
    #define  BOX_DLR      "\315"  /* ═ */
    #define  BOX_DUD      "\272"  /* ║ */
    #define  BOX_DUL      "\274"  /* ╝ */
    #define  BOX_DUR      "\310"  /* ╚ */
    #define  BOX_DDL      "\273"  /* ╗ */
    #define  BOX_DDR      "\311"  /* ╔ */
    #define  BOX_DUDL     "\271"  /* ╣ */
    #define  BOX_DUDR     "\314"  /* ╠ */
    #define  BOX_DULR     "\312"  /* ╩ */
    #define  BOX_DDLR     "\313"  /* ╦ */
    #define  BOX_DUDLR    "\316"  /* ╬ */
    #define  BOX_DU_SL    "\275"  /* ╜, not in CP850 */
    #define  BOX_DU_SR    "\323"  /* ╙, not in CP850 */
    #define  BOX_DD_SL    "\267"  /* ╖, not in CP850 */
    #define  BOX_DD_SR    "\326"  /* ╓, not in CP850 */
    #define  BOX_DL_SU    "\276"  /* ╛, not in CP850 */
    #define  BOX_DL_SD    "\270"  /* ╕, not in CP850 */
    #define  BOX_DR_SU    "\324"  /* ╘, not in CP850 */
    #define  BOX_DR_SD    "\325"  /* ╒, not in CP850 */
    #define  BOX_DU_SLR   "\320"  /* ╨, not in CP850 */
    #define  BOX_DD_SLR   "\322"  /* ╥, not in CP850 */
    #define  BOX_DL_SUD   "\265"  /* ╡, not in CP850 */
    #define  BOX_DR_SUD   "\306"  /* ╞, not in CP850 */
    #define  BOX_DLR_SU   "\317"  /* ╧, not in CP850 */
    #define  BOX_DLR_SD   "\321"  /* ╤, not in CP850 */
    #define  BOX_DLR_SUD  "\330"  /* ╪, not in CP850 */
    #define  BOX_DUD_SL   "\266"  /* ╢, not in CP850 */
    #define  BOX_DUD_SR   "\307"  /* ╟, not in CP850 */
    #define  BOX_DUD_SLR  "\327"  /* ╫, not in CP850 */
    #define  BOX_SLR      "\304"  /* ─ */
    #define  BOX_SUD      "\263"  /* │ */
    #define  BOX_SUL      "\331"  /* ┘ */
    #define  BOX_SUR      "\300"  /* └ */
    #define  BOX_SDL      "\277"  /* ┐ */
    #define  BOX_SDR      "\332"  /* ┌ */
    #define  BOX_SULR     "\301"  /* ┴ */
    #define  BOX_SDLR     "\302"  /* ┬ */
    #define  BOX_SUDL     "\264"  /* ┤ */
    #define  BOX_SUDR     "\303"  /* ├ */
    #define  BOX_SUDLR    "\305"  /* ┼ */
    
    #elif CHARSET == UTF8
    
    /* UTF-8 box drawing characters */
    #define  BOX_DLR      "\342\225\220"  /* ═ */
    #define  BOX_DUD      "\342\225\221"  /* ║ */
    #define  BOX_DUL      "\342\225\235"  /* ╝ */
    #define  BOX_DUR      "\342\225\232"  /* ╚ */
    #define  BOX_DDL      "\342\225\227"  /* ╗ */
    #define  BOX_DDR      "\342\225\224"  /* ╔ */
    #define  BOX_DUDL     "\342\225\243"  /* ╣ */
    #define  BOX_DUDR     "\342\225\240"  /* ╠ */
    #define  BOX_DULR     "\342\225\251"  /* ╩ */
    #define  BOX_DDLR     "\342\225\246"  /* ╦ */
    #define  BOX_DUDLR    "\342\225\254"  /* ╬ */
    #define  BOX_DU_SL    "\342\225\234"  /* ╜ */
    #define  BOX_DU_SR    "\342\225\231"  /* ╙ */
    #define  BOX_DD_SL    "\342\225\226"  /* ╖ */
    #define  BOX_DD_SR    "\342\225\223"  /* ╓ */
    #define  BOX_DL_SU    "\342\225\233"  /* ╛ */
    #define  BOX_DL_SD    "\342\225\225"  /* ╕ */
    #define  BOX_DR_SU    "\342\225\230"  /* ╘ */
    #define  BOX_DR_SD    "\342\225\222"  /* ╒ */
    #define  BOX_DU_SLR   "\342\225\250"  /* ╨ */
    #define  BOX_DD_SLR   "\342\225\245"  /* ╥ */
    #define  BOX_DL_SUD   "\342\225\241"  /* ╡ */
    #define  BOX_DR_SUD   "\342\225\236"  /* ╞ */
    #define  BOX_DLR_SU   "\342\225\247"  /* ╧ */
    #define  BOX_DLR_SD   "\342\225\244"  /* ╤ */
    #define  BOX_DLR_SUD  "\342\225\252"  /* ╪ */
    #define  BOX_DUD_SL   "\342\225\242"  /* ╢ */
    #define  BOX_DUD_SR   "\342\225\237"  /* ╟ */
    #define  BOX_DUD_SLR  "\342\225\253"  /* ╫ */
    #define  BOX_SLR      "\342\224\200"  /* ─ */
    #define  BOX_SUD      "\342\224\202"  /* │ */
    #define  BOX_SUL      "\342\224\230"  /* ┘ */
    #define  BOX_SUR      "\342\224\224"  /* └ */
    #define  BOX_SDL      "\342\224\220"  /* ┐ */
    #define  BOX_SDR      "\342\224\214"  /* ┌ */
    #define  BOX_SULR     "\342\224\264"  /* ┴ */
    #define  BOX_SDLR     "\342\224\254"  /* ┬ */
    #define  BOX_SUDL     "\342\224\244"  /* ┤ */
    #define  BOX_SUDR     "\342\224\234"  /* ├ */
    #define  BOX_SUDLR    "\342\224\274"  /* ┼ */
    
    #else
    #error : Box drawing characters are not defined for this charset.
    ""
    #endif
    
    #endif /* BOX_H */
    You'd then use it very simply:
    Code:
    #include <stdio.h>
    #include "box.h"
    
    int main(void)
    {
        fputs(BOX_DDR BOX_DLR BOX_DLR BOX_DLR BOX_DDL "\n", stdout);
        fputs(BOX_DUD "Box"                   BOX_DUD "\n", stdout);
        fputs(BOX_DUR BOX_DLR BOX_DLR BOX_DLR BOX_DUL "\n", stdout);
    
        return 0;
    }
    If you wish to override the detection, use -DCHARSET=CP437 or -DCHARSET=UTF8 when compiling.

    For a C introduction course, having that header file available would be useful -- both for better output, but also as an illustration to the preprocessor, and compile-time options. I think.

    Here is the simple Bash script I used to generate the definitions for any character set, in case you want to support some other character sets at compilation time:
    Code:
    #!/bin/bash
    
    if [ $# -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
        exec >&2
        printf '\n'
        printf 'Usage: %s [ -h | --help ]\n' "$0"
        printf '       %s CHARSET(s)...\n' "$0"
        printf '\n'
        printf 'This script will output the box drawing strings in the\n'
        printf 'specified charset(s) as preprocessor macro definitions.\n'
        printf '\n'
        exit 0
    fi
    
    while [ $# -gt 0 ]; do
        CHARSET="$1"
        shift 1
    
        printf '/* Charset %s */\n' "$CHARSET"
        while read  NAME  ORIGINAL ; do
            printf '#define  %-11s  ' "$NAME"
            STRING="$(printf '%s' "$ORIGINAL" | iconv -t "$CHARSET" 2>/dev/null | od -vt o1 | sed -e 's|^[0-9A-Fa-f]*||; /^ *$/d; s| |\\|g')" || exit $?
            if [ -n "$STRING" ]; then
                printf '"%s"\t/* %s */\n' "$STRING" "$ORIGINAL"
            else
                printf '""\t/* %s not supported in %s */\n' "$ORIGINAL" "$CHARSET"
            fi
        done << END
    BOX_DLR	    ═
    BOX_DUD	    ║
    BOX_DUL	    ╝
    BOX_DUR	    ╚
    BOX_DDL	    ╗
    BOX_DDR     ╔
    BOX_DUDL    ╣
    BOX_DUDR    ╠
    BOX_DULR    ╩
    BOX_DDLR    ╦
    BOX_DUDLR   ╬
    BOX_DU_SL   ╜
    BOX_DU_SR   ╙
    BOX_DD_SL   ╖
    BOX_DD_SR   ╓
    BOX_DL_SU   ╛
    BOX_DL_SD   ╕
    BOX_DR_SU   ╘
    BOX_DR_SD   ╒
    BOX_DU_SLR  ╨
    BOX_DD_SLR  ╥
    BOX_DL_SUD  ╡
    BOX_DR_SUD	╞
    BOX_DLR_SU	╧
    BOX_DLR_SD	╤
    BOX_DLR_SUD	╪
    BOX_DUD_SL	╢
    BOX_DUD_SR	╟
    BOX_DUD_SLR ╫
    BOX_SLR	    ─
    BOX_SUD	    │
    BOX_SUL	    ┘
    BOX_SUR	    └
    BOX_SDL	    ┐
    BOX_SDR     ┌
    BOX_SULR    ┴
    BOX_SDLR    ┬
    BOX_SUDL    ┤
    BOX_SUDR    ├
    BOX_SUDLR   ┼
    END
    
        printf '\n'
    done
    If you write a library or just utility functions to draw boxes, with a little more effort you can define static const sets of strings, and switch between them at runtime. You could even have one using just basic ASCII characters (like -, +, |, #), that'd be ugly, but still work for users that don't really have any box-drawing characters available at that moment. You could try autodetecting, but a command-line option (with a default set at compile time based on the OS) would be sufficient, in my opinion.

  15. #15
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    The Unicode character set also has the same characters as ASCII in the first 128 codes. You might say that Unicode is ASCII, but I certainly would not!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A faster ASCII table
    By cpjust in forum Tech Board
    Replies: 16
    Last Post: 03-25-2010, 02:28 PM
  2. ASCII Table
    By peckitt99 in forum C Programming
    Replies: 21
    Last Post: 10-09-2006, 01:53 AM
  3. help! extended ascii table
    By godhand in forum Linux Programming
    Replies: 7
    Last Post: 10-07-2003, 05:20 PM
  4. ASCII table going crazy?
    By Jamsan in forum Windows Programming
    Replies: 19
    Last Post: 03-27-2003, 02:33 AM
  5. need help with an ascii table =\
    By gsr squirrel in forum C++ Programming
    Replies: 9
    Last Post: 04-19-2002, 03:11 AM