keytab problem

Discussion in 'Mac Programming' started by jamesapp, Jun 4, 2008.

  1. jamesapp macrumors 6502a

    Joined:
    Mar 7, 2008
    #1
    confused about a program from a book on c programming. Got the following error messages from the K + R book, when i tried to compile the program.

    james-collinss-macbook-pro:chap5 jamescollins$ gcc keytab.c -o keytab.out
    keytab.c:8: warning: ‘struct key’ declared inside parameter list
    keytab.c:8: warning: its scope is only this definition or declaration, which is probably not what you want
    keytab.c:15: error: ‘NKEYS’ undeclared here (not in a function)
    keytab.c:17: error: redefinition of ‘struct key’
    keytab.c: In function ‘main’:
    keytab.c:43: warning: passing argument 2 of ‘binsearch’ from incompatible pointer type
    keytab.c: At top level:
    keytab.c:54: error: conflicting types for ‘binsearch’
    keytab.c:8: error: previous declaration of ‘binsearch’ was here

    the program is supposed to count occurences of C keywords
    the book gives a list of words, and says to initialize the list as an external variable.

    here is my source file which i called keytab.c:

    Code:
    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    
    #define MAXWORD 100
    
    int geword(char *, int);
    int binsearch(char *, struct key *, int);
    
    struct key {
        char *word;
        int count;
    };
    
    struct key keytab[NKEYS];
    
    struct key {
        char *word;
        int count;
     } keytab[] = {
        "auto", 0,
        "break", 0,
        "case", 0,
        "char", 0,
        "const", 0,
        "continue", 0,
        "default", 0,
        /* ... */
        "unsigned", 0,
        "void", 0,
        "volatile", 0,
        "while", 0,
    };
    
    /* count C keywords */
    main()
    {
      int n;
      char word[MAXWORD];
      
      while (getword(word, MAXWORD) != EOF)
          if (isalpha(word[0]))
              if ((n = binsearch(word, keytab, NKEYS)) >= 0)
                  keytab[n].count++;
      for (n = 0; n < NKEYS; n++)
           if (keytab[n].count > 0)
               printf("%4d %s\n",
                    keytab[n].count, keytab[n].word);
      return 0;
    }
    
    /* binsearch: find word in tab[0]...tab[n-1] */
    int binsearch(char *word, struct key tab[], int n)
    {
      int cond;
      int low, high, mid;
      
      low = 0;
      high = n - 1;
      while (low <= high) {
          mid = (low+high) / 2;
          if ((cond = strcmp(word, tab[mid].word)) < 0)
              high = mid - 1;
          else if (cond > 0)
               low = mid + 1;
          else
               return mid;
      }
      return -1;
    }
    
    /* getword: get next word or character from input */
    int getword(char *word, int lim)
    {
      int c, getch(void);
      void ungetch(int);
      char *w = word;
      
      while (isspace(c = getch()))
          ;
      if (c != EOF)
          *w++ = c;
      if (!isalpha(c)) {
          *w = '\0';
          return c;
      }
      for ( ; --lim > 0; w++)
          if (!isalnum(*w = getch())) {
              ungetch(*w);
              break;
          }
      *w = '\0';
      return word[0];
    }
    
    /* getch and ungetch */
    #define BUFSIZE 100
    
    char buf[BUFSIZE];  /* buffer for ungetch */
    int bufp = 0;  /* next free position in buf */
    
    int getch(void)  /* get a (possibly pushed back) character */
    {
      return (bufp > 0) ? buf[--bufp] : getchar();
    }
    
    void ungetch(int c)  /* push character back on input */
    {
      if (bufp >= BUFSIZE)
          printf("ungetch: too many characters\n");
      else
          buf[bufp++] = c;
    }
    
     
  2. primes macrumors newbie

    Joined:
    Jun 4, 2008
    #2
    Many things wrong...

    Try...

    Code:
    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    
    #define MAXWORD 100
    #define NKEYS 11
    
    
    struct key {
        char *word;
        int count;
     } keytab[NKEYS] = {
        "auto", 0,
        "break", 0,
        "case", 0,
        "char", 0,
        "const", 0,
        "continue", 0,
        "default", 0,
        "unsigned", 0,
        "void", 0,
        "volatile", 0,
        "while", 0
    };
    
    int geword(char *, int);
    int binsearch(char *, struct key *, int);
    
    /* count C keywords */
    main()
    {
      int n;
      char word[MAXWORD];
      
      while (getword(word, MAXWORD) != EOF)
          if (isalpha(word[0]))
              if ((n = binsearch(word, keytab, NKEYS)) >= 0)
                  keytab[n].count++;
      for (n = 0; n < NKEYS; n++)
           if (keytab[n].count > 0)
               printf("%4d %s\n",
                    keytab[n].count, keytab[n].word);
      return 0;
    }
    
    /* binsearch: find word in tab[0]...tab[n-1] */
    int binsearch(char *word, struct key tab[], int n)
    {
      int cond;
      int low, high, mid;
      
      low = 0;
      high = n - 1;
      while (low <= high) {
          mid = (low+high) / 2;
          if ((cond = strcmp(word, tab[mid].word)) < 0)
              high = mid - 1;
          else if (cond > 0)
               low = mid + 1;
          else
               return mid;
      }
      return -1;
    }
    
    /* getword: get next word or character from input */
    int getword(char *word, int lim)
    {
      int c, getch(void);
      void ungetch(int);
      char *w = word;
      
      while (isspace(c = getch()))
          ;
      if (c != EOF)
          *w++ = c;
      if (!isalpha(c)) {
          *w = '\0';
          return c;
      }
      for ( ; --lim > 0; w++)
          if (!isalnum(*w = getch())) {
              ungetch(*w);
              break;
          }
      *w = '\0';
      return word[0];
    }
    
    /* getch and ungetch */
    #define BUFSIZE 100
    
    char buf[BUFSIZE];  /* buffer for ungetch */
    int bufp = 0;  /* next free position in buf */
    
    int getch(void)  /* get a (possibly pushed back) character */
    {
      return (bufp > 0) ? buf[--bufp] : getchar();
    }
    
    void ungetch(int c)  /* push character back on input */
    {
      if (bufp >= BUFSIZE)
          printf("ungetch: too many characters\n");
      else
          buf[bufp++] = c;
    }
    
    
    Boiled down to:

    1. Declarations out of order (or un-needed).
    2. No declaration for NKEYS (you must define it first).

    Now to complete it, you must add extra "keywords" into your table and make the NKEYS constant match the number of keywords.

    I saved this as "count.c" on my system, then started up TERMINAL in same directory (sorry, I am a UNIX person), then ran "cc count.c".

    To test, I ran "./a.out <count.c". I ran the program against itself and it seems to work except that the rest of the C-lang keywords need to be added in.
     
  3. primes macrumors newbie

    Joined:
    Jun 4, 2008
    #3
    I forgot...

    Also, you left a trailing comma in the array def and the list of keyword MUST appear in ascending, lexicographic order (!) or the binsearch may not work correctly.
     
  4. jamesapp thread starter macrumors 6502a

    Joined:
    Mar 7, 2008

Share This Page