/* Copyright 2005 Daniel Cer (daniel.cer@cs.colorado.edu) This work is licensed under the Creative Commons Attribution-NonCommercial- ShareAlike License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.5/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA. */ #include #include #include #include #define INBUF_SZ 1024 char **read_entries(char *file_name, size_t *entries_N); void free_entries(char **entries, int entries_N); int cmp_entries(const void *entry_a, const void *entry_b); int main(int argc, char *argv[]) { char *term, *file_name; char **entries; size_t entries_N, entry_id; char **search_result; if (argc != 3) { fprintf(stderr, "Usage:\n\t%s (search term) (file with list of terms)\n", argv[0]); return -1; } term = argv[1]; file_name = argv[2]; /* read in the entries */ if (!(entries = read_entries(file_name, &entries_N))) { fprintf(stderr, "Can't open \"%s\": %s\n", file_name, strerror(errno)); return -1; } /* find the first match / check to see if there are any matches */ if (!(search_result = lfind(&term, entries, &entries_N, sizeof(char **), cmp_entries))) { fprintf(stderr, "Search term not found.\n"); return -2; } /* locate all of the remaining matches */ for (entry_id=0,entries_N--; search_result; search_result = lfind(&term, search_result+1, &entries_N, sizeof(char **), cmp_entries)) { entries_N+=entry_id;entry_id=search_result-entries;entries_N-=entry_id; printf("found match on line: %d\n", entry_id+1); } free(entries); return 0; } /* read_entries() - reads in a file from disk, storing each line in the * file as a separate string, and then returns an array of said strings. * It also sets the value pointed to by *entries_N to be the array's length * (/number of lines in the file). */ char **read_entries(char *file_name, size_t *entries_N){ FILE *fh; int i; char **entries; char inbuf[INBUF_SZ]; if (!(fh = fopen(file_name, "r+"))) return NULL; /* find out how many entries we have */ for (i = 0; fgets(inbuf, INBUF_SZ, fh); i++); *entries_N = i; /* alloc memory for the array of pointers to the entry strings */ if (!(entries=malloc(sizeof(char *)*(*entries_N)))){fclose(fh); return NULL;} fseek(fh, 0, SEEK_SET); /* read in the entries */ for (i = 0; fgets(inbuf, INBUF_SZ, fh); i++) { int entry_len; entry_len = strlen(inbuf); if (inbuf[entry_len-1] == '\n') { inbuf[--entry_len] = '\0'; } if (!(entries[i] = malloc(sizeof(char)*(entry_len+1)))) { free_entries(entries, i); return NULL; } strcpy(entries[i], inbuf); } fclose(fh); return entries; } /* free_entries() - release the memory allocated for an array of strings */ void free_entries(char **entries, int entries_N) { int i; for (i = 0; i < entries_N; i++) free(entries[i]); free(entries); } /* cmp_entries() - helper routine for lfind. note that strcmp * can't be used directly since we want to compare strings given * by pointers to strings (i.e. pointers to pointers to characters) * rather than just standard C strings. */ int cmp_entries(const void *entry_a, const void *entry_b) { return strcmp(*(char **)entry_a, *(char **)entry_b); }