Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

jamesapp

macrumors 6502a
Original poster
Mar 7, 2008
544
0
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;
}
 
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.
 
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.