2

I am trying to do K&R programming exercise 6.01 in C ANSI version which states

Our version of getword does not properly handle underscores, string constants, comments, or preprocessor control lines. Write a better version.

Below is the code I made to ignore comments, preprocessors and handle underscore but my word count is coming out to be incorrect if I input this same code to the binary for e.g.

gcc getword.c
./a.out<getword.c

gives me

output
   2 auto
   5 break
   1 case
   7 char
   1 const
   1 continue
   1 default
   4 do
   1 double
   4 else
   1 enum
   1 extern
   1 float
   3 for
   1 goto
  11 if
  12 int
   1 long
   1 register
   2 return
   1 short
   1 signed
   1 sizeof
   1 static
   3 struct
   1 switch
   1 typedef
   1 union
   1 unsigned
   3 void
   1 volatile
   4 while

code is as below

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAXWORD 100
#define BUFSIZE 1000

char buf[BUFSIZE];
int bufp = 0;

int getch (void) {
    return bufp > 0 ? buf[--bufp] : getchar ();
}
void ungetch (int c)
{
  if (c == EOF)
    return;
  if (bufp >= BUFSIZE)
    printf ("ungetch: too many characters\n");
  else
    buf[bufp++] = c;
}

int getword(char *,int);

 /* count C Keywords */


struct key {
        char *word;
        int count;
} keytab[] = {
    "auto" , 0,
    "break" , 0,
    "case" , 0,
    "char" , 0,
    "const" , 0,
    "continue" , 0,
    "default" , 0,
    "do" , 0,
    "double" , 0,
    "else" , 0,
    "enum" , 0,
    "extern" , 0,
    "float" , 0,
    "for" , 0,
    "goto" , 0,
    "if" , 0,
    "int" , 0,
    "long" , 0,
    "register" , 0,
    "return" , 0,
    "short" , 0,
    "signed" , 0,
    "sizeof" , 0,
    "static" , 0,
    "struct" , 0,
    "switch" , 0,
    "typedef" , 0,
    "union" , 0,
    "unsigned" , 0,
    "void" , 0,
    "volatile" , 0,
    "while" , 0,
};
int binsearch(char *,struct key *,int);
#define NKEYS (sizeof keytab / sizeof keytab[0])
int  main() {
    int n;
    char word[MAXWORD];

    while(getword(word,MAXWORD)!=EOF)
            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;
}

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;
}

int getword(char *word,int lim) {
    int c,getch(void);
    void ungetch(int);
    char *w = word;

    while(isspace(c=getch()) || c=='\t')
            ;
    if(c=='/') {
            char d=getch();
            if(d=='/') {
                    do {
                            c = getch ();
                            if (c == EOF)
                                    break;
                    }
                    while (c != '\n');
                    c=getch();
            }
            else if(d=='*') {
                    c=getch();
                    do {
                            if (c == EOF)
                                    break;
                    }
                    while (c != '*' && (c=getch())!='/');
                    c=getch();
            }
            else
                    ungetch(d);
    }
    if(c=='#')
    {
            do {
                    c = getch ();
                    if (c == EOF)
                            break;
            }
            while (c != '\n');
            c=getch();
    }
    if(c=='\n')
            c=getch();
    while(isspace(c=getch()) || c=='\t')
            ;

    if(c!=EOF)
            *w++ = c;

    if((!isalpha(c)) && ( c != '_')) {
            *w = '\0';
    return c;
}
//auto
/* auto break &$%^^$^$^$////65/456/4/64* */
    for(;--lim>0;w++)
            if(!isalnum(*w=getch()) && *w!='_' ) {
                    ungetch(*w);
                    break;
            }
            *w = '\0';
            return word[0];
}

The output is wrong for ex char comes 10 times in file but output is 7
Tried to debug but at-last came here for guidance and help

greybeard
  • 2,249
  • 8
  • 30
  • 66
D.Pinjani
  • 41
  • 1
  • 3
    I suggest you should start with formatting your code properly. – MikeCAT Aug 25 '16 at 14:05
  • There are 3 `char` missing, and there are 3 which occur right at the start of a line. But there is 1 preceded by `"`, 2 preceded by a space or tab, and 4 preceded by `(`. So I know what I would look for. – Weather Vane Aug 25 '16 at 14:06
  • ...and you can easily find out if those three are missed, by changing them to `chat` in a copy of the source file. If the count of `char` is still 7, then those are the 3 that were missed. – Weather Vane Aug 25 '16 at 14:21
  • Your program fails on the trivial input `int` (it prints nothing). Debugging is much easier if you start with small test cases that are "obviously" handled correctly. Insert tracing output of what you read into `word`, test very simple cases, and you should spot something that could be a pattern. – molbdnilo Aug 25 '16 at 14:29
  • number of `char` is 9 times. – BLUEPIXY Aug 25 '16 at 14:37
  • ...because the 10th is literal text, which is what OP was asked to solve. – Weather Vane Aug 25 '16 at 14:38
  • When compiling, always enable all the warnings, then fix those warnings. (for `gcc`, at a minimum use: `-Wall -Wextra -pedantic` I also use: `-Wconversion -std=gnu99` ) This will result in several warnings about 1) comparison between signed and unsigned values, 2) incorrect syntax for initialization of `keytab` 3) conversion between `char` and `int`, Suggest fix the warnings, then re-postt the code – user3629249 Aug 25 '16 at 16:24
  • 1
    for ease of readability and understanding: 1) separate code blocks (for, if, else, while, do...while, switch, case, default) via a blank line 2) consistently indent the code. indent after every opening brace '{', un-indent before every closing brace '}'. suggest each indent level be 4 spaces (never use tabs for indenting) as that will be wide enough to be clearly visible even with variable width fonts. 3) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* 4) place function prototypes before any function bodies, not inside some function – user3629249 Aug 25 '16 at 16:30
  • Comment and document your code, have a look at [Doxygen](http://www.doxygen.org/). Format your code for ease of reading - essential to maintaining code, if not coding. Pay close attention to what happens with the input that stopped skipping. – greybeard Aug 26 '16 at 06:21
  • (Noticed that I messed up the last two lines in my edit effort. Without knowing what `getword()` is to return, `return word[0];` just _looks_ suspicious.) – greybeard Aug 26 '16 at 07:00

0 Answers0