Chinaunix首页 | 论坛 | 博客
  • 博客访问: 209253
  • 博文数量: 136
  • 博客积分: 2919
  • 博客等级: 少校
  • 技术积分: 1299
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-11 09:08
文章分类

全部博文(136)

文章存档

2013年(1)

2011年(135)

我的朋友

分类: C/C++

2011-07-15 09:36:01

  1. /**
  2.   tpop(3): Design and Implementation
  3.   created on Jul 14, 2011
  4.   */

  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <time.h>
  9. #include "eprintf.h"

  10. enum {
  11.     NPREF = 2, /* number of prefix words */
  12.     NHASH = 4093, /* size of state hash table array */
  13.     MAXGEN = 10000 /* maxium words generated */
  14. };
  15. char NONWORD[] = "\n"; /* cannot appear as real word */

  16. typedef struct State State;
  17. typedef struct Suffix Suffix;
  18. struct State { /* prefix + suffix list */
  19.     char *pref[NPREF]; /* prefix words */
  20.     Suffix *suf; /* list of suffix */
  21.     State *next; /* next in hash table */
  22. };

  23. struct Suffix { /* list of suffixes */
  24.     char *word; /* suffix */
  25.     Suffix *next; /* next in list of suffixes */
  26. };

  27. State *statetab[NHASH]; /* hash table of states */
  28. State *lookup(char *prefix[], int create);
  29. void build(char *prefix[], FILE*);
  30. void generate(int nwords);
  31. void add(char *prefix[], char *word);
  32. void addsuffix(State *, char *);

  33. //char NONWORD[] = "\n"; /* cannot appear as real word */
  34. const int MULTIPLIER = 31; /* for hash() */


  35. /* hash: compute hash value for array of NPREF strings*/
  36. unsigned int hash(char *s[NPREF])
  37. {
  38.     unsigned int h;
  39.     unsigned char *p;
  40.     int i;

  41.     h = 0;
  42.     for (i = 0; i < NPREF; i++)
  43.       for (p = (unsigned char *)s[i]; *p != '\0'; p++)// *p not '\0'
  44.     h = MULTIPLIER * h + *p;
  45.     return h % NHASH;
  46. }



  47. /* lookup: search for prefix; create if requested.
  48. /* returns pointer if present or created; NULL if not.
  49. /* creation doesn't strdup so strings mustn't change later.*/
  50. State* lookup(char *prefix[NPREF], int create)
  51. {
  52.     int i, h;
  53.     State *sp;

  54.     h = hash(prefix);
  55.       for (sp = statetab[h]; sp != NULL; sp = sp->next) {
  56.     for (i = 0; i < NPREF; i ++)
  57.      if(strcmp(prefix[i], sp->pref[i]) != 0)
  58.      break;
  59.     if (i == NPREF) /* found it */
  60.      return sp;
  61.     }
  62.     if (create) {
  63.     sp = (State*)emalloc(sizeof(State));
  64.     for (i = 0; i < NPREF; i++)
  65.      sp->pref[i] = prefix[i];
  66.     sp->suf = NULL;
  67.     sp->next = statetab[h];
  68.     statetab[h] = sp;
  69.     printf("running lookup here?\n");
  70.     }
  71.     return sp;
  72. }

  73. /* build: read input, build prefix table */
  74. void build(char *prefix[NPREF], FILE *f)
  75. {
  76.     char buf[100], fmt[10];
  77.     //* create a format string; %s could overflow buf
  78.     sprintf(fmt, "%%%ds", sizeof(buf)-1);
  79.     while (fscanf(f, fmt, buf) != EOF)
  80.       add(prefix, estrdup(buf));
  81. }

  82. /* add: add word to suffix list, update prefix */
  83. void add(char *prefix[NPREF], char *suffix)
  84. {
  85.     State *sp;

  86.     sp = lookup(prefix, 1); /* create if not found */
  87.     addsuffix(sp, suffix);
  88.     /* move the words down the prefix */
  89.     memmove(prefix, prefix+1, (NPREF-1)*sizeof(prefix[0]));
  90.     prefix[NPREF-1] = suffix;
  91. }

  92. /* addsuffix: add to state. suffix must not change later */
  93. void addsuffix(State *sp, char *suffix)
  94. {
  95.     Suffix *suf;

  96.     suf = (Suffix *)emalloc(sizeof(Suffix));
  97.     suf->word = suffix;
  98.     suf->next = sp->suf;
  99.     sp->suf = suf;
  100. }


  101. /* generate: produce output, one word per line */
  102. void generate(int nwords)
  103. {
  104.     State *sp;
  105.     Suffix *suf;
  106.     char *prefix[NPREF], *w;
  107.     int i, nmatch;

  108.     for (i = 0; i < NPREF; i++) /* reset initial prefix */
  109.       prefix[i] = NONWORD;

  110.     for (i = 0; i < nwords; i++) {
  111.     sp = lookup(prefix, 0);
  112.     if (sp == NULL)
  113.      eprintf("internal error: lookup failed");
  114.     nmatch = 0;
  115.     for (suf = sp->suf; suf != NULL; suf = suf->next)
  116.      if (rand() % ++nmatch == 0) /* prob=1/nmatch */
  117.      w = suf->word;
  118.     if (nmatch == 0)
  119.      eprintf("internal error: no suffix %d %s", i, prefix[0]);
  120.     if (strcmp(w, NONWORD) == 0)
  121.      break;
  122.     printf("%s\n", w);
  123.     memmove(prefix, prefix+1, (NPREF-1)*sizeof(prefix[0]));
  124.     prefix[NPREF-1] = w;
  125.     }
  126. }

  127. /* markov main: markov-chain random text generation */
  128. int main(void)
  129. {
  130.     int i, nwords = MAXGEN;
  131.     char *prefix[NPREF]; /* current input prefix */
  132.     long seed;

  133. // setprogram("markov");
  134.     seed = time(NULL);
  135.     srand(seed);
  136.     for (i = 0; i < NPREF; i++) /* set up initial prefix */
  137.       prefix[i] = NONWORD;
  138.     build(prefix, stdin);
  139.   //  printf("Building is done.\n");
  140.     add(prefix, NONWORD);
  141.     generate(nwords);
  142.     return 0;
  143. }///:~

Makefile:
markov: markov.o eprintf.o
    gcc -o markov markov.o eprintf.o
eprintf.o: eprintf.c eprintf.h
    gcc -c -I -o eprintf.o eprintf.c
markov.o: markov.c
    gcc -c -o markov.o markov.c
clean:
    rm -f markov *.o
阅读(468) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~