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!