Ciao, l'esercitazione mi ha incuriosito cosi' ho scritto una possibile soluzione.
Contrariamente a quanto chiede il testo pero' non ho implementato 2 cose:
1. Non dico a che numero di riga/righe si incontra una parola.
2. Il mio programma e' case - sensitive (quindi "Che" e' diverso dalla parola "che").
3. La gestione delle parole non viene fatta in ordine alfabetico.
questi 3 punti sono dovuti al fatto che mi manca la voglia. Per il resto funziona come dovrebbe (o almeno spero, non ho testato piu' di tanto), quindi lo posto sperando che possa essere utile.
main.c
/**
* main.c
*
* Descrizione : Generatore Riferimenti Incrociati.
* La gestione delle parole NON viene fatta in ordine alfabetico
* quindi nemmeno il report finale lo sara'.
* Il programma e' case-sensitive.
* Data : 14/08/2010
*/
#include <stdio.h>
#include <stdlib.h>
#include "File.h"
#define PGM_NAME (0)
#define FILE_IN (1)
#define FILE_OUT (2)
/* Prototipi funzione */
static void usage (const char *);
int main(int argc, char** argv) {
FILE* fdIn;
FILE* fdOut;
if (argc != 3) {
usage(argv[PGM_NAME]);
return 0;
}
/* Apertura file di input & output */
fdIn = File_Open(argv[FILE_IN],RD);
fdOut = File_Open(argv[FILE_OUT],WR);
/* Lettura & memorizzazione in memoria del file di input */
File_Load(fdIn);
/* Chiusura file di input */
File_Close(fdIn);
/* Generazione report */
File_PrepareReport(fdOut);
File_WriteReport(fdOut);
/* Chiusura file di output */
File_Close(fdOut);
return 0;
}
static void usage(const char* pgmname) {
printf("Sintax: %s <file_in> <file_out>\n", pgmname);
}
File.h
#ifndef FILE_H_
#define FILE_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef enum { RD, WR } ModeFileOpen;
extern FILE* File_Open (const char *, int);
extern int File_Close (FILE *);
extern void File_Load (FILE *);
extern void File_PrepareReport (FILE *);
extern void File_WriteReport (FILE *);
#ifdef __cplusplus
}
#endif
#endif /* FILE_H_ */
File.c
/**
* File.c
*
* Descrizione : Gestione fisica del file di testo.
* La funzione File_Load non e' stata testata molto quindi
*+ potrebbe contenere dei bug.
* Data : 14/08/2010
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include "File.h"
#include "List.h"
char* hdrFile[] = {
"Nro",
"Parole",
"Numero di volte",
NULL
};
struct _word* words = NULL;
extern FILE* File_Open(const char* path, int mode) {
struct stat st;
FILE* fd;
char s[3];
/* Si sta' tentando di scrivere un file gia' esistente ?? */
if (mode == WR) {
if (stat(path,&st) != -1) {
printf("[+] Il file esiste gia'.\n");
exit(-1);
}
}
switch (mode) {
case RD:
strcpy(s,"r");
break;
case WR:
strcpy(s,"w");
break;
}
if (!(fd = fopen(path,s))) {
perror("fopen()");
exit(-1);
}
return fd;
}
extern int File_Close(FILE* fd) {
return fclose(fd);
}
extern void File_Load(FILE* fd) {
struct _word* e;
char buff[MAX_BUFF];
char c;
unsigned ichar;
unsigned nword;
unsigned nrow;
int posw;
ichar = nword = nrow = 0;
fseek(fd, 0L, SEEK_SET);
while ((c = fgetc(fd)) != EOF) {
if (isalpha(c)) buff[ichar++] = c;
if (c == ' ' || c == '\n') {
if (c == '\n') ++nrow;
buff[ichar++] = '\0';
ichar = 0;
if (!words) {
words = List_Alloc(++nword,nrow,buff);
}
else {
/* La parola e' gia' in memoria ?? */
if ((posw = List_wordIsPresent(words,buff)) != WORD_NOTFOUND)
List_incWordCounter(words,posw, nrow);
else {
e = List_Alloc(++nword,nrow,buff);
List_Add(words,e);
}
}
}
}
}
extern void File_PrepareReport(FILE* fd) {
unsigned short i;
for (i = 0; hdrFile[i]; ++i)
fprintf(fd,"%4s\t\t",hdrFile[i]);
fprintf(fd,"\n");
}
extern void File_WriteReport(FILE* fd) {
struct _word* fly = words;
while (fly) {
fprintf(fd,"%3d\t\t%s\t\t%5d\n",fly->n,fly->s,fly->nrep);
fly = fly->nx;
}
}
List.h
#ifndef LIST_H_
#define LIST_H_
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_BUFF (255)
#define WORD_NOTFOUND (-1)
struct _word {
unsigned n;
unsigned nrep;
char s[MAX_BUFF];
struct _word* nx;
};
extern struct _word* List_Alloc (unsigned, unsigned, const char *);
extern void List_Add (struct _word *, struct _word *);
extern int List_wordIsPresent (struct _word *, const char *);
extern void List_incWordCounter (struct _word *, unsigned, unsigned);
#ifdef __cplusplus
}
#endif
#endif /* LIST_H_ */
List.c
/**
* List.c
*
* Descrizione : Gestione file in memoria con una lista linkata aperta [ a coda ].
* Data : 14/08/2010
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "List.h"
extern struct _word* List_Alloc(unsigned nw, unsigned nr, const char* s) {
struct _word* e;
if (!(e = malloc(sizeof(struct _word)))) {
perror("malloc()");
exit(-1);
}
e->nx = NULL;
e->nrep = 1;
e->n = nw;
strcpy(e->s, s);
return e;
}
extern void List_Add(struct _word* t, struct _word* e) {
struct _word* tmp = t;
while (tmp->nx) tmp = tmp->nx;
tmp->nx = e;
}
extern int List_wordIsPresent(struct _word* list, const char *word) {
struct _word* fly;
int found;
fly = list;
found = WORD_NOTFOUND;
while (fly && found == WORD_NOTFOUND) {
if (!(strcmp(fly->s,word))) found = fly->n;
fly = fly->nx;
}
return found;
}
extern void List_incWordCounter(struct _word* list, unsigned n, unsigned r) {
struct _word* fly = list;
while (--n) fly = fly->nx;
++fly->nrep;
}
Saluti, netburst.
[EDIT]
Nel caso vi occorra il programma NON case-sensitive (quindi "Che" e' uguale alla parola "che") non dovete fare altro che apportare una piccola modifica alla funzione "List_wordIsPresent" presente nel module List.c.
La modifica da effettuare e' sostituire quella strcmp che ho utilizzato con una vostra funzione per il controllo tra le 2 stringhe, ed in quella funzione considerare i caratteri minuscoli uguali ai maiuscoli, ed il gioco e' fatto.
[/EDIT]