Uni.LaboratorioC History
Hide minor edits - Show changes to markup
Troverete inoltre le risposte - eventualmente commentate dai migliori maghi - alle domande che i suddetti hanno pompato sulle rispettive pagine personali del corso. Leggi le risposte
Troverete inoltre le risposte - eventualmente commentate dai migliori maghi - alle domande che i suddetti hanno pompato sulle rispettive pagine personali del corso.
Leggi le risposte

"Non tutte le librerie si possono invocare"

"Non tutte le librerie si possono invocare"
:: Laboratorio C ::
:: Ambulatorio di C ::

"Non tutte le librerie si possono invocare"
...anche detto Laboratorio di programmazione, conducono Valentina Ciriani e Fabio Scotti.
Troverete inoltre le risposte - eventualmente commentate dai migliori maghi - alle domande che i suddetti hanno pompato sulle rispettive pagine personali del corso.
Leggi le risposte
Troverete inoltre le risposte - eventualmente commentate dai migliori maghi - alle domande che i suddetti hanno pompato sulle rispettive pagine personali del corso. Leggi le risposte
:: Laboratorio C ::
Troverete inoltre le risposte - eventualmente commentate dai migliori maghi - alle domande che i suddetti hanno pompato sulle rispettive pagine personali del corso. Leggi le risposte\\\
Troverete inoltre le risposte - eventualmente commentate dai migliori maghi - alle domande che i suddetti hanno pompato sulle rispettive pagine personali del corso.
Leggi le risposte\\\
Troverete inoltre le risposte - eventualmente commentate dai migliori maghi - alle domande che i suddetti hanno pompato sulle rispettive pagine personali del corso. Leggi le risposte\\\
Qui ci sono le soluzioni agli esercizi dell'ultima lezione, con tanto di commento.
Esercizio 1
Data la traccia sotto riportata completare il codice in modo di aumentare di 1 tutti gli interi pari e diminuire di 1 tutti quelli dispari nell'array vettore[] di dimensione dim. Riportare come risultato il numero che comparira' a monitor. Per esempio un vettore che contiene gli elementi {4,56,3,78,23} dopo essere stato aggiornato deve contenere gli elementi {5,57,2,79,22}. laboratorio 23-24?
Aumenta interi pari #include <stdio.h> float CalcolaRisultato(int vettore[], int dim); int main() { int vettore[] = {4,56,3,78,23} ; int dim = 5; int conto; float risultato; //Se il tuo programma funziona correttamente, dovresti ottenere: 2573 for (conto = 0; conto < dim; conto ++) { if ((vettore[conto] % 2) == 0) vettore[conto] ++; else vettore[conto] --; } risultato = CalcolaRisultato(vettore, dim); printf("\nrisultato da copiare ed incollare = %d \n\n" , (int) risultato ); getchar(); exit(0); } // main float CalcolaRisultato(int vettore[], int dim) { int i; float divisore, dividendo=0; for(i=0;i < dim; i++) { dividendo += i * vettore[i]; } divisore = (dim +1)*dim/2; return 100*dividendo/divisore; }
Note sull'esercizio
Innanzitutto, l'esercizio ti dava un vettore di 462 elementi, mentre qui il vettore ne ha solamente 5.
Il cuore dell'esercizio sta nella sequenza
for (conto = 0; conto < dim; conto ++) { if ((vettore[conto] % 2) == 0) vettore[conto] ++; else vettore[conto] --; }
che vuol dire esattamente questo:
for (conto = 0; conto < dim; conto ++)
esamina il vettore dal primo all'ultimo elemento, ricordando che dim = numero elementi del vettore.
if ((vettore[conto] % 2) == 0) vettore[conto] ++; else vettore[conto] --;
If ((vettore[conto] % 2) == 0) controlla se l'elemento conto-esimo del vettore è pari, cioè se il resto della divisione intera per due è 0.
In caso positivo, esegue la riga vettore[conto] ++, come da specifica; in caso contrario invece viene diminuito con vettore[conto] --, sempre come da specifica.
La funzione CalcolaRisultato è stata data dal professore, serve per generare il valore che va incollato etc. etc.
Esercizio 2
Esegui le seguenti attivita':
- salva il testo sotto riportato nel file telefonate.txt ;
- scrivi il programma Contatelefonate.c che accede al file telefonate.txt e calcola il numero di telefonate effettuate a un cellulare e il numero di quelle effettuate verso un numero fisso;
- calcola come risultato il maggiore tra questi due numeri.
Per stabilire se il telefono e' un cellulare o un fisso si consiglia di utilizzare la funzione strcmp(s1,s2) che restituisce 0 se le due stringhe sono uguali, un numero negativo se s1 e' minore di s2 in ordine lessicografico e un numero positivo altrimenti. Nota bene: il file telefonate.txt e' composto da stringa tabulatore numeroconvirgola tabulatore stringa tabulatore stringa FINERIGA
Note preliminari
Il file telefonate.txt fornito dal professore NON è nel formato che lui indica, cioè stringa tab numeroconvirgola tab stringa tab string FINERIGA, perché non ci sono TAB ma SPAZI fra una riga e l'altra!
Inoltre, il risultato che dà lui, cioè 45, è SBAGLIATO: le chiamate a cellulare sono 44, e sono maggiori delle 23 chiamate a fisso...
Telefonate
#include <stdio.h> #include <string.h> int main() { FILE * telefonate; int chiamate_fisso = 0; int chiamate_cell = 0; int valore; char numero[30]; char ora[30]; char tipo[30]; char durata[30]; telefonate = fopen("telefonate.txt", "r"); if (telefonate == NULL) { printf("Errore nell'apertura del file telefonate.txt\n"); getchar(); return 1; } while (!feof(telefonate)) { fscanf(telefonate,"s s\n", numero, ora, tipo, durata); printf("%s\n", tipo); valore = strcmp(tipo, "cellul"); if (valore == 0) chiamate_cell ++; else chiamate_fisso++; } if (chiamate_fisso > chiamate_cell) printf("%d\n", chiamate_fisso); else printf("%d\n", chiamate_cell); getchar(); return 0; }
Note postliminari
L'unica stringa che ci interessa è la 3a, cioè quella che contiene scritto cellul oppure milano, firenze o quel diavolo che è.
La funzione strcmp(stringa1,stringa2) fa parte della libreria standard del C, e la si ottiene con la riga
#include <string.h>
in cima.
strcmp(stringa1, stringa2) funziona così:
- se le stringhe sono uguali, restituisce uno 0;
- se la prima stringa è MINORE della seconda, lessicograficamente parlando, resituisce -1, o comunque un valore minore di 0
- se invece la seconda stringa è MAGGIORE della seconda, restituisce un valore maggiore di 0, di solito + 1.
Che cosa vuol dire lessicograficamente parlando? Bene o male, è una specie di conto alfabetico, provate un po' per vedere che cosa voglia significare.
Ai nostri fini, serve solo verificare che la terza stringa sia uguale a cellul, e in quel caso aumentare il contatore di numero di chiamate a cell.
Tutto ciò lo si ottiene con
valore = strcmp(tipo, "cellul"); if (valore == 0) chiamate_cell ++; else chiamate_fisso++;
dove int valore l'ho dichiarata appositamente allo scopo.
Esercizio 3
Scrivi un programma che:
- conta quanti caratteri ci sono nel file COSTITUZ.TXT (63 KB) ;
- conta quante volte compare la lettera minuscola 'r' seguita dalla minuscola 'a' ;
- calcola come FLOAT la frequenza di occorrenza della lettera 'i' (e' indifferente se maiuscola o minuscola);
- restituisce come soluzione (con due decimali dopo la virgola) il FLOAT contenete il prodotto delle due quantita' appena calcolate nei punti 2.e 3.
Soluzione: risultato da copiare ed incollare = 45.23
costituzione.c
#include <stdio.h> int main() { FILE * costituzione; int numero_ra = 0; int numero_i = 0; int numero_caratteri = 0; float frequenza_i; float risultato; char c; costituzione = fopen("costituzione.txt", "r"); if (costituzione == NULL) { printf("Errore nell'apertura del file costituzione.txt"); getchar(); return 1; } while (!feof(costituzione)) { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'r') { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'a') numero_ra ++; } else if (c == 'i' || c == 'I') numero_i ++; } frequenza_i = (float) numero_i / numero_caratteri; printf("Numero di ra = %d\n", numero_ra); printf("Numero di i = %d\n", numero_i); printf("Numero di caratteri = %d\n", numero_caratteri); printf("Frequenza di i = %f\n", frequenza_i); printf("risultato = %2.2f", numero_ra * frequenza_i); fclose(costituzione); getchar(); return 0; }
Note sull'esercizio
I punti dubbi sono:
- I caratteri come lo spazio o la punteggiatura vanno contati come numero_caratteri, oppure no? E le lettere accentate, vanno trasformate in lettere non accentate o che diavolo?
Ad ogni modo, il cuore dell'esercizio sta nelle righe
while (!feof(costituzione)) { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'r') { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'a') numero_ra ++; } else if (c == 'i' || c == 'I') numero_i ++; }
Ogni volta che faccio una fscanf sul file, aumento il numero di caratteri, ed il motivo mi sembra ovvio.
Se il carattere trovato è una r, devo poi controllare che ci sia una a, ecco perché dopo il primo
if (c == 'r')
c'è un'altra fscanf.
Sia che trovo una lettera che non è r, sia che trovo una r non seguita da una a, il programma cade automaticamente nell'
else if (c == 'i' || c == 'I') numero_i ++;
Ciò accade perché uso sempre il char c per immagazzinare il prossimo carattere da leggere.
Esercizio 4
Utilizzando codoce sotto riportato come traccia si scriva un programma che contiene una funzione ricorsiva int magia(int n) che si basa sulla funzione ricorsiva magia(n):
- magia(0) vale 1;
- se n>0, allora magia(n) vale (magia(n-1)+100) se n e' pari e (2*magia(n-1)) se n e' dispari;
Il risultato e' quello restituito a monitor dal codice.
magia.c
#include <stdio.h> int magia(int n); int main() //NON MODIFICARE IL MAIN { printf("la soluzione e' --> %d", magia(13)); getchar(); return(0); } int magia(int n) { // 1. magia(0) vale 1; // 2. se n>0, allora magia(n) vale (magia(n-1)+100) se n e' pari e (2*magia(n-1)) se n e' dispari; if (n == 0) return 1; else if (n > 0) { if ((n % 2) == 0) return magia(n - 1) + 100; else return 2*magia(n-1); } }
Note sull'esercizio
Le funzioni ricorsive si scrivono esattamente come le leggete: se ci fate caso, ho copiato pari pari la specifica data dal problema e l'ho tradotta in C.
Infatti, la riga che dice:
magia(0) vale 1;
si traduce letteralmente in
if (n == 0) return 1;
mentre la riga che dice:
se n>0, allora magia(n) vale (magia(n-1)+100) se n e' pari e (2*magia(n-1)) se n e' dispari;
diventa
else if (n > 0) { if ((n % 2) == 0) return magia(n - 1) + 100; else return 2*magia(n-1); }
Esercizio 5
Si utilizzi il codice sotto riportato per risolvere l'esercizio. Data il vettore di caratteri (stringa) v[] inizializzato nel codice dell'esercizio:
- si critti carattere per carattere la stringa v[] mediante il metodo di Cesare con chiave 1 memorizzando il risultato nella stringa srt[];
- La stringa srt[] deve possedere il proprio terminatore;
- il risultato finale e' il numero che compare a monitor (viene prodotto automaticamente dalla funzione CalcolaRisulato che ha gia' impostato il passaggio della stringa srt).
cesare.c
#include <stdio.h> #include <stdlib.h> #include <string.h> float CalcolaRisultato(char stringa[]); int main() { char v[]="SIATTACCADOMANIALLALBA" ; char str[1000]=""; // stringa nella quale va inserito il risultato finale float risultato; int i; // ----- inzio dell'esercizo ------- for (i = 0; i < strlen(v); i ++) { str[i] = v[i] + 1; } str[strlen(v)] = 0; printf("%s\n", str); // ----- fine dell'esercizo ------- // NON TOCCARE TUTTE LE RIGHE QUI SOTTO risultato = CalcolaRisultato(str); printf("\nrisultato da copiare ed incollare = %d \n\n" , (int) risultato ); getchar(); exit(0); } // main float CalcolaRisultato(char stringa[]) { int i; float divisore, dividendo=0; int dim = strlen(stringa); for(i=0;i < dim; i++) { dividendo += i * (int)stringa[i]; } divisore = (dim +1)*dim/2; return 100*dividendo/divisore; }
Note sull'esercizio
Mi sembra semplice: ogni lettera va incrementata di 1, cioè la a diventa b etc.
Inoltre, questa modifica non va salvata nella stringa originale, bensì in str[]. Ciò vuol dire che occorre mettere il \0 alla fine della stringa, perché la teoria ci insegna che le stringhe in C sono NULL-terminated, cioè finiscono con uno 0 (non il carattere, ma proprio il valore 0).
Ecco perché ho messo
str[strlen(v)] = 0;
La strlen(v) mi restituisce la lunghezza della stringa v. Da notare che se la stringa ha 4 caratteri, la strlen mi restituisce il numero 4 => occorre ricordarsi che la prima posizione delle stringhe è 0.
Quindi, il ciclo for è stato scritto cos':
for (i = 0; i < strlen(v); i ++) {
mentre il 5° carattere deve essere il famoso 0 di cui sopra:
str[strlen(v)] = 0;
In questa sezione potrete trovare le soluzioni commentate degli esercizi del buon Scotti e della sensuale Ciriani, divise e confezionate per lezione.
\\
Data la traccia sotto riportata completare il codice in modo di aumentare di 1 tutti gli interi pari e diminuire di 1 tutti quelli dispari nell'array vettore[] di dimensione dim. Riportare come risultato il numero che comparira' a monitor. Per esempio un vettore che contiene gli elementi {4,56,3,78,23} dopo essere stato aggiornato deve contenere gli elementi {5,57,2,79,22}.
Data la traccia sotto riportata completare il codice in modo di aumentare di 1 tutti gli interi pari e diminuire di 1 tutti quelli dispari nell'array vettore[] di dimensione dim. Riportare come risultato il numero che comparira' a monitor. Per esempio un vettore che contiene gli elementi {4,56,3,78,23} dopo essere stato aggiornato deve contenere gli elementi {5,57,2,79,22}. laboratorio 23-24?
#include <string.h> #include <ctype.h>
else if (c == 'i') numero_i ++;
else if (c == 'i' || c == 'I') numero_i ++;
frequenza_i = (numero_i * 100) / numero_caratteri;
frequenza_i = (float) numero_i / numero_caratteri;
// printf("risultato = %2.2f", numero_ra * frequenza_i); NO
printf("risultato = %2.2f", numero_ra / frequenza_i);
printf("risultato = %2.2f", numero_ra * frequenza_i);
}
}
Esce sbagliato. Devo verificare, ma ci sono buoni indizi che il risultato da lui fornito, cioè 45.23, sia veramente sbagliato.
- I caratteri come lo spazio o la punteggiatura vanno contati come numero_caratteri, oppure no? E le lettere accentate, vanno trasformate in lettere non accentate o che diavolo?
- Il numero di occorrenze di ra non può essere così basso, perché se la frequenza di i nel testo è sul 9%, vuol dire che al massimo posso trovare 5 ra in tutto il testo! Ma basta contare il numero di volte che la parola democRAzia compare nel testo, ed è chiaro che non può essere così.
Soluzione: non è il prodotto, ma la DIVISIONE!
Chiaro esempio di approssimazione.
- I caratteri come lo spazio o la punteggiatura vanno contati come numero_caratteri, oppure no? E le lettere accentate, vanno trasformate in lettere non accentate o che diavolo?
else if (c == 'i') numero_i ++;
else if (c == 'i' || c == 'I') numero_i ++;
else if (c == 'i') numero_i ++;
else if (c == 'i' || c == 'I') numero_i ++;
Esercizio 5
Si utilizzi il codice sotto riportato per risolvere l'esercizio. Data il vettore di caratteri (stringa) v[] inizializzato nel codice dell'esercizio:
- si critti carattere per carattere la stringa v[] mediante il metodo di Cesare con chiave 1 memorizzando il risultato nella stringa srt[];
- La stringa srt[] deve possedere il proprio terminatore;
- il risultato finale e' il numero che compare a monitor (viene prodotto automaticamente dalla funzione CalcolaRisulato che ha gia' impostato il passaggio della stringa srt).
cesare.c
#include <stdio.h> #include <stdlib.h> #include <string.h> float CalcolaRisultato(char stringa[]); int main() { char v[]="SIATTACCADOMANIALLALBA" ; char str[1000]=""; // stringa nella quale va inserito il risultato finale float risultato; int i; // ----- inzio dell'esercizo ------- for (i = 0; i < strlen(v); i ++) { str[i] = v[i] + 1; } str[strlen(v)] = 0; printf("%s\n", str); // ----- fine dell'esercizo ------- // NON TOCCARE TUTTE LE RIGHE QUI SOTTO risultato = CalcolaRisultato(str); printf("\nrisultato da copiare ed incollare = %d \n\n" , (int) risultato ); getchar(); exit(0); } // main float CalcolaRisultato(char stringa[]) { int i; float divisore, dividendo=0; int dim = strlen(stringa); for(i=0;i < dim; i++) { dividendo += i * (int)stringa[i]; } divisore = (dim +1)*dim/2; return 100*dividendo/divisore; }
Note sull'esercizio
Mi sembra semplice: ogni lettera va incrementata di 1, cioè la a diventa b etc.
Inoltre, questa modifica non va salvata nella stringa originale, bensì in str[]. Ciò vuol dire che occorre mettere il \0 alla fine della stringa, perché la teoria ci insegna che le stringhe in C sono NULL-terminated, cioè finiscono con uno 0 (non il carattere, ma proprio il valore 0).
Ecco perché ho messo
str[strlen(v)] = 0;
La strlen(v) mi restituisce la lunghezza della stringa v. Da notare che se la stringa ha 4 caratteri, la strlen mi restituisce il numero 4 => occorre ricordarsi che la prima posizione delle stringhe è 0.
Quindi, il ciclo for è stato scritto cos':
for (i = 0; i < strlen(v); i ++) {
mentre il 5° carattere deve essere il famoso 0 di cui sopra:
str[strlen(v)] = 0;
Esercizio 4
Esercizio 4
Utilizzando codoce sotto riportato come traccia si scriva un programma che contiene una funzione ricorsiva int magia(int n) che si basa sulla funzione ricorsiva magia(n):
- magia(0) vale 1;
- se n>0, allora magia(n) vale (magia(n-1)+100) se n e' pari e (2*magia(n-1)) se n e' dispari;
Il risultato e' quello restituito a monitor dal codice.
magia.c
#include <stdio.h> int magia(int n); int main() //NON MODIFICARE IL MAIN { printf("la soluzione e' --> %d", magia(13)); getchar(); return(0); } int magia(int n) { // 1. magia(0) vale 1; // 2. se n>0, allora magia(n) vale (magia(n-1)+100) se n e' pari e (2*magia(n-1)) se n e' dispari; if (n == 0) return 1; else if (n > 0) { if ((n % 2) == 0) return magia(n - 1) + 100; else return 2*magia(n-1); } }
Note sull'esercizio
Le funzioni ricorsive si scrivono esattamente come le leggete: se ci fate caso, ho copiato pari pari la specifica data dal problema e l'ho tradotta in C.
Infatti, la riga che dice:
magia(0) vale 1;
si traduce letteralmente in
if (n == 0) return 1;
mentre la riga che dice:
se n>0, allora magia(n) vale (magia(n-1)+100) se n e' pari e (2*magia(n-1)) se n e' dispari;
diventa
else if (n > 0) { if ((n % 2) == 0) return magia(n - 1) + 100; else return 2*magia(n-1); }
printf("risultato = %2.2f", numero_ra * frequenza_i);
// printf("risultato = %2.2f", numero_ra * frequenza_i); NO
printf("risultato = %2.2f", numero_ra / frequenza_i);
Soluzione: non è il prodotto, ma la DIVISIONE!\\\
NOTE SULL'ESERCIZIO
Note sull'esercizio
strcmp(stringa1, stringa2) funziona così:\\\
strcmp(stringa1, stringa2) funziona così:
dove int valore l'ho dichiarata appositamente allo scopo.
dove int valore l'ho dichiarata appositamente allo scopo.
Esercizio 3
Scrivi un programma che:
- conta quanti caratteri ci sono nel file COSTITUZ.TXT (63 KB) ;
- conta quante volte compare la lettera minuscola 'r' seguita dalla minuscola 'a' ;
- calcola come FLOAT la frequenza di occorrenza della lettera 'i' (e' indifferente se maiuscola o minuscola);
- restituisce come soluzione (con due decimali dopo la virgola) il FLOAT contenete il prodotto delle due quantita' appena calcolate nei punti 2.e 3.
Soluzione: risultato da copiare ed incollare = 45.23
costituzione.c
#include <stdio.h> #include <string.h> #include <ctype.h> int main() { FILE * costituzione; int numero_ra = 0; int numero_i = 0; int numero_caratteri = 0; float frequenza_i; float risultato; char c; costituzione = fopen("costituzione.txt", "r"); if (costituzione == NULL) { printf("Errore nell'apertura del file costituzione.txt"); getchar(); return 1; } while (!feof(costituzione)) { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'r') { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'a') numero_ra ++; } else if (c == 'i') numero_i ++; } frequenza_i = (numero_i * 100) / numero_caratteri; printf("Numero di ra = %d\n", numero_ra); printf("Numero di i = %d\n", numero_i); printf("Numero di caratteri = %d\n", numero_caratteri); printf("Frequenza di i = %f\n", frequenza_i); printf("risultato = %2.2f", numero_ra * frequenza_i); fclose(costituzione); getchar(); return 0;
}
Note sull'esercizio
Esce sbagliato. Devo verificare, ma ci sono buoni indizi che il risultato da lui fornito, cioè 45.23, sia veramente sbagliato.
I punti dubbi sono:
- I caratteri come lo spazio o la punteggiatura vanno contati come numero_caratteri, oppure no? E le lettere accentate, vanno trasformate in lettere non accentate o che diavolo?
- Il numero di occorrenze di ra non può essere così basso, perché se la frequenza di i nel testo è sul 9%, vuol dire che al massimo posso trovare 5 ra in tutto il testo! Ma basta contare il numero di volte che la parola democRAzia compare nel testo, ed è chiaro che non può essere così.
Chiaro esempio di approssimazione.
Ad ogni modo, il cuore dell'esercizio sta nelle righe
while (!feof(costituzione)) { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'r') { fscanf(costituzione, "%c", &c); numero_caratteri ++; if (c == 'a') numero_ra ++; } else if (c == 'i') numero_i ++; }
Ogni volta che faccio una fscanf sul file, aumento il numero di caratteri, ed il motivo mi sembra ovvio.
Se il carattere trovato è una r, devo poi controllare che ci sia una a, ecco perché dopo il primo
if (c == 'r')
c'è un'altra fscanf.
Sia che trovo una lettera che non è r, sia che trovo una r non seguita da una a, il programma cade automaticamente nell'
else if (c == 'i') numero_i ++;
Ciò accade perché uso sempre il char c per immagazzinare il prossimo carattere da leggere.
Esercizio 4
In caso positivo, esegue la riga vettore[conto] ++, come da specifica; in caso contrario invece viene diminuito con vettore[conto] --, sempre come da specifica.
In caso positivo, esegue la riga vettore[conto] ++, come da specifica; in caso contrario invece viene diminuito con vettore[conto] --, sempre come da specifica.
La funzione CalcolaRisultato è stata data dal professore, serve per generare il valore che va incollato etc. etc.
Esercizio 2
Esegui le seguenti attivita':
- salva il testo sotto riportato nel file telefonate.txt ;
- scrivi il programma Contatelefonate.c che accede al file telefonate.txt e calcola il numero di telefonate effettuate a un cellulare e il numero di quelle effettuate verso un numero fisso;
- calcola come risultato il maggiore tra questi due numeri.
Per stabilire se il telefono e' un cellulare o un fisso si consiglia di utilizzare la funzione strcmp(s1,s2) che restituisce 0 se le due stringhe sono uguali, un numero negativo se s1 e' minore di s2 in ordine lessicografico e un numero positivo altrimenti. Nota bene: il file telefonate.txt e' composto da stringa tabulatore numeroconvirgola tabulatore stringa tabulatore stringa FINERIGA
Note preliminari
Il file telefonate.txt fornito dal professore NON è nel formato che lui indica, cioè stringa tab numeroconvirgola tab stringa tab string FINERIGA, perché non ci sono TAB ma SPAZI fra una riga e l'altra!
Inoltre, il risultato che dà lui, cioè 45, è SBAGLIATO: le chiamate a cellulare sono 44, e sono maggiori delle 23 chiamate a fisso...
Telefonate
#include <stdio.h> #include <string.h> int main() { FILE * telefonate; int chiamate_fisso = 0; int chiamate_cell = 0; int valore; char numero[30]; char ora[30]; char tipo[30]; char durata[30]; telefonate = fopen("telefonate.txt", "r"); if (telefonate == NULL) { printf("Errore nell'apertura del file telefonate.txt\n"); getchar(); return 1; } while (!feof(telefonate)) { fscanf(telefonate,"s s\n", numero, ora, tipo, durata); printf("%s\n", tipo); valore = strcmp(tipo, "cellul"); if (valore == 0) chiamate_cell ++; else chiamate_fisso++; } if (chiamate_fisso > chiamate_cell) printf("%d\n", chiamate_fisso); else printf("%d\n", chiamate_cell); getchar(); return 0; }
Note postliminari
L'unica stringa che ci interessa è la 3a, cioè quella che contiene scritto cellul oppure milano, firenze o quel diavolo che è.
La funzione strcmp(stringa1,stringa2) fa parte della libreria standard del C, e la si ottiene con la riga
#include <string.h>
in cima.
strcmp(stringa1, stringa2) funziona così:
* se le stringhe sono uguali, restituisce uno 0;
- se la prima stringa è MINORE della seconda, lessicograficamente parlando, resituisce -1, o comunque un valore minore di 0
- se invece la seconda stringa è MAGGIORE della seconda, restituisce un valore maggiore di 0, di solito + 1.
Che cosa vuol dire lessicograficamente parlando? Bene o male, è una specie di conto alfabetico, provate un po' per vedere che cosa voglia significare.
Ai nostri fini, serve solo verificare che la terza stringa sia uguale a cellul, e in quel caso aumentare il contatore di numero di chiamate a cell.
Tutto ciò lo si ottiene con
valore = strcmp(tipo, "cellul"); if (valore == 0) chiamate_cell ++; else chiamate_fisso++;
dove int valore l'ho dichiarata appositamente allo scopo.
(:title Laboratorio C:)
Qui ci sono le soluzioni agli esercizi dell'ultima lezione, con tanto di commento.
Esercizio 1
Data la traccia sotto riportata completare il codice in modo di aumentare di 1 tutti gli interi pari e diminuire di 1 tutti quelli dispari nell'array vettore[] di dimensione dim. Riportare come risultato il numero che comparira' a monitor. Per esempio un vettore che contiene gli elementi {4,56,3,78,23} dopo essere stato aggiornato deve contenere gli elementi {5,57,2,79,22}.
Aumenta interi pari #include <stdio.h> float CalcolaRisultato(int vettore[], int dim); int main() { int vettore[] = {4,56,3,78,23} ; int dim = 5; int conto; float risultato; //Se il tuo programma funziona correttamente, dovresti ottenere: 2573 for (conto = 0; conto < dim; conto ++) { if ((vettore[conto] % 2) == 0) vettore[conto] ++; else vettore[conto] --; } risultato = CalcolaRisultato(vettore, dim); printf("\nrisultato da copiare ed incollare = %d \n\n" , (int) risultato ); getchar(); exit(0); } // main float CalcolaRisultato(int vettore[], int dim) { int i; float divisore, dividendo=0; for(i=0;i < dim; i++) { dividendo += i * vettore[i]; } divisore = (dim +1)*dim/2; return 100*dividendo/divisore; }
NOTE SULL'ESERCIZIO
Innanzitutto, l'esercizio ti dava un vettore di 462 elementi, mentre qui il vettore ne ha solamente 5.
Il cuore dell'esercizio sta nella sequenza
for (conto = 0; conto < dim; conto ++) { if ((vettore[conto] % 2) == 0) vettore[conto] ++; else vettore[conto] --; }
che vuol dire esattamente questo:
for (conto = 0; conto < dim; conto ++)
esamina il vettore dal primo all'ultimo elemento, ricordando che dim = numero elementi del vettore.
if ((vettore[conto] % 2) == 0) vettore[conto] ++; else vettore[conto] --;
If ((vettore[conto] % 2) == 0) controlla se l'elemento conto-esimo del vettore è pari, cioè se il resto della divisione intera per due è 0.
In caso positivo, esegue la riga vettore[conto] ++, come da specifica; in caso contrario invece viene diminuito con vettore[conto] --, sempre come da specifica.