You have to be very careful on memory allocation/deallocation. I think it is better to implement a set of
String
handling functions and a simple state machine to parse the input line.
Please note: never use the
gets
function.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
typedef struct
{
char * s;
int len;
} String;
void initstring( String * ps)
{
if ( ! ps ) return;
ps->s = (char * ) 0;
}
void fillstring( String * ps, const char * beg, const char * end)
{
if ( ! ps ) return;
ps->len = end - beg;
if ( ps->len < 1) return;
ps->s = (char *) malloc( ps->len);
if ( ! ps->s ) return;
memcpy(ps->s, beg, ps->len);
}
void printstring(const String * ps)
{
int i;
if ( ! ps || ! ps->s) return;
for ( i = 0; i< ps->len; ++i)
{
putchar(ps->s[i]);
}
}
void emptystring( String * ps)
{
if ( ! ps || ! ps->s ) return;
free( ps->s );
ps->s = (char* ) 0;
}
enum {
NOT_BLANK = 0,
BLANK,
MATCH
};
const char * nextword( const char * start, char letter, String * ps)
{
const char *p = start;
const char *beg = (const char *) 0;
const char *end = (const char *) 0;
int state = BLANK;
while (*p != '\0' && ! end)
{
switch ( state )
{
case BLANK:
if ( *p != ' ')
{
if ( toupper(*p) == toupper(letter))
{
state = MATCH;
beg = p;
}
else
{
state = NOT_BLANK;
}
}
break;
case NOT_BLANK:
if ( *p == ' ')
{
state = BLANK;
}
break;
case MATCH:
if ( *p == ' ')
{
end = p;
}
break;
}
++p;
}
if ( state == MATCH )
{
if ( *p == '\0' ) end = p;
if ( ps ) fillstring(ps, beg, end);
}
return end;
}
enum
{
BUFSIZE = 512,
};
int main()
{
char line[BUFSIZE];
char letter;
const char *p;
int count = 0;
printf("please enter a line a text:\n");
if ( ! fgets(line, BUFSIZE, stdin) ) return -1;
size_t len = strlen(line);
if ( len > 0 && line[len-1] == '\n' )
line[len-1] = '\0';
printf("please insert a letter:\n");
if ( scanf("%c", & letter) != 1)
return -1;
p = line;
while ( 1 )
{
p = nextword( p, letter, (String * )0);
if ( ! p ) break;
++count;
}
printf("there are %d matches.\n", count);
if ( count > 0)
{
int i;
String * as = (String *) malloc ( count * sizeof ( String ));
if ( ! as ) return -1;
p = line;
for ( i = 0; i < count; ++i)
p = nextword( p, letter, &(as[i]));
for ( i = 0; i< count; ++i)
{
printstring(&as[i]);
printf("\n");
}
for ( i = 0; i < count; ++i)
emptystring( &(as[i]));
free(as);
}
return 0;
}