Структури - 2
Chapter 6 - Structures
6.5 Self-referential Structures
6.6 Table Lookup
6.7 Typedef
6.8 Unions
6.9 Bit-fields

Самосвързани структури

Двоично дърво, търсещи дървета (дървета за търсене)

struct tnode {     /* the tree node: */
    char *word;    /* points to the text */
    int count;     /* number of occurrences */
    struct *tnode;  /* left child */
    struct *tnode;  /* right child */
};


Пример:
Да се преброи по колко пъти се среща дума в даден низ (текст).

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define MAXWORD 100

struct tnode *addtree(struct tnode *, char *);
void treeprint(struct tnode *);

int getword(char *, int);

/* word frequency count */
main()

{
    struct tnode *root;
    char word[MAXWORD];

    root = NULL;
    while (getword(word, MAXWORD) != EOF)
        if (isalpha(word[0]))
            root = addtree(root, word);
    treeprint(root);
    return 0;
}



struct tnode *talloc(void);
char *strdup(char *);

/* addtree: add a node with w, at or below p */
struct treenode *addtree(struct tnode *p, char *w)
{

    int cond;
    if (p == NULL) {     /* a new word has arrived */
        p = talloc();     /* make a new node */
        p->word = strdup(w);

        p->count = 1;
        p->left = p->right = NULL;
    }
    else if ((cond = strcmp(w, p->word)) == 0)

        p->count++;     /* repeated word */
    else if (cond < 0)  /* less than into left subtree */
        p->left = addtree(p->left, w);
    else                /* greater than into right subtree */
        p->right = addtree(p->right, w);

    return p;
}



/* treeprint: in-order print of tree p */
void treeprint(struct tnode *p)

{
    if (p != NULL) {
        treeprint(p->left);
        printf("%4d %s\n", p->count, p->word);
        treeprint(p->right);

    }
}



#include <stdlib.h>

/* talloc: make a tnode */
struct tnode *talloc(void)
{

    return (struct tnode *) malloc(sizeof(struct tnode));
}


char *strdup(char *s) /* make a duplicate of s */
{

    char *p;
    p = (char *) malloc(strlen(s)+1); /* +1 for '\0' */
    if (p != NULL)

        strcpy(p, s);
    return p;
}


Таблица за справки
Речник и двойки (ключ, елемент), търсене и директен достъп (индекс)
Хеширане - хеш стойност, хеш таблица

Пример:
Да се реализира таблица за замени:  идентификатор - стойност.

ebook - The C Programming Language Ritchie & kernighan -.doc struct nlist {          /* table entry */   
    struct nlist *next;
/* next entry in chain */   
    char *name;         /* defined name */
    char *defn;         /* replacement text */

#define HASHSIZE 101

static struct nlist *hashtab[HASHSIZE]; /* pointer table */
ebook - The C Programming Language Ritchie & kernighan -.doc
/* hash: form hash value for string s */
unsigned hash(char *s)

{
    unsigned hashval;
    for (hashval = 0; *s != '\0'; s++)
        hashval = *s + 31 * hashval;

    return hashval % HASHSIZE;
}



/* lookup: look for s in hashtab */
struct nlist *lookup(char *s)
{
    struct nlist *np;
    for (np = hashtab[hash(s)]; np != NULL; np = np->next)    
        if (strcmp(s, np->name) == 0)

            return np; /* found */
    return NULL; /* not found */

}


struct nlist *lookup(char *);
char *strdup(char *);

/* install: put (name, defn) in hashtab */
struct nlist *install(char *name, char *defn)
{

    struct nlist *np;
    unsigned hashval;

    if ((np = lookup(name)) == NULL) { /* not found */
        np = (struct nlist *) malloc(sizeof(*np));
        if (np == NULL || (np->name = strdup(name)) == NULL)
            return NULL;
        hashval = hash(name);
        np->next = hashtab[hashval];
        hashtab[hashval] = np;

    }
    else /* already there */

        free((void *) np->defn); /*free previous defn */
    if ((np->defn = strdup(defn)) == NULL)
        return NULL;

    return np;
}


Typedef

typedef struct tnode *Treeptr;

typedef
struct tnode {  /* the tree node: */
    char *word;         /* points to the text */
    int count;          /* number of occurrences */
    struct *tnode;      /* left child */
    struct *tnode;      /* right child */
} Treenode;



/* talloc: make a tnode */
struct tnode *talloc(void)
{

    return (struct tnode *) malloc(sizeof(struct tnode));
}


Treeptr talloc(void)
{

    return (Treeptr) malloc(sizeof(Treenode));
}



Обединения

union u_tag {
    int ival;
    float fval;
    char *sval;
} u;


if (utype == INT)
    printf("%d\n", u.ival);

if (utype == FLOAT)
    printf("%f\n", u.fval);

if (utype == STRING)
    printf("%s\n", u.sval);

else
    printf("bad type %d in utype\n", utype);


Битови полета
Флагове и битови полета

#define KEYWORD
#define EXTRENAL
#define STATIC

enum { KEYWORD = 01, EXTERNAL = 02, STATIC = 04 };

flags |= EXTERNAL | STATIC;

flags &= ~(EXTERNAL | STATIC);

if ((flags & (EXTERNAL | STATIC)) == 0) ...
ebook - The C Programming Language Ritchie & kernighan -.doc


struct {
    unsigned int is_keyword : 1;
    unsigned int is_extern : 1; u
    nsigned int is_static : 1;

} flags;

flags.is_extern = flags.is_static = 1;

flags.is_extern = flags.is_static = 0;

if (flags.is_extern == 0 && flags.is_static == 0) ...


Упражнение.
Да се дефинира структура emp, съхраняваща име на човек и заплата.
Да се дефинира масив от такива структури, да се чете таблица - име, заплата и да се изведе такава таблица с отбелязана най-висока (!) и най-ниска (?) заплата. Да се изчисли и средната заплата от въведените.

1. вариант: програма emp1.c - името в структурата е в char name[50];, таблицата се чете в масив от структури:
struct emp tab[100];

emp1.c

2. вариант: програма emp2.c - името в структурата е в char *name;, таблицата се чете в масив от структури:
struct emp tab[100];
emp2.c

3. вариант: програма emp3.c - името в структурата е в char *name;, таблицата се чете в масив от указатели към структури:
struct emp *tab[100];


4. вариант: програма emp4.c - името в структурата е в char name[50];, таблицата се чете в свързан списък, в дефиницията на структурата се добавя:
struct emp *next;

5. вариант: програма emp5.c - името в структурата е в char *name;, таблицата се чете в свързан списък, в дефиницията на структурата се добавя:
struct emp *next;
emp5.c