Problema di Comunicazione tra Processi Concorrenti tramite Pipe in C

di il
0 risposte

Problema di Comunicazione tra Processi Concorrenti tramite Pipe in C

Il programma utilizza le pipe per gestire diversi processi concorrenti. Quando il programma deve scrivere sulla pipe2 per poi condividerla col processo concorrente stampa, smette di funzionare correttamente perché quando leggo la pipe2 su stampa non legge niente. La ragione esatta di questa interruzione non è chiara, e sono necessari ulteriori debug per identificare la causa di questo problema.

Attraverso alcuni debug con varie print inserite qua e là, ho potuto circoscrivere che il problema risiede nella funzione stampa o alla fine della funzione creaTabella quando scrive sulla pipe2[1] in modalità scrittura.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>

// Definizione della struttura per un oggetto contenente una stringa, la sua frequenza, e le coordinate nella matrice
typedef struct {
    wchar_t Stringa[31];
    float frequenza;
    int occorrenza;
    int x;
    int y;
} oggetto;

// Definizione della struttura per una matrice contenente una lista di oggetti e le sue dimensioni
typedef struct {
    oggetto** lista;
    int x;
    int y;
} matrice;

// Definizione della struttura per l'alfabeto contenente un sottoalfabeto e una parola
struct Alfabeto {
    struct Alfabeto* sottoalfabeto[46];
    oggetto *parola;
};

// Definizione del tipo Dizionario come un puntatore a struct Alfabeto
typedef struct Alfabeto Dizionario;

// Dichiarazione della funzione ricorsivaDeallocazione
Dizionario* deallocazione(Dizionario* diz);
int creaTabella(FILE* file, int indice, matrice* matrix, Dizionario* diz, int pipe1[], int pipe2[], wchar_t primaParola[]);
int indiceAscii(wchar_t carattere);
bool confrontaStringhe(wchar_t* stringa1, wchar_t* stringa2);
bool ricercaOperativa(wchar_t stringa[], int indice, Dizionario* diz, int i, int p, matrice* m);
void leggiParolaFileInput(FILE* file, int pipe1[], long int posizione);
void stampa(FILE* foglio, int pipe2[], int MAX);
long int primaParola(FILE* file, matrice* matrix);

int main() { // dichiaro la funzione main

    setlocale(LC_ALL, "it_IT.UTF-8"); // Imposta una locale che supporta Unicode

    FILE* file = fopen("prova.txt", "r");
    FILE* foglio = fopen("controprova.csv", "w");
    if (file == NULL || foglio == NULL) { // se uno dei file non si apre
        exit(EXIT_FAILURE); // esco con errore
    }

    Dizionario* dizionario = (Dizionario*)calloc(1, sizeof(Dizionario)); // alloco il dizionario
    dizionario->parola = (oggetto*)calloc(1, sizeof(oggetto)); // alloco una parola nel dizionario

    matrice matrix; // dichiaro una matrice

    matrix.lista = (oggetto**)calloc(1, sizeof(oggetto*));
    matrix.lista[0] = (oggetto*)calloc(2, sizeof(oggetto));

    long int posizione = primaParola(file, &matrix);
    if (posizione == -1) {
        exit(EXIT_FAILURE); // esco con errore
    }

    int pipe1[2], pipe2[2]; // dichiaro due pipe

    if (pipe(pipe1) == -1 || pipe(pipe2) == -1) { // se la creazione delle pipe fallisce
        exit(EXIT_FAILURE); // esco con errore
    }
    int MAX; // massimo numero di bytes da allocare in una riga nella matrice
    pid_t pid_Processo1, pid_Processo2, pid_Processo3; // dichiaro i pid dei processi

    pid_Processo1 = fork(); // creo il primo processo
    if (pid_Processo1 == -1) { // se la fork fallisce
        perror("Fork errore"); // stampo un errore
        return 1; // ritorno 1
    } else if (pid_Processo1 == 0) { // se sono nel processo figlio
        close(pipe1[0]); // chiudo la lettura della pipe1
        leggiParolaFileInput(file, pipe1, posizione); // chiamo la funzione leggiParolaFileInput
        exit(0); // esce dal processo
    } else { // se sono nel processo padre
        close(pipe1[1]); // chiudo la scrittura della pipe1
        waitpid(pid_Processo1, NULL, 0); // attendo la terminazione del processo 1
    }

    pid_Processo2 = fork(); // creo il secondo processo
    if (pid_Processo2 == -1) { // se la fork fallisce
        perror("Fork errore"); // stampo un errore
        return 1; // ritorno 1
    } else if (pid_Processo2 == 0) { // se sono nel processo figlio
        close(pipe2[0]); // chiudo la lettura della pipe2
        wchar_t primaParolaArray[31]; // Assicurati che la dimensione sia sufficiente
        wcscpy(primaParolaArray, matrix.lista[0][0].Stringa);
        MAX = creaTabella(file, 0, &matrix, dizionario, pipe1, pipe2, primaParolaArray); // chiamo la funzione creaTabella che ritorna numero massimo di bytes delle righe della matrice
        exit(0); // esce dal processo
    } else { // se sono nel processo padre
        close(pipe1[0]); // chiudo la lettura della pipe1
        close(pipe2[1]); // chiudo la scrittura della pipe2
        waitpid(pid_Processo2, NULL, 0); // attendo la terminazione del processo 2
    }

    pid_Processo3 = fork(); // creo il terzo processo
    if (pid_Processo3 == -1) { // se la fork fallisce
        perror("Fork errore"); // stampo un errore
        return 1; // ritorno 1
    } else if (pid_Processo3 == 0) { // se sono nel processo figlio
        close(pipe2[1]); // chiudo la scrittura della pipe2
        stampa(foglio, pipe2, MAX); // chiamo la funzione stampa
        close(pipe2[0]); // chiudo la lettura della pipe2
        exit(0); // esce dal processo
    }
    waitpid(pid_Processo3, NULL, 0); // attendo la terminazione del processo 3

    wait(NULL); // attendo la terminazione di tutti i processi figli
    wait(NULL); // attendo la terminazione di tutti i processi figli
    wait(NULL); // attendo la terminazione di tutti i processi figli

    fclose(foglio); // chiudo il file di output
    fclose(file); // chiudo il file di input

    for (int i = 0; i < 46; i++) { // libero la memoria del dizionario
        dizionario->sottoalfabeto[i] = deallocazione(dizionario->sottoalfabeto[i]); // chiamo la funzione deallocazione
    }
    free(dizionario->parola); // libero la memoria della parola
    free(dizionario); // libero la memoria del dizionario

    return 0; // ritorno 0
}

Dizionario* deallocazione(Dizionario* diz) { // dichiaro la funzione deallocazione
    if (diz == NULL) { // se il dizionario è NULL
        return NULL; // ritorno NULL
    }

    for (int i = 0; i < 46; i++) { // scorro i 46 elementi del sottoalfabeto
        diz->sottoalfabeto[i] = deallocazione(diz->sottoalfabeto[i]); // chiamo la funzione deallocazione ricorsivamente
    }
    free(diz->parola); // libero la memoria della parola
    free(diz); // libero la memoria del dizionario
    return NULL;
}

// Funzione per ottenere l'indice ASCII di un carattere
int indiceAscii(wchar_t carattere) {
    // Converti il carattere in minuscolo
    wchar_t c = towlower(carattere);

    if (iswalpha(c)) {
        // Gestione delle lettere non accentate
        return c - L'a';
    } else {
        // Gestione dei caratteri accentati
        switch (c) {
            case L'à': return 26;
            case L'è': return 27;
            case L'é': return 28;
            case L'ì': return 29;
            case L'ò': return 30;
            case L'ù': return 31;
            case L'!': return 32;
            case L'?': return 33;
            case L'.': return 34;
            case L'\'': return 35;
        }
    }

    // Gestione dei numeri
    if (c >= L'0' && c <= L'9') {
        return 36 + (c - L'0');
    }

    // Carattere non riconosciuto
    return -1;
}

// Funzione per confrontare due stringhe
bool confrontaStringhe(wchar_t* Stringa1, wchar_t* Stringa2) { // dichiaro la funzione confrontaStringhe
    if (*Stringa1 == L'\0' && *Stringa2 == L'\0') { // se entrambe le stringhe sono terminate
        return true; // ritorno true
    }
    
    if (*Stringa1 == *Stringa2 || (towlower((wchar_t)*Stringa1) == towlower((wchar_t)*Stringa2))) { // controlla se i caratteri sono uguali o se sono uguali in minuscolo
        return confrontaStringhe(Stringa1 + 1, Stringa2 + 1); // richiamo la funzione sul prossimo carattere
    }

    return false; // se i caratteri non sono uguali, ritorno false
}

// Funzione per trovare la prima parola nel file
long int primaParola(FILE* file, matrice* matrix) {
    char carattere;
    const wchar_t* caratteriAccentati = L"àèéìòóùÀÈÉÌÒÓÙ";
    int indice = 0; // inizializzo l'indice a 0
    long int pos = 0; // Inizializza pos a 0

    while ((carattere = fgetwc(file)) != WEOF) {
        wchar_t successivo = fgetwc(file);
        fseek(file, -1, SEEK_CUR);
        if (carattere == L'\n' || carattere == L' ') { // se i primi caratteri sono \n o spazio saltali
            continue;
        } else if (iswalnum(carattere) || (wcschr(caratteriAccentati, carattere) != NULL)) { // se trovi o quando troverai dei caratteri alfanumerici allora aggiungi alla matrice in prima posizione
            matrix->lista[0][0].Stringa[indice] = carattere;
            indice++;
            if (successivo == L' ' || successivo == L'\n' || successivo == L'!' || successivo == L'?' || successivo == L'.') { // se seguito da spazio o da a capo termina la Stringa 
                matrix->lista[0][0].Stringa[indice] = L'\0';
                return ftell(file);
            } else if (successivo == L'\'') { // se seguito da apostrofo appendi l'apostrofo e termina la Stringa e la primaparola
                matrix->lista[0][0].Stringa[indice] = L'\'';
                matrix->lista[0][0].Stringa[indice + 1] = L'\0';
                return ftell(file);
            }
            continue;
        } else if (carattere == L'!' || carattere == L'?' || carattere == L'.') { // se incontri dei caratteri speciali aggiungili alla matrice come dei caratteri a se
            matrix->lista[0][0].Stringa[indice] = carattere;
            matrix->lista[0][0].Stringa[indice + 1] = L'\0';
            return ftell(file);
        }
    }
    
    // Se arriviamo qui, significa che abbiamo raggiunto la fine del file senza trovare una parola valida
    return -1; // Ritorniamo -1 per indicare che non è stata trovata una parola valida
}

// Funzione per la ricerca operativa di una stringa nella matrice
bool ricercaOperativa(wchar_t stringa[], int indice, Dizionario* diz, int i, int p, matrice* m) { // dichiaro la funzione ricercaOperativa
    Dizionario* dizAttuale = diz; // inizializzo dizAttuale con diz
    int ASCII; // dichiaro la variabile ASCII

    if (stringa[indice] == '\0') { // se il carattere corrente è il terminatore di stringa
        if (confrontaStringhe(dizAttuale->parola->Stringa, m->lista[i][0].Stringa)) { // se la stringa della parola del dizionario è uguale alla stringa della matrice
            int n = 1; // inizializzo n a 1
            int y = dizAttuale->parola->y; // assegno la coordinata y della parola del dizionario a y
            int x = dizAttuale->parola->x; // assegno la coordinata x della parola del dizionario a x
            int trovato = 0; // inizializzo trovato a 0

            m->lista[y][0].occorrenza++; // incremento l'occorrenza della parola nella matrice
            while (n <= m->x && m->lista[y][n].x == n) { // finché n è minore o uguale alla dimensione x della matrice e l'elemento della matrice è uguale a n
                if (confrontaStringhe(m->lista[y][n].Stringa, m->lista[i][p].Stringa)) { // se la stringa corrente è uguale alla stringa della matrice
                    m->lista[y][n].occorrenza++; // incremento l'occorrenza
                    m->lista[y][n].frequenza = (float)m->lista[y][n].occorrenza / (float)m->lista[y][0].occorrenza; // calcolo la frequenza
                    trovato = 1; // imposto trovato a 1
                }
                m->lista[y][n].frequenza = (float)m->lista[y][n].occorrenza / (float)m->lista[y][0].occorrenza; // calcolo la frequenza
                n++; // incremento n
            }

            if (!trovato) { // se non ho trovato la stringa
                if (n > m->x) { // se n è maggiore della dimensione x della matrice
                    m->x = n; // assegno n a x
                }
                m->lista[y] = realloc(m->lista[y], (n + 1) * sizeof(oggetto)); // rialloco la memoria per la riga della matrice
                wcscpy(m->lista[y][n].Stringa, m->lista[i][p].Stringa); // copio la stringa nella matrice
                m->lista[y][n].occorrenza = 1; // inizializzo l'occorrenza a 1
                m->lista[y][n].frequenza = (float)m->lista[y][n].occorrenza / (float)m->lista[y][0].occorrenza; // calcolo la frequenza
                m->lista[y][n].x = n; // assegno n alla coordinata x
            }

            return true; // ritorno true
        }

        wcscpy(dizAttuale->parola->Stringa, stringa); // copio la stringa nella parola del dizionario
        dizAttuale->parola->x = p; // assegno p alla coordinata x della parola
        dizAttuale->parola->y = i; // assegno i alla coordinata y della parola
        m->lista[i][1].x = 1; // assegno 1 alla coordinata x della matrice
        m->lista[i][0].x = 0; // assegno 0 alla coordinata x della matrice
        m->lista[i][1].occorrenza = 1; // inizializzo l'occorrenza a 1
        m->lista[i][0].occorrenza = 1; // inizializzo l'occorrenza a 1
        m->lista[i][1].frequenza = (float)m->lista[i][1].occorrenza / (float)m->lista[i][0].occorrenza; // calcolo la frequenza

        return false; // ritorno false
    }

    ASCII = indiceAscii(stringa[indice]); // calcolo l'indice ASCII del carattere corrente
    if (dizAttuale->sottoalfabeto[ASCII] == NULL) { // se il sottoalfabeto corrente è NULL
        dizAttuale->sottoalfabeto[ASCII] = (Dizionario*)calloc(1, sizeof(Dizionario)); // alloco memoria per il sottoalfabeto
        if (dizAttuale->sottoalfabeto[ASCII] == NULL) { // se la memoria non è stata allocata
            exit(1); // esco con errore
        }
        dizAttuale->sottoalfabeto[ASCII]->parola = (oggetto*)calloc(1, sizeof(oggetto)); // alloco memoria per la parola del sottoalfabeto
        if (dizAttuale->sottoalfabeto[ASCII]->parola == NULL) { // se la memoria non è stata allocata
            exit(1); // esco con errore
        }
    }
    dizAttuale = dizAttuale->sottoalfabeto[ASCII]; // assegno il sottoalfabeto corrente a dizAttuale
    return ricercaOperativa(stringa, indice + 1, dizAttuale, i, p, m); // richiamo la funzione ricorsivamente
}

// Funzione per gestire la fine di una stringa
int creaTabella(FILE* file, int indice, matrice* matrix, Dizionario* diz, int pipe1[], int pipe2[], wchar_t primaParola[]) { // dichiaro la funzione creaTabella
    wchar_t stringa1[31]; // dichiaro una stringa di 31 caratteri
    matrix->x = 1; // inizializzo la dimensione x a 1
    matrix->y = 1; // inizializzo la dimensione y a 1
    matrix->lista = NULL; // inizializzo la lista a NULL

    matrix->lista = (oggetto**)calloc(1, matrix->y * sizeof(oggetto*)); // alloco memoria per la matrice
    matrix->lista[matrix->y - 1] = (oggetto*)calloc(1, 2 * sizeof(oggetto)); // alloco memoria per una riga della matrice

    wcscpy(matrix->lista[0][0].Stringa, primaParola); // copio la prima parola nella matrice

    // Legge tutte le parole dalla pipe1 prima di scrivere sulla pipe2
    while (read(pipe1[0], &stringa1, sizeof(stringa1)) > 0) { // legge tutte le parole dalla pipe1
        if (stringa1[0] == '\0') { // se la stringa è vuota
            break; // esce dal ciclo
        }

        // Aggiunge le parole come valore alla struttura dati Matrice
        wcscpy(matrix->lista[matrix->y - 1][1].Stringa, stringa1); // copio la stringa nella matrice
        matrix->lista[matrix->y - 1][1].x = 1; // assegno 1 alla coordinata x
        matrix->lista[matrix->y - 1][0].x = 0; // assegno 0 alla coordinata x

        int controllo = ricercaOperativa(matrix->lista[matrix->y - 1][0].Stringa, 0, diz, matrix->y - 1, 1, matrix); // chiamo la funzione ricercaOperativa
        if (controllo == 0) { // se il controllo è 0
            matrix->y++; // incremento la dimensione y
            matrix->lista = realloc(matrix->lista, matrix->y * sizeof(oggetto*)); // rialloco la memoria per la matrice
            matrix->lista[matrix->y - 1] = (oggetto*)calloc(1, 2 * sizeof(oggetto)); // alloco memoria per una nuova riga
        }

        wcscpy(matrix->lista[matrix->y - 1][0].Stringa, stringa1); // copio la stringa nella matrice
        stringa1[0] = '\0'; // resetto la stringa
    }

    // Gestisci la fine
    wcscpy(matrix->lista[matrix->y - 1][1].Stringa, matrix->lista[0][0].Stringa); // copio la prima parola nell'ultima riga
    int controllo = ricercaOperativa(matrix->lista[matrix->y - 1][0].Stringa, 0, diz, matrix->y - 1, 1, matrix); // chiamo la funzione ricercaOperativa
    if (controllo == 0) { // se il controllo è 0
        matrix->y++; // incremento la dimensione y
    }
    close(pipe1[0]); // chiudo la pipe1

    int dimRiga = 31; // dimensione minima di ogni riga
    int dimMAX = 31; // dimensione massima che può assumere una riga della matrice

    // Scrive le righe della matrice nella pipe2
    for (int i = 0; i < matrix->y - 1; i++) { // scrivo le righe della matrice nella pipe2
        wchar_t* riga = calloc(1, dimRiga * sizeof(wchar_t)); // Buffer per memorizzare la rappresentazione in stringa della riga allocato dinamicamente
        int occorrenze = 0; // contatore occorrenze
 
        swprintf(riga, dimRiga, L"%ls", matrix->lista[i][0].Stringa);

        for (int j = 1; j < matrix->x + 1; j++) { // itero sulle colonne
            if (occorrenze == matrix->lista[i][0].occorrenza) { // se le occorrenze sono uguali
                break; // esce dal ciclo
            }
            occorrenze = occorrenze + matrix->lista[i][j].occorrenza; // incremento le occorrenze
            int incremento = wcslen(matrix->lista[i][j].Stringa) + 6; // calcolo l'incremento di bytes che ogni volta bisogna aggiungere
            dimRiga += incremento; // sommo alla dimensione di quella riga
            if (dimRiga > dimMAX) { // verifico se quella corrisponde alla dimensione massima della riga più lunga della matrice
                dimMAX = dimRiga; // se si associo quel valore
            }
            riga = realloc(riga, dimRiga * sizeof(wchar_t)); // estendo sempre il buffer riga reallocandolo
            swprintf(riga + wcslen(riga), dimRiga - wcslen(riga), L",%ls,%.4f", matrix->lista[i][j].Stringa, matrix->lista[i][j].frequenza); // aggiungo la stringa e la frequenza
        }
        if ((i + 1) != matrix->y - 1) { // se non è l'ultima riga
            swprintf(riga + wcslen(riga), dimRiga - wcslen(riga), L"%ls", L"\n"); // aggiungo una nuova linea
        }
        wprintf(L"%ls", riga);
        write(pipe2[1], riga, sizeof(riga)); // scrivo la rappresentazione in stringa della riga sulla pipe2
    }
    close(pipe2[1]); // chiudo la pipe2
    return dimMAX; // ritorno dimMAX
}

void stampa(FILE* foglio, int pipe2[], int MAX) { // dichiaro la funzione stampa
    close(pipe2[1]); // chiudo la scrittura della pipe2
    wchar_t riga[MAX]; // dichiaro un buffer per la riga con dimensione di bytes pari alla dimensione massima della riga più lunga della matrice
    while (read(pipe2[0], riga, sizeof(riga)) > 0) { // leggo dalla pipe2
        fwprintf(foglio, L"%ls", riga); // scrivo la riga nel file
    }
}

// Funzione per la lettura del file di input
void leggiParolaFileInput(FILE* file, int pipe1[], long int posizione) {
    wchar_t stringa1[31];
    int indice = 0;
    wchar_t carattere;
    const wchar_t* caratteriAccentati = L"àèéìòóùÀÈÉÌÒÓÙ";
    fseek(file, posizione, SEEK_SET);

    while ((carattere = fgetwc(file)) != WEOF) {
        wchar_t successivo = fgetwc(file);
        fseek(file, -1, SEEK_CUR);

        if ((carattere == L' ' || carattere == L'\n') && successivo == WEOF) {
            // Gestisci il caso in cui l'ultimo carattere è uno spazio o una nuova riga
            if (indice > 0) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
            }
            break;
        }

        if (carattere == L'!' || carattere == L'?' || carattere == L'.') {
            if (indice > 0) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
            }
            stringa1[0] = carattere;
            stringa1[1] = L'\0';
            write(pipe1[1], stringa1, sizeof(stringa1));
            if (successivo == WEOF) {
                break;
            }
        } else if (iswalnum(carattere) || (wcschr(caratteriAccentati, carattere) != NULL) || carattere == L'\'') {
            stringa1[indice++] = carattere;
            if (successivo == L' ' || successivo == L'\n' || successivo == WEOF ||
                successivo == L'!' || successivo == L'?' || successivo == L'.' || carattere == L'\'') {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
            }
        } else if (carattere == L' ' || carattere == L'\n') {
            if (indice > 0) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
            }
        } else if (!(iswalnum(carattere) || (wcschr(caratteriAccentati, carattere) != NULL) ||
                     carattere == L'\'' || carattere == L'!' ||
                     carattere == L'?' || carattere == L'.') &&
                   (successivo == L' ' || successivo == L'\n')) {
            if (indice > 0) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
            }
            continue;
        }

        if (successivo == WEOF) {
            break;
        }
    }

    close(pipe1[1]);
}
Devi accedere o registrarti per scrivere nel forum
0 risposte