All pastes #2027506 Raw Edit

Untitled

public c v1 · immutable
#2027506 ·published 2010-12-23 19:53 UTC
rendered paste body
#include <stdbool.h>    // C99, boolean type support#include <stdio.h>#include <stdlib.h>#include <math.h>//#define DATATYPE_IS_INT#define DATATYPE_IS_DOUBLE#define EXIT_CODE_XMALLOC       1   // if malloc() fails, program will exit!#define DEBUG_MESSAGES_ENABLED  0   // default is 0 (auto-enabled for DEBUG builds)#define NDEBUG                      // disable assertions#include <assert.h>#define WCHARBUF_LINES          20  // def: 20#define WCHARBUF_COLMS          800 // def: 80 (using a huge number, like 500, is a good idea,                                    //          in order to prevent a buffer overflow :)#define RECOMMENDED_CONS_WIDTH  150#define RECOMMENDED_CONS_WIDTHQ "150"   // use the same value, quoted/* Preprocessor directives depending on DATATYPE_IS_* : */#if defined DATATYPE_IS_INT || defined DATATYPE_IS_LONG    #define DTYPE           long int    #define DTYPE_STRING    "INTEGER"    #define DTYPE_PRINTF    "%*.*ld"    #undef DATATYPE_IS_CHAR#elif defined DATATYPE_IS_FLOAT    #define DTYPE           float    #define DTYPE_STRING    "FLOAT"    #define DTYPE_PRINTF    "%*.*f"    #undef DATATYPE_IS_CHAR#elif defined DATATYPE_IS_DOUBLE    #define DTYPE           double    #define DTYPE_STRING    "DOUBLE"    #define DTYPE_PRINTF    "%*.*lf"    #undef DATATYPE_IS_CHAR#elif defined DATATYPE_IS_CHAR    #define DTYPE           char    #define DTYPE_STRING    "CHARACTER"    #define DTYPE_PRINTF    "%*.*c" /* using the "precision" sub-specifier ( .* ) with a  */                                    /* character will produce a harmless compiler warning */    #undef  FIND_VALUE    #define FIND_VALUE 'E'      // value to use in order to test the find functions, in CHAR mode#else    #error "DATATYPE_IS_* preprocessor directive undefined!"#endiftypedef struct node_struct {    DTYPE data;    struct node_struct *left;    struct node_struct *right;    /* int height;  // useful for AVL trees */} node;typedef struct {    node *root;    bool IsAVL;     // useful for AVL trees    long size;} tree;typedef struct {    long size;    DTYPE ar[0];    // GCC extension} arraystr;static inlineDTYPE get_largest(node *n){    if (n == NULL)        return (DTYPE)0;        // ?    for(; n->right != NULL; n=n->right);    return n->data;}staticint subtreeheight(node *ST){    if (ST == NULL)        return -1;    int height_left  = subtreeheight(ST->left);    int height_right = subtreeheight(ST->right);    return (height_left > height_right) ? (height_left + 1) : (height_right + 1);}void prettyprint_tree(tree *T){    if (T == NULL)  // if T empty, abort        return;#ifndef DATATYPE_IS_CHAR /* then DTYPE is a numeric type */    /* compute spaces, find width: */    int width, i, j;    DTYPE max = get_largest(T->root);    width = (max < 10) ? 1 :            (max < 100) ? 2 :            (max < 1000) ? 3 :            (max < 10000) ? 4 :            (max < 100000) ? 5 :            (max < 1000000) ? 6 :            (max < 10000000) ? 7 :            (max < 100000000) ? 8 :            (max < 1000000000) ? 9 : 10;    assert  (max < 10000000000);    width += 2; // needed for prettier results#if defined DATATYPE_IS_FLOAT || defined DATATYPE_IS_DOUBLE    width += 2; // because of the decimals! (1 decimal is printed by default...)#endif // float or double    int spacesafter = width / 2;    int spacesbefore = spacesafter + 1;    //int spacesbefore = ceil(width / 2.0);#else /* character input */    int i, j, width = 3, spacesbefore = 2, spacesafter = 1;#endif // #ifndef DATATYPE_IS_CHAR    /* start wchar_t printing, using a 2D character array with swprintf() : */    struct columninfo{  // auxiliary structure        bool visited;        int  col;    };    wchar_t wcharbuf[WCHARBUF_LINES][WCHARBUF_COLMS];    int line=0;    struct columninfo eachline[WCHARBUF_LINES];    for (i=0; i<WCHARBUF_LINES; ++i){       // initialization        for (j=0; j<WCHARBUF_COLMS; ++j)            wcharbuf[i][j] = (wchar_t)' ';        eachline[i].visited = false;        eachline[i].col = 0;    }    int height = subtreeheight(T->root);    void recur_swprintf(node *ST, int cur_line, const wchar_t *nullstr){ // nested function,                                                                            // GCC extension!        float offset = width * pow(2, height - cur_line);        ++cur_line;        if (eachline[cur_line].visited == false) {            eachline[cur_line].col = (int) (offset / 2);            eachline[cur_line].visited = true;        }        else{            eachline[cur_line].col += (int) offset;            if (eachline[cur_line].col + width > WCHARBUF_COLMS)                swprintf(wcharbuf[cur_line], L"  BUFFER OVERFLOW DETECTED! ");        }        if (ST == NULL){            swprintf(wcharbuf[cur_line] + eachline[cur_line].col, L"%*.*s", 0, width, nullstr);            if (cur_line <= height){                /* use spaces instead of the nullstr for all the "children" of a NULL node */                recur_swprintf(NULL, cur_line, L"          ");                recur_swprintf(NULL, cur_line, L"          ");            }            else                return;        }        else{            recur_swprintf(ST->left,  cur_line, nullstr);            recur_swprintf(ST->right, cur_line, nullstr);            swprintf(wcharbuf[cur_line] + eachline[cur_line].col - 1, L"("DTYPE_PRINTF"",                     spacesbefore, 1, ST->data);          //swprintf(wcharbuf[cur_line] + eachline[cur_line].col + spacesafter + 1, L")");            swprintf(wcharbuf[cur_line] + eachline[cur_line].col + spacesafter + 2, L")");        }    }    void call_recur(tree *tr){  // nested function, GCC extension! (wraps recur_swprintf())        recur_swprintf(tr->root, -1, L"NULL");    }    call_recur(T);    /* Omit empty columns: */    int omit_cols(void){        // nested function, GCC extension!        int col;        for (col=0; col<RECOMMENDED_CONS_WIDTH; ++col)            for (line=0; line <= height+1; ++line)                if (wcharbuf[line][col] != ' ' && wcharbuf[line][col] != '\0')                    return col;        return 0;    }    /* Use fputwc to transfer the character array to the screen: */    j = omit_cols() - 2;    j = (j < 0) ? 0 : j;    for (line=0; line <= height+1; ++line){     // assumes RECOMMENDED_CONS_WIDTH console window!        fputwc('\n', stdout);                   // optional blanc line        for (i=j; i<j+RECOMMENDED_CONS_WIDTH && i<WCHARBUF_COLMS; ++i)            fputwc(wcharbuf[line][i], stdout);        fputwc('\n', stdout);    }}