001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<string.h>
004: #include<ctype.h>
005: 
006: void stampa(int r, int c, char cr[r][c]);
007: void stampaorizzontali(int r, int c, char cr[r][c]);
008: void stampaverticali(int r, int c, char cr[r][c]);
009: 
010: int main(int argc, char **argv){
011: 
012:   char nomefile[1000]; // temporaneo sufficientemente largo per nome file
013:   printf("Inserire il nome del file da aprire: ");
014:   scanf("%s", nomefile);
015: 
016:   FILE *fp = fopen(nomefile, "r"); // apro il file in lettura non binario
017:   if(!fp)
018:   {
019:     perror("");   // qualora apertura fallisse stampo relativo errore
020:     exit(EXIT_FAILURE);
021:   }
022: 
023:   int nr, nc; // per memorizzare dimensioni schema
024:   fscanf(fp, "%d %d", &nr, &nc); // leggo da file
025:   char mat[nr][nc]; // alloco matrice schema con VLA (qui posso farlo, sono nella main())
026: 
027:   for(int r=0; r<nr; ++r)
028:     for(int c=0; c<nc; ++c)
029:       fscanf(fp, " %c", &mat[r][c]);  // leggo carattere per carattere ignorando spaziature e riempo matrice
030: 
031:   fclose(fp); // chiudo file
032: 
033:   // invoco funzioni di stampa
034:   printf("Schema cruciverba: \n\n");
035:   stampa(nr, nc, mat);
036: 
037:   printf("\nParole orizzontali:\n");
038:   stampaorizzontali(nr, nc, mat);
039: 
040:   printf("\nParole verticali:\n");
041:   stampaverticali(nr, nc, mat);
042: 
043:   return 0;
044: }
045: 
046: void stampa(int r, int c, char cr[r][c]) // per passare VLA a funzione devo passare prima le sue dimensioni e solo dopo l'array
047: {
048:   // ciclo su elementi matrice
049:   for(int y=0; y<r; ++y) 
050:   {
051:     for(int x=0; x<c; ++x)
052:       printf("%c", toupper(cr[y][x])); //stampo carattere (lo converto in maniuscolo ma non era di fatto richiesto)
053:     printf("\n"); // al termine di ogni riga vado a capo
054:   }
055: }
056: 
057: void stampaorizzontali(int r, int c, char cr[r][c])
058: {
059:   char tmp[c+1]; // temporaneo in cui creo man mano le parole da stampare. Sicuramente sono massimo c caratteri a cui aggiungere il carattere di fine stringa
060:   int count = 1; // contatore parole (non richiesto dal testo)
061: 
062:   for(int y=0; y<r; ++y)
063:   {
064:     int tmp_index = 0;  // indice che uso per creare la stringa in tmp[]
065:     for(int x=0; x<c; ++x)
066:     {
067:       if(cr[y][x] != '#') // incontro casella  con carattere, l'accumulo nella stringa e procedo
068:       {
069:   tmp[tmp_index] = cr[y][x]; 
070:   ++tmp_index; // aggiorno indice per tmp[]
071:       }
072:       else   // scatta quando cr[y][x] == '#' ovvero incontro casella 'nera', chiudo la stringa, se lunghezza maggiore di due la stamp
073:       {
074:   tmp[tmp_index] = '\0'; // termino stringa  (altrimenti e' solo array di char ma non stringa)
075:   if(strlen(tmp) > 2)    // controllo lunghezza
076:   {
077:     printf("%3d. %s\n", count, tmp); // nel caso stampo e incremento contatore parole
078:     ++count;
079:   }
080:   tmp_index = 0; // devo ripartire con una nuova stringa in cui mettere i caratteri e di conseguenza azzero indice
081:       }
082:     }
083:     // a fine riga comunque chiudo la stringa e controllo se lunghezza maggiore di due come sopra
084:     tmp[tmp_index] = '\0';
085:     if(strlen(tmp) > 2)
086:     {
087:       printf("%3d. %s\n", count, tmp);
088:       ++count;
089:     }
090:     tmp_index = 0;
091:   }
092: }
093: 
094: void stampaverticali(int r, int c, char cr[r][c])
095: {
096:   // si puo' fare simile alla precedente banalmente invertendo i cicli
097:   // viceversa io creo la trasposta e richiamo la precedente ottenendo cosi' codice piu' compatto (ma non necessariamente piu' efficiente, anzi)
098:   char crt[c][r];
099:   for(int y=0; y<r; ++y)
100:     for(int x=0; x<c; ++x)
101:       crt[x][y] = cr[y][x];
102: 
103:   stampaorizzontali(c, r, crt);
104: 
105: }
106: 
107: 
108: