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: