The line
if((fgets(ch,3,fp))=="the" || (fgets(ch,3,fp))=="and")
has a couple of problems:
- You can't compare string values with the
==
operator; you need to use the strcmp
library function;
- You're not comparing the same input to
"the"
and "and"
; when the first comparison fails, you're reading the next 3 characters from input;
Life will be easier if you abstract out the input and comparison operations; at a high level, it would look something like this:
#define MAX_WORD_LENGTH 10 // or however big it needs to be
...
char word[MAX_WORD_LENGTH + 1];
...
while ( getNextWord( word, sizeof word, fp )) // will loop until getNextWord
{ // returns false (error or EOF)
if ( match( word ) )
count++;
}
The getNextWord
function handles all the input; it will read characters from the input stream until it recognizes a "word" or until there's no room left in the input buffer. In this particular case, we'll assume that a "word" is simply any sequence of non-whitespace characters (meaning punctuation will be counted as part of a word). If you want to be able to recognize punctuation as well, this gets a bit harder; for example, a '
may be quoting character ('hello'), in which case it should not be part of the word, or it may be part of a contraction or a posessive (it's, Joe's), in which case it should be part of the word.
#include <ctype.h>
...
int getNextWord( char *target, size_t targetSize, FILE *fp )
{
size_t i = 0;
int c;
/**
* Read the next character from the input stream, skipping
* over any leading whitespace. We'll add each non-whitespace
* character to the target buffer until we see trailing
* whitespace or EOF.
*/
while ( (c = fgetc( fp )) != EOF && i < targetSize - 1 )
{
if ( isspace( c ) )
{
if ( i == 0 )
continue;
else
break;
}
else
{
target[i++] = c;
}
}
target[i] = 0; // add 0 terminator to string
return i > 0; // if i == 0, then we did not successfully read a word
}
The match
function simply compares the input word to a list of target words, and returns "true" (1) if it sees a match. In this case, we create a list of target words with a terminating NULL entry; we just walk down the list, comparing each element to our input. If we reach the NULL entry, we didn't find a match.
#include <string.h>
...
int match( const char *word )
{
const char *targets[] = {"and", "the", NULL};
const char *t = targets;
while ( t && strcmp( t, word ))
t++;
return t != NULL; // evaluates to true if we match either "the" or "and"
}
Note that this comparison is case-sensitive; "The" will not compare equal to "the". If you want a case-insensitive comparison, you'll have to make a copy of the input string and convert it all to lowercase, and compare that copy to the target:
#include <stdlib.h>
#Include <ctype.h>
#include <string.h>
...
int match( const char *word )
{
const char *targets[] = {"and", "the", NULL};
const char *t = targets;
char *wcopy = malloc( strlen( word ) + 1 );
if ( wcopy )
{
char *w = word;
char *c = wcopy;
while ( *w )
*c++ = tolower( *w++ );
}
else
{
fprintf( stderr, "malloc failure in match: fatal error, exiting\n" );
exit(0);
}
while ( t && strcmp( t, wcopy))
t++;
free( wcopy );
return t != NULL; // evaluates to true if we match either "the" or "and"
}