Pagina 1 di 3 1 2 3 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 21
  1. #1

    [C] Problema con matrice dinamica

    Salve, sono ancora alle prime armi nella programmazione in C.
    Ho un problemino con l'allocazione di una matrice dinamica e spero che mi aiutiate a risolverlo... Ho la necessità di allocare, all'interno di una funzione, un array bidimensionale che dovrò modificare opportunamente e restituire al main...

    Riporto di seguito la porzione di programma che riguarda il mio problema:
    codice:
    int main ()
    {
        char** diz = NULL; int num;
    
        num = Elabora_file1(diz);
        if (num == -1){
            return 1;
        }
    
    ...........
    }

    La funzione Elabora_file1 così definita riceve come parametro il doppio puntatore diz ed è così strutturata:

    codice:
    int Elabora_file1 (char** diz)
    {
        FILE* pf1; int num, i=0;
    
        pf1 = fopen(f1, "r");
        if (pf1 == NULL){
            printf ("Errore apertura del file!\n");
            return -1;
        } //Lettura del file
    
        fscanf (pf1, "%d", &num);
        diz = Alloca_diz(num);
        while (fscanf(pf1, "%s", diz[i]) != EOF){
            i++;
        }
    
        fclose(pf1);
    return num;
    }
    Qualche informazione in più per capire il codice.
    Il file che apro nella funzione è strutturato in modo che nella prima riga compaia il numero di parole (la cui lunghezza massima è 20 caratteri) che seguiranno...
    Ad esempio:
    3
    ciao
    miao
    salve
    Il numero sulla prima riga mi da dunque l'informazione necessaria per allocare la matrice..
    Richiamo la funzione Alloca_diz così strutturata:

    codice:
    char** Alloca_diz (int num)
    {
        char** m; int i=0;
    
        m = malloc(num*sizeof(char*));
        for (i=0; i<20; i++){
            m[i] = malloc(20*sizeof(char));
        }
    
        return m;
    }
    Il problema si presenta quando devo ritornare la matrice nel main e credo di aver capito il motivo...
    La matrice è allocata all'interno della funzione ma NON nel main e di conseguenza le modifiche che applico sulla stessa non sono visibili nel main...
    Avevo dunque pensato all'utilizzo di un TRIPLO puntatore ma non ho idea di come fare...

    Qualche anima buona mi potrebbe aiutare? C'è qualche modo per evitare l'utilizzo del triplo puntatore??? Nel corso del programma dovrò riutilizzare la matrice per altre elaborazioni e quindi mi risulterebbe assai scomodo lavorare con un triplo puntatore...

    Grazie in anticipo

  2. #2

    Moderazione

    Benvenuto sul forum Ti ricordo che il codice va formattato nei tag [code] ... [/code], altrimenti perde l'indentazione; qui ho sistemato io, in futuro ricordatene.

    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Si scusami... Grazie...
    Hai qualche idea su come risolvere il problema?

  4. #4
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Intendi dire che la funzione Elabora_file1() dovrebbe restituire in qualche modo al main la matrice allocata dalla funzione Alloca_diz() ?
    Se è così, non c'è nulla di difficile. Il tuo puntatore rimane un doppio puntatore all'interno del main e un triplo puntatore nella funzione Elabora_file1() (in rosso le modifiche):

    codice:
    int main ()
    {
        char** diz = NULL; int num;
    
        num = Elabora_file1(&diz);
        if (num == -1){
            return 1;
        }
    
    ...........
    }
    codice:
    int Elabora_file1 (char*** diz)
    {
        FILE* pf1; int num, i=0;
    
        pf1 = fopen(f1, "r");
        if (pf1 == NULL){
            printf ("Errore apertura del file!\n");
            return -1;
        } //Lettura del file
    
        fscanf (pf1, "%d", &num);
        *diz = Alloca_diz(num);
        while (fscanf(pf1, "%s", (*diz)[i]) != EOF){
            i++;
        }
    
        fclose(pf1);
    return num;
    }
    Fai attenzione a un fatto nella funzione Alloca_diz(): allochi per il puntatore m un certo numero "num" di puntatori char, poi però dopo assumi che tale numero di puntatori sia pari (almeno) a 20, dato che il ciclo esegue staticamente 20 iterazioni. Tutto ciò funzionerà correttamente solo se num sarà effettivamente almeno 20. E anche se dai per scontato che quel "num" non sia mai meno di 20, irrobustisci il codice con un controllo o scrivendo "i < num" come predicato di uscita del for. Considerazioni analoghe valgono anche per il while nella funzione Elabora_file1().
    Ricorda inoltre di deallocare la memoria con la free() una volta che la matrice non ti serve più.
    every day above ground is a good one

  5. #5
    Scusa avevo sbagliato a copiare il codice! errore mio Nella funzione che alloca la matrice al posto del 20 all'interno del ciclo for va messo il numero di stringhe che estrarrò dal file Quindi la matrice dovrà contenere sulle righe le singole stringhe che estraggo dal file...
    Ho provato ad implementare i cambiamenti da te suggeriti ma purtroppo il programma non va

  6. #6
    Utente bannato
    Registrato dal
    Apr 2012
    Messaggi
    510
    Originariamente inviato da Astor92
    Ho provato ad implementare i cambiamenti da te suggeriti ma purtroppo il programma non va
    Qual'è il problema esattamente?

  7. #7
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Se è agevole, posta tutto il programma, possibilmente fornendo anche il contenuto di un file di prova.
    Nel frattempo, questo è un esempio funzionante di qualcosa di simile.

    * ometto, per semplicità, il controllo di tutti gli errori possibili;
    * il passaggio del puntatore triplo alla funzione wrapper() può ovviamente essere "propagato" alla funzione allocate() senza che questa debba necessariamente restituire il valore di un puntatore dichiarato localmente

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define STRLEN  20
    
    char **allocate(int num)
    {
        char **m = NULL;
        int i;
    
        m = malloc(sizeof(char *) * num);
        for (i = 0; i < num; i++) {
            m[i] = malloc(sizeof(char) * STRLEN);
        }
    
        return m;
    }
    
    int wrapper(char ***m)
    {
        int num = 10, i;
    
        *m = allocate(num);
        for (i = 0; i < num; i++) {
            printf("insert string number %d\n", i+1);
            fgets((*m)[i], STRLEN, stdin);
        }
    
        return num;
    }
    
    int main(void)
    {
        char **m = NULL;
        int num, i;
    
        num = wrapper(&m);
        puts("*** strings ***");
        for (i = 0; i < num; i++) {
            puts(m[i]);
        }
        for (i = 0; i < num; i++) {
            free(m[i]);
        }
        free(m);
    
        return 0;
    }
    every day above ground is a good one

  8. #8
    Il programma mi chiede questo:
    Si scriva un programma in grado di contare le occorrenze di ogni parola, appartenente a un insieme specificato, all’interno di un generico testo. Più in dettaglio, l’elenco delle parole da ricercare è memorizzato in un file di testo, in ragione di una parola per riga del file. La lunghezza delle singole parole è limitata a 20 caratteri, e inoltre il numero totale
    di tali parole è indicato sulla prima riga del file stesso.
    Le parole così specificate devono essere ricercate in un testo memorizzato in un secondo file. Il numero di righe di questo file è indefinito. Come output, il programma deve riportare su video l’elenco delle parole contenute nel primo file, ciascuna seguita dal numero di occorrenze con cui compare nel testo contenuto nel secondo file. Si noti che i due file devono
    essere letti una volta sola.
    Si trascurino i possibili problemi derivanti dall’uso della punteggiatura (ovvero si considerino le stringhe “parola”, “parola.”, etc., come diverse).

    ESEMPIO FILE1
    4
    edison
    e’
    genio
    citazione

    ESEMPIO FILE2
    il genio non e’ altro che una grande attitudine alla pazienza, Buffon
    il Genio e’ la punta estrema della saggezza, Cocteau
    il GENIO e’ 10% ispirazione e 90% sudore, Edison
    Io un genio? Non diciamo sciocchezze..., Anonimo

    Questo è il codice che ho scritto:
    codice:
    int main ()
    {
        char** diz = NULL; int num, i=0; int* v;
    
        num = Elabora_file1(&diz);
        if (num == -1){
            return 1;
        }
    
    	v = malloc(num*sizeof(int));
    	for(i=0; i<num; i++)
    		v[i] = 0;
    
    	if (Elabora_risultati(&num, diz,v));
    	else return 1;
    
    	Stampa_risultati(num, diz, v);
    
        return 0;
    }
    Funzione che legge il primo file. La prima riga del file contiene il numero di parole contenute nel file stesso. Utilizzo il risultato della prima fscanf per allocare la matrice.
    Dopodichè memorizzo nella matrice le parole estraendole dal file attraverso un ciclo di fscanf
    codice:
     int Elabora_file1 (char*** diz)
    {
        FILE* pf1; int num, i=0;
    
        pf1 = fopen(f1, "r");
        if (pf1 == NULL){
            printf ("Errore apertura del file!\n");
            return -1;
        }
    
        fscanf (pf1, "%d", &num);
        *diz = Alloca_diz(num);
        while (fscanf(pf1, "%s", (*diz)[i]) != EOF){
            i++;
        }
    
        fclose(pf1);
    	return num;
    }
    Funzione che mi alloca la matrice
    codice:
    char** Alloca_diz (int num)
    {
        char** m; int i=0;
    
        m = malloc(num*sizeof(char*));
        for (i=0; i<num; i++){
            m[i] = malloc(MAXLEN*sizeof(char));
        } //allocazione della matrice 1
    
        return m;
    }

    Funzione che mi ricerca nel secondo file le parole memorizzate dal primo file e incrementa le caselle di un vettore v, precedentemente allocato ed inizializzato a zero, in modo da tener conto delle occorrenze.
    codice:
    int Elabora_risultati (int* num, char** diz, int* v)
    {
    	FILE* pf2; char stringa[MAXLEN]; int i=0;
    
    	pf2 = fopen(f2, "r");
        if (pf2 == NULL){
            printf ("Errore apertura del file!\n");
            return -1;
        }
    
        while (fscanf(pf2, "%s", stringa) != EOF){
            for(i=0; i<num; i++){
                if (strcmp(stringa,diz[i]) == 0)
                    v[i]++;
            }
        }
    
        fclose(pf2);
    	return 1;
    }
    Funzione di stampa
    codice:
    void Stampa_risultati(int num, char** diz, int* v)
    {
        int i=0;
    
    	for(i=0; i<num; i++){
            printf ("%s:\t%d volta/e\n", diz[i], v[i]);
        }
    	return;
    }
    Ho omesso le parti in cui libero la memoria perchè ho scritto il codice di botto e me n'ero scordato

  9. #9
    Originariamente inviato da Who am I
    Qual'è il problema esattamente?
    Quando provo ad avviare il programma mi dà errore! E' probabile che abbia fatto anche altri errori qua e là... Ho scritto tutto il codice sopra così magari potete controllarlo meglio

  10. #10
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Perché passi num per indirizzo alla funzione Elabora_risultati() ?
    every day above ground is a good one

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.