Come posso sommare colonne di file diversi in C?

di il
5 risposte

Come posso sommare colonne di file diversi in C?

Ciao a tutti, ho 160 file del tipo File%d-%d , dove il primo %d è un intero r=1,....,40 mentre il secondo %d è un intero d=1,...,4 che posso schematizzare come segue:
         File1-1     File1-2    File1-3     File1-4        
         x1a y1a     x1b y1b    x1c y1c     x1d y1d 
         x2a y2a     x2b y2b    x2c y2c     x2d y2d
         x3a y3a     x3b y3b    x3c y3c     x3d y3d
            .           .           .           .
            .           .           .           .


          File2-1     File2-2    File2-3     File2-4   
          x1e y1e     x1f y1f    x1g y1g     x1h y1h 
          x2e y2e     x2f y2f    x2g y2g     x2h y2h
          x3e y3e     x3f y3f    x3g y3g     x3h y3h
             .           .            .        .
             .           .            .        .
               
           
           File3-1     File3-2    File3-3     File3-4   
           x1i y1i     x1l y1l    x1m y1m     x1n y1n 
           x2i y2i     x2l y2l    x2m y2m     x2n y2n
           x3i y3i     x3l y3l    x3m y3m     x3n y3n
             .            .           .           .
             .            .           .           .
               
Devo sommare le colonne di ogni file con il secondo %d fissato (ad esempio: File%d-1) riga per riga e scrivere la somma in un nuovo file: Filesum1; stessa cosa per File%d-2 e così via, cioè devo ottenere:
                       Filesum1                                                 Filesum2                              and so on  ..
          x1a+x1e+x1i+...       y1a+y1e+y1i+..                        x1b+x1f+x1l+..      y1b+y1f+y1l+..                .
          x2a+x2e+x2b+..        y2a+y2e+y2i+..                       x2b+x2f+x2l+..      y2b+y2f+y2l+..                 .
                  .                   .                                    .                       .                    .
                  .                   .                                    .                       .                    . 
Con il seguente codice prendo in considerazione solo File1-%d e File2-%d . Vorrei modificare il codice aggiungendo dei cicli che mi permettano di considerare tutti i file: File1-%d, File2-%d, File3-%d, ... , File40-%d, dove l'intero %d assume valori da 1 a 4.
int main(){
        FILE *readFile1;
        FILE *readFile2;
        FILE *writeFile;
        char inFile1[32] = {0};
        char inFile2[32] = {0};
        char sumFile[32] = {0};
        int i,xa,xb,ya,yb;
        for(i=0;i<4;i++){
                sprintf(inFile1, "File1-%d", i); 
                sprintf(inFile2, "File2-%d", i); 
                sprintf(sumFile, "sumFile%d", i); 
                readFile1 = fopen(inFile1, "r");
                readFile2 = fopen(inFile2, "r");
                writeFile = fopen(sumFile, "w");
                while(1){
                        if(feof(readFile1) || feof(readFile2))
                                break;
                        fscanf(readFile1, "%d %d", &xa, &ya);
                        fscanf(readFile2, "%d %d", &xb, &yb);
                        fprintf(writeFile, "%d %d", xa+xb, ya+yb);
                }   
                fclose(readFile1);
                fclose(readFile2);
                fclose(writeFile);
        }   
        return 1;
}
Qualcuno potrebbe aiutarmi? Grazie!

5 Risposte

  • Re: Come posso sommare colonne di file diversi in C?

    Non ho capito se vuoi ottenere come risultato delle lunghe stringhe che siano la concatenazione delle stringhe parziali, oppure se ognuno di quegli x1a, x1e, ecc. sono valori numerici da sommare per ottenerne il totale (per cui le lettere le hai aggiunte solo per aiutare a capirne l'ordine).
  • Re: Come posso sommare colonne di file diversi in C?

    Quello che stai descrivendo e' un "tensore" a 4 dimensioni (o se vuoi, 'array multidimensionale')

    - 2 dimensioni sono le due colonne nel file
    - le altre 2 dimensioni sono i due indici del file

    E le operazioni che stai desvrivendo sono le normali operazioni che si fanno lungo gli assi del tensore.

    Quindi, quello che ti conviene fare e':

    1) implementare una mini libreria per la manipolazione di tensori (per le sole cose che ti servono), oppure cerchi una libreria gia' fatta (ad esempio boost::multiarray), che va studiata
    2) implementi il codice per leggere i due vettori dai file
    3) allochi abbastanza spazio nel tensore per tenere tutte le informazioni
    4) popoli le varie dimensioni con i dati letti dai file
    5) calcoli le somme (il risultato e' un tensore di dimensione inferiore)
    6) salvi il risultato nel formato che piu' di aggrada

    Giusto per la terminologia:
    un 'tensore' e' la versione generalizzata di un 'vettore'/'array'. Il tensore ha un 'rango' che corrisponde al numero di dimensioni:

    un numero e' un tensore di rango 0
    un vettore e' un tensore di rango 1
    una matrice e' un tensore di rango 2
    un cubo e' un tensore di rango 3
    ecc ...

    Ogni dimensione ha un numero definito di elementi
  • Re: Come posso sommare colonne di file diversi in C?

    AldoBaldo ha scritto:


    Non ho capito se vuoi ottenere come risultato delle lunghe stringhe che siano la concatenazione delle stringhe parziali, oppure se ognuno di quegli x1a, x1e, ecc. sono valori numerici da sommare per ottenerne il totale (per cui le lettere le hai aggiunte solo per aiutare a capirne l'ordine).

    Sono valori numerici da sommare per ottenerne il totale!
  • Re: Come posso sommare colonne di file diversi in C?

    migliorabile ha scritto:


    Quello che stai descrivendo e' un "tensore" a 4 dimensioni (o se vuoi, 'array multidimensionale')

    - 2 dimensioni sono le due colonne nel file
    - le altre 2 dimensioni sono i due indici del file

    E le operazioni che stai desvrivendo sono le normali operazioni che si fanno lungo gli assi del tensore.

    Quindi, quello che ti conviene fare e':

    1) implementare una mini libreria per la manipolazione di tensori (per le sole cose che ti servono), oppure cerchi una libreria gia' fatta (ad esempio boost::multiarray), che va studiata
    2) implementi il codice per leggere i due vettori dai file
    3) allochi abbastanza spazio nel tensore per tenere tutte le informazioni
    4) popoli le varie dimensioni con i dati letti dai file
    5) calcoli le somme (il risultato e' un tensore di dimensione inferiore)
    6) salvi il risultato nel formato che piu' di aggrada

    Giusto per la terminologia:
    un 'tensore' e' la versione generalizzata di un 'vettore'/'array'. Il tensore ha un 'rango' che corrisponde al numero di dimensioni:

    un numero e' un tensore di rango 0
    un vettore e' un tensore di rango 1
    una matrice e' un tensore di rango 2
    un cubo e' un tensore di rango 3
    ecc ...

    Ogni dimensione ha un numero definito di elementi
    Ti ringrazio per il suggerimento. Ho fatto delle ricerche ed ho visto che queste librerie sono tipiche del C++, ma io programmo in C quindi mi servirebbe una soluzione alternativa...
  • Re: Come posso sommare colonne di file diversi in C?

    Per puro intrattenimento, ho provato a cercare una soluzione al problema seguendo una strada "alla mia maniera" (cioè "a tentoni").

    Per prima cosa, ho verificato che ogni file contenesse la stessa quantità di righe, perché mi sembrava un presupposto essenziale. Per questo ho messo insieme due funzioni:

    unsigned int conta_righe_ogni_file( void );
    unsigned int conta_righe_file( const char *nf ); // nf: nome file

    Se tutti i file hanno la stessa quantità di righe, conta_righe_ogni_file() restituisceo la quantità di righe; in caso contrario segnala l'errore in console e restituisce (unsigned int)-1.

    Se il controllo viene superato, uso la conoscenza della quantità delle righe nei file per allocare con calloc() uno spazio di memoria sufficiente a contenere tutti i dati presenti in tutti i file in un unico vettore di strutture coo_t (una specie di "punto", con coordinate intere x e y). Ipotizzando che i file abbiano 10 righe ciascuno, si tratta di un vettore con 4*40*10 elementi.

    Se l'allocazione riesce, con due funzioni dedicate...

    int carica_dati_ogni_file( coo_t *d, unsigned int qr ); // qr: quantita' di righe
    int carica_dati_file( coo_t *d, unsigned int n1, unsigned int n2, unsigned int qr );

    ...provvedo a leggere i dati dei file e a collocarli sequenzialmente nel vettore allocato, per poterli successivamente manipolare più agevolmente. Le due funzioni restituiscono 1 se il caricamento va a buon fine, 0 in caso contrario. In caso di errore, segnalano in console il "punto" nel quale si è verificato il problema (ad esempio, aprendo File12-1.txt, oppure caricando la riga n. 5 di File21-2.txt).

    Il parametro d punta allo spazio allocato dove collocare i dati letti, mentre n1 e n2 sono i due numeri che compaiono nei nomi dei file.

    Per individuare la posizione dove collocare ogni singolo dato nel vettore ho usato l'aritmetica dei puntatori, basandomi sui numeri identificativi dei file e su quelli delle righe.
    int carica_dati_file(
        coo_t *d, unsigned int n1, unsigned int n2, unsigned int qr ) {
        
        /* qui legge i dati dal file, riga per riga, collocandoli nel vettore a
        partire dalla posizione puntata da d (calcolata in carica_dati_ogni_file);
        qr e' la quantita' delle righe presenti in ogni file, incluso questo;
        n1 e n2 servono solo per comporre il nome del file da aprire */
        
    }
    
    int carica_dati_ogni_file( coo_t *d, unsigned int qr ) {
        unsigned int i, j;
    
        for( i=0; i<MAX_N1; ++i ) {
            for( j=0; j<MAX_N2; ++j ) {
                if( !carica_dati_file(d+i*MAX_N2*qr+j*qr,i+1,j+1,qr) )
                    return 0; // errore gia' segnalato in carica_dati_file()
            }
        }
    
        return 1;
    }
    Una volta che ho i dati in memoria, posso pensare a creare i file per l'output, Filesum1.txt ecc. con una funzione compila_file_somme():

    int compila_file_somme( const coo_t *dati, unsigned int qr );

    Nell'ambito di questa funzione, ho usato un ciclo annidato fatto così:
    for( j=0; j<MAX_N2; ++j ) { // MAX_N2 vale 4
        char b[32];
    
        FILE *f = fopen( componi_nome_file_somma(b,j+1), "w+" );
    
        if( f ) {
            for( r=0; r<qr; ++r ) { // r rappresenta il numero della riga
                coo_t somma = { 0, 0 };
    
                for( i=0; i<MAX_N1; ++i ) { // MAX_N1 vale 40
                    coo_t dato;
    
                    estrai_dato( &dato, dati, qr, i, j, r );
    
                    somma.x += dato.x;
                    somma.y += dato.y;
                }
    
                fprintf( f, "%d %d\n", somma.x, somma.y );
            }
    
            fclose( f );
        }
        else {
            printf( "%s non aperto\n", b );
            return 0;
        }
    }
    ...dove estrai_dato() è una funzione accessoria che si occupa di "recuperare" un singolo dato dal vettore nel quale sono stati caricati tutti i dati contenuti nel file.
    /*==============================================================================
    n1 e' in relazione al primo numero contenuto nel nome dei file (qui, pero', zero
    based), mentre n2 e' in relazione al secondo (sempre zero based); r e' il numero
    d'ordine della riga della quale si vuole conoscere i valori.
    Presuppone che n1, n2 e r non "sfondino" il vettore.
    ==============================================================================*/
    
    int estrai_dato( coo_t *dato, const coo_t *vettore_dati, unsigned int qr,
                     unsigned int n1, unsigned int n2, unsigned int r ) {
        if( dato && vettore_dati ) {
            *dato = vettore_dati[n1*MAX_N2*qr+n2*qr+r];
            return 1;
        }
    
        return 0;
    }
    Non avendo i 160 file coi dati (e non avendo voglia di crearli) non ho potuto fare i test che sarebbe stato il caso di fare, per cui non so dirti quanto sia affidabile o inaffidabile questo procedimento, né quanti e quali errori potrei aver commesso. Dita incrociate!
Devi accedere o registrarti per scrivere nel forum
5 risposte