001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<string.h>
004: 
005: #define MSIZE   (60)
006: #define NCOPPIE (512)
007: #define NFILE   "brisk.csv"
008: #define OFILE   "descr.txt"
009: #define BFILE   "descr.bin"
010: 
011: // struct per gestire 2 coppie di coordinate
012: struct brisk
013: {
014:   unsigned int r1, c1, r2, c2;
015: };
016: 
017: // prototipi funzioni utilizzate e definite dopo la main()
018: 
019: struct brisk *leggi_csv(void);
020: void          leggi_dati(char *, unsigned int [MSIZE][MSIZE]);
021: char         *leggi_stringa(void);
022: void          gen_descr(struct brisk *,  unsigned int [MSIZE][MSIZE]);
023: void          gen_descr_bin(struct brisk *,  unsigned int [MSIZE][MSIZE]);
024: 
025: int main(int argc, char **argv){
026: 
027:   // #1 chiamo funzione che esegue punto 1
028:   struct brisk *coppie = leggi_csv();
029: 
030:   // #2 
031:   // chiedo nome file (ma poteva esser fatto internamente alla funzione successiva, e' una questione di stile)
032:   printf("Inserisci nome file input: ");
033:   char *nomefile = leggi_stringa();
034:   // una funzione non puo' restituire array e
035:   // di conseguenza lo devo passare io alla funzione
036:   unsigned int mat[MSIZE][MSIZE];
037:   // invoco funzione che legge da file e riempie array
038:   leggi_dati(nomefile, mat);
039:   free(nomefile);
040: 
041:   // #3
042:   // chiedo nome file 
043:   // invoco funzione che calcola descrittore e lo salva su file
044:   gen_descr(coppie, mat);
045: 
046:   // #BONUS, anche se non richiesto dal testo vi lascio da studiare questa funzione che
047:   //         genera effettivamente un reale descrittore binario e lo salva su file
048:   gen_descr_bin(coppie, mat);
049: 
050:   // libero memoria prima di uscire
051:   free(coppie);
052:   return 0;
053: }
054: 
055: // #1 leggo e memorizzo in struttura allocata dinamicamente il file brisk.csv
056: struct brisk *leggi_csv(void)
057: {
058:   struct brisk *coppie = malloc(NCOPPIE*sizeof(struct brisk));
059: 
060:   FILE *f = fopen(NFILE, "r");
061:   if(!f)
062:   {
063:     perror("");
064:     exit(EXIT_FAILURE);
065:   }
066:   for(int i = 0; i < NCOPPIE; ++i)
067:   {
068: 
069:     fscanf(f, "%u,%u,%u,%u", &coppie[i].r1, &coppie[i].c1, &coppie[i].r2, &coppie[i].c2);
070:     printf("%u,%u,%u,%u\n", coppie[i].r1, coppie[i].c1, coppie[i].r2, coppie[i].c2);
071:   }
072:   fclose(f);
073: 
074:   // stampa di DEBUG (commentata dopo aver verificato il corretto funzionamento)
075:   /*
076:   printf("Ho letto:\n");
077:   for(int i = 0; i < NCOPPIE; ++i)
078:     printf("(%u,%u) (%u,%u)\n", coppie[i].r1, coppie[i].c1, coppie[i].r2, coppie[i].c2);
079:   */
080: 
081:   return coppie;
082: }
083: 
084: // #2 leggo e memorizzo in array bidimensionale 
085: void leggi_dati(char *nfile, unsigned int m[MSIZE][MSIZE])
086: {
087:   FILE *f = fopen(nfile, "r");
088:   if(!f)
089:   {
090:     perror("");
091:     exit(EXIT_FAILURE);
092:   }
093: 
094:   // lettura da file ASCII
095:   // leggo un valore per volta
096:   // e lo sistemo nella relativa posizione
097:   // riga per riga
098:   for(int i = 0; i < MSIZE; ++i)
099:     for(int j = 0; j < MSIZE; ++j)
100:       fscanf(f, "%u", &m[i][j]);
101: 
102:   fclose(f);
103: 
104:   // stampa di DEBUG (commentata una volta verificato il funzionamento)
105:   /*
106:   for(int i = 0; i < MSIZE; ++i)
107:   {
108:     for(int j = 0; j < MSIZE; ++j)
109:     {
110:       printf("%3u ", m[i][j]);
111:     }
112:     printf("\n");
113:   }
114:   */
115: }
116: 
117: // #3 genera descrittore e lo salva su file
118: void gen_descr(struct brisk *c, unsigned int mat[MSIZE][MSIZE])
119: {
120:   unsigned char descr[NCOPPIE] = {0}; // array che contiene il descrittore, lo inizializzo a 0
121:   for(int i = 0; i < NCOPPIE; ++i)
122:     if(mat[c[i].r1][c[i].c1] > mat[c[i].r2][c[i].c2])
123:       descr[i] = 1;
124: 
125:   FILE *fp = fopen(OFILE, "w");
126:   if(!fp)
127:   {
128:     perror("");
129:     exit(EXIT_FAILURE);
130:   }
131:   
132: 
133:   // stampa a schermo e salvataggio su file
134:   printf("Descrittore: ");
135:   for(int i = 0; i < NCOPPIE; ++i)
136:   {
137:     printf("%d", descr[i]);
138:     fprintf(fp, "%d", descr[i]);
139:   }
140:   printf("\n");
141:   fclose(fp);
142: 
143: 
144: }
145: 
146: // #3 genera descrittore lavorando a livello di bit e lo salva su file
147: //    come indicato sopra non era richiesto dal testo ma puo' essere
148: //    utile esercizio di manipolazione bit
149: void gen_descr_bin(struct brisk *c, unsigned int mat[MSIZE][MSIZE])
150: {
151:   
152:   // come gestisco 512 bit? Un singolo int e' 4 byte ovvero 32 bit
153:   // mi bastano 16 int per gestire quindi 512 bit
154:   unsigned int descr[16] = {0}; 
155: 
156:   // per il singolo bit calcolato di volta in volta
157:   unsigned int bit;  
158: 
159:   // man mano che calcolo stampo anche
160:   printf("Descrittore: ");
161: 
162:   // scandisco tutte le coppie
163:   for(int i = 0; i < NCOPPIE; ++i)
164:   {
165:     // calcolo il relativo bit
166:     if(mat[c[i].r1][c[i].c1] > mat[c[i].r2][c[i].c2])
167:       bit = 1;
168:     else
169:       bit = 0;
170: 
171:     // man mano lo stampo a schermo
172:     printf("%u", bit);
173:     
174:     // dove lo metto?
175:     // il contatore del ciclo i lo posso vedere come indice del relativo bit che calcolo da 0 a 511
176:     // in quale elemento di descr[] devo mettere quel bit lo posso calcolare dividendo i per 32 (numero di bit di ciascun elemento di decr[])
177:     int index = i/32;  
178: 
179:     // e quale bit uso di quell'elemento? In questo caso e' calcolabile come resto della divisione di i per 32
180:     int offset = i%32;
181: 
182:     // la variabile bit contiene solo 1 o 0 quindi da un punto di vista binario sara' 
183:     // 00000000000000000000000000000000 oppure 00000000000000000000000000000001
184:     // sposto il bit nella posizione in cui deve andare (scorrimento verso sinistra di offset)
185:     // e per "iniettarlo" nel relativo elemento mi basta un or bit a bit '|'
186:     descr[index] = descr[index] | (bit << offset);
187:   }
188:   printf("\n");
189: 
190:   // salvataggio su file binario
191:   FILE *fp = fopen(BFILE, "w");
192:   if(!fp)
193:   {
194:     perror("");
195:     exit(EXIT_FAILURE);
196:   }
197: 
198:   fwrite(descr, sizeof(unsigned int), 16, fp);
199:   
200:   fclose(fp);
201: 
202: 
203: }
204: 
205: 
206: // funzione di appoggio per lettura stringa
207: // vista identica a lezione
208: char *leggi_stringa(void)
209: {
210:   char tmp[1000];
211:   scanf(" %s", tmp);
212: 
213:   char *s = malloc(strlen(tmp) + 1);
214:   strcpy(s, tmp);
215: 
216:   return s;
217: }
218: