История изменений
Исправление vodz, (текущая версия) :
нет разницы искать подстроку или перебирать посимвольно
Есть. Или вы парсите слова, а потом перебираете, либо вы вызываете сразу библиотечную strstr(), которая возможно написана со всякими там SIMD и сразу получите информацию, а есть хотя бы одна подстрока.
Короче, вот готовый вариант.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
typedef struct MY_GETLINE_ARGS {
char *lp;
size_t n;
const char *name;
} my_getline_args_t;
#define S(p_my_getline_args_t) ((p_my_getline_args_t)->lp)
#define U_C(s) (*((unsigned char *)(s)))
static my_getline_args_t *
my_getline(my_getline_args_t *a, FILE *in, const char *prmt)
{
char *e;
if(a == NULL)
a = calloc(1, sizeof(*a));
if(prmt != NULL)
printf ("%s: ", prmt);
errno = 0;
if(getline(&a->lp, &a->n, in) < 0) {
if(errno) {
fprintf(stderr, "%s I/O error: %s\n", a->name, strerror(errno));
exit(1);
}
if(a->name == NULL)
exit(0);
return NULL;
}
e = strchr(a->lp, '\n');
if(e != NULL)
*e = '\0';
return a;
}
int
main ()
{
int k = 0;
FILE *myfile;
my_getline_args_t *name;
my_getline_args_t *word;
my_getline_args_t line, *pline;
char *p, *buf;
size_t wl;
name = my_getline(NULL, stdin, "Enter name of file");
if ((myfile = fopen (S(name), "r")) == NULL) {
fprintf(stderr, "%s %s\n", S(name), strerror(errno));
return 1;
}
word = my_getline(NULL, stdin, "Enter word");
wl = strlen(S(word));
if(wl == 0) {
fprintf(stderr, "word must not empty\n");
return 2;
}
pline = memset(&line, 0, sizeof(line));
pline->name = S(name);
while((pline = my_getline(pline, myfile, NULL)) != NULL) {
buf = S(pline);
while((p = strstr(buf, S(word))) != NULL) {
if((p != S(pline) && isspace(U_C(p-1)) == 0)
|| (p[wl] != '\0' && isspace(U_C(p+wl)) == 0)) {
buf++;
} else {
k++;
buf = p + wl;
}
}
}
printf("%s have %d of `%s' words\n", S(name), k, S(word));
/*
Cleaning, but do not need
fclose(myfile);
free(S(name));
free(S(word));
free(S(&line));
*/
return 0;
}
Исходная версия vodz, :
нет разницы искать подстроку или перебирать посимвольно
Есть. Или вы парсите слова, а потом перебираете, либо вы вызываете сразу библиотечную strstr(), которая возможно написана со всякими там SIMD и сразу получите информацию, а есть хотя бы одна подстрока.
Короче, вот готовый вариант.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
typedef struct MY_GETLINE_ARGS {
char *lp;
size_t n;
const char *name;
} my_getline_args_t;
#define S(p_my_getline_args_t) ((p_my_getline_args_t)->lp)
#define U_C(s) (*((unsigned char *)(s)))
static my_getline_args_t *
my_getline(my_getline_args_t *a, FILE *in, const char *prmt)
{
char *e;
if(a == NULL)
a = calloc(1, sizeof(*a));
if(prmt != NULL)
printf ("%s: ", prmt);
errno = 0;
if(getline(&a->lp, &a->n, in) < 0) {
if(errno) {
fprintf(stderr, "%s I/O error: %s\n", a->name, strerror(errno));
exit(1);
}
if(a->name == NULL)
exit(0);
return NULL;
}
e = strchr(a->lp, '\n');
if(e != NULL)
*e = '\0';
return a;
}
int
main ()
{
int k = 0;
FILE *myfile;
my_getline_args_t *name;
my_getline_args_t *word;
my_getline_args_t line, *pline;
char *p, *buf;
size_t wl;
name = my_getline(NULL, stdin, "Enter name of file");
if ((myfile = fopen (S(name), "r")) == NULL) {
fprintf(stderr, "%s %s\n", S(name), strerror(errno));
return 1;
}
word = my_getline(NULL, stdin, "Enter word");
wl = strlen(S(word));
if(wl == 0) {
fprintf(stderr, "word must not empty\n");
return 2;
}
pline = memset(&line, 0, sizeof(line));
pline->name = S(name);
while(1) {
pline = my_getline(pline, myfile, NULL);
if(pline == NULL)
break;
buf = S(pline);
while((p = strstr(buf, S(word))) != NULL) {
if((p != S(pline) && isspace(U_C(p-1)) == 0)
|| (p[wl] != '\0' && isspace(U_C(p+wl)) == 0)) {
buf++;
} else {
k++;
buf = p + wl;
}
}
}
printf("%s have %d of `%s' words\n", S(name), k, S(word));
/*
Cleaning, but not need
fclose(myfile);
free(S(name));
free(S(word));
free(S(&line));
*/
return 0;
}