Realizziamo oggi un semplice programma sulla terna pitagorica utilizzando Scratch.
Il termine deriva da Pitagora. Infatti la terna pitagorica è l’aspetto aritmetico, del ben noto teorema geometrico di Pitagora, di cui ricordiamo l’enunciato:
In ogni triangolo rettangolo il quadrato costruito sull’ipotenusa è equivalente alla somma dei quadrati costruiti sui cateti.
Quindi, dal punto di vista aritmetico, se tre numeri interi a, b e c verificano la relazione a2 + b2 = c2, allora si dice che formano una terna pitagorica.
Esistono dunque infinite terne con numeri interi che soddisfano questa condizione, come ad esempio: 3, 4 e 5 oppure 5, 12 e 13 e così via.
Terna pitagorica con Scratch
Si realizzi dunque un programma che legga in input tre valori (a, b e c) e determini se questi numeri possono formare una terna pitagorica, utilizzando la programmazione a blocchi con Scratch.
Innanzitutto scegliamo uno sfondo e uno sprite qualunque.
Dopo creiamo tre variabili: a, b e c.
Chiediamo di inserire il primo cateto (a), dopo il secondo cateto (b) ed infine l’ipotenusa (c).
Quindi verifichiamo che la proprietà descritta sopra sia soddisfatta.
Ecco quindi il codice completo:
In questo modo verifichiamo che il triangolo è rettangolo dal punto di vista geometrico e che i tre numeri formano una terna pitagorica dal punto di vista aritmetico.
Bene, ma se non volessimo dare importanza all’ordine di inserimento dei dati?
In questo caso allora occorre, prima di applicare la formula, calcolare il valore massimo tra i tre valori inseriti in input.
Quindi controlliamo innanzitutto se b è maggiore di a e se è vero allora:
– controllo se b è maggiore di c e:
– se vero allora si deve verificare che: a2 + c2= b2;
– se invece è falso si deve verificare che: a2 + b2 = c2.
– invece se b maggiore di a è falso allora controllo se a è maggiore di c:
– se vero allora si deve verificare che: c2 + b2= a2;
– se falso invece si deve verificare che: a2 + b2 = c2.
Ecco dunque la seconda soluzione dell’algoritmo sulla terna pitagorica con scratch.
Chiaramente la soluzione proposta è solo uno dei possibili metodi per realizzare l’algoritmo sulla terna pitagorica con Scratch.
La funzione ftell in C consente di restituire la posizione corrente del file pointer rispetto all’inizio del file. La posizione corrente è espressa come numero di byte.
La sintassi della funzione ftell in C è dunque la seguente:
long ftell(FILE *fp)
La funzione ftell in C restituisce dunque un intero che è la posizione corrente del puntatore.
FILE *fp è, come nelle altre funzioni, il puntatore a FILE ottenuto dalla precedente chiamata fopen.
Esempio funzione ftell in C
Facciamo adesso un semplice esempio di programma che visualizza la dimensione di un file utilizzando le funzioni fseek ed ftell.
Supponiamo quindi di avere un file di testo di nome alunni.txt che contiene i nomi di alcuni alunni.
Quindi apriamo il file alunni.txt in lettura, con la funzione fopen, e calcoliamo semplicemente la dimensione di questo file utilizzando fseek per spostare il puntatore alla fine del file ed ftell per restituire la dimensione in byte del nostro file.
Ecco dunque il listato dell’esempio con l’uso di ftell in C:
#include <stdio.h>
#include <stdlib.h>
#define N 5
int main() {
FILE *fp;
long n;
if((fp=fopen("alunni.txt", "rt"))==NULL) {
printf("Errore nell'apertura del file'");
exit(1);
}
fseek(fp,0L,SEEK_END);
n=ftell(fp);
fclose(fp);
printf("Dimensione del file in byte: %ld\n", n);
return 0;
}
Sono svariati i casi in cui si può utilizzare la funzione ftell in C, infatti si potrebbe ad esempio voler conoscere la posizione di un valore massimo o di un determinato valore a seguito di una ricerca e così via. Nei tutorial che seguiranno vedremo ancora altri esempi d’uso.
La funzione fseekin C consente di muovere il puntatore di lettura e/o scrittura in una posizione qualunque all’interno del file, dopo la sua apertura con fopen.
Finora l’accesso al file è stato di tipo sequenziale, ovvero per aggiungere o leggere un elemento ci siamo posizionati esattamente sotto tutti gli elementi precedenti.
Infatti, molte volte c’è la necessità di realizzare un accesso diretto o random ad un elemento di un file. Ecco dunque che la funzione fseek ritorna molto utile a questo scopo.
La sintassi della funzione fseek in C è quindi la seguente:
int fseek(FILE *fp, long distanza, int partenza)
Dove fp è il file pointer, distanza indica di quanti byte il file pointer deve essere spostato mentre partenza indica da quale posizione deve essere spostato.
La funzione fseek ritorna 0 se lo spostamento è avvenuto con successo, altrimenti un valore diverso da 0.
Allora definiamo il punto di partenza che può assumere solo uno di questi tre valori:
SEEK_SET – inizio del file
SEEK_END – fine del file
SEEK_CUR – posizione corrente dell’indicatore
Esempio d’uso della funzione fseek in C
Realizziamo dunque lo stesso esempio di prima con rewind con la funzione fseek in C, solo a scopo didattico per capirne il funzionamento.
#include<stdlib.h>
#include<stdio.h>
#define N 100
int main() {
FILE *fp;
char buf[N];
if((fp=fopen("alunni.txt", "rt"))==NULL) {
printf("Errore nell'apertura del file'");
exit(1);
}
/* legge e stampa fino alla fine del file */
while(!feof(fp)) {
fgets(buf,N,fp);
printf("%s", buf);
}
/* riporta il file pointer all'inizio */
fseek(fp,0,SEEK_SET);
printf("\nStampo la seconda volta\n");
/* legge e stampa fino alla fine del file */
while(!feof(fp)) {
fgets(buf,N, fp);
printf("%s", buf);
}
printf("\nStampo la terza volta\n");
fseek(fp,0,SEEK_CUR);
/* legge e stampa fino dalla posizione corrente dell'indicatore che in questo caso è l'ultima riga*/
while(!feof(fp)) {
fgets(buf,N, fp);
printf("%s", buf);
}
fclose(fp);
return 0;
}
Le potenzialità della funzione fseek in C saranno trattate anche nelle prossime lezioni in maniera approfondita.
In questa lezione parleremo di rewind in C, cioè della funzione che permette di riposizionarsi nuovamente all’inizio di un file.
La sintassi della funzione rewind in C è dunque questa:
void rewind(FILE *fp);
Dove FILE *fp è il puntatore a FILE ottenuto dalla precedente chiamata fopen.
Esempio d’uso di rewind in C
Leggiamo un file riga per riga e quando arriviamo alla fine, chiamiamo la funzione rewind che effettuerà un secondo ciclo di lettura.
In definitiva stamperemo il contenuto del file due volte.
Supponiamo dunque che il file alunni.txt contenga i dati degli alunni, tipo nome, cognome e voto di una materia. Quindi con la funzione fopen apriamo questo file e controlliamo che non ci siano errori nell’operazione di apertura del file.
Leggiamo con la funzione fgets le stringhe fino alla fine del file e dopo riportiamo, con la funzione rewind, il puntatore all’inizio del file e ripetiamo l’operazione di lettura.
Ecco dunque il listato completo:
#include<stdlib.h>
#include<stdio.h>
#define N 100
int main() {
FILE *fp;
char buf[N];
if((fp=fopen("alunni.txt", "rt"))==NULL) {
printf("Errore nell'apertura del file'");
exit(1);
}
/* legge e stampa fino alla fine del file */
while(!feof(fp)) {
fgets(buf,N,fp);
printf("%s", buf);
}
/* riporta il file pointer all'inizio */
rewind(fp);
printf("\nStampo la seconda volta\n");
/* legge e stampa fino alla fine del file */
while(!feof(fp)) {
fgets(buf,N, fp);
printf("%s", buf);
}
fclose(fp);
return 0;
}
Chiaramente questo è solo un esempio d’uso della funzione rewind in C, prossimamente vedremo altri esempi.
Proponiamo ancora degli esercizi sui file in C ed in particolare sulle funzioni fopen, fwrite, fread e fclose.
Propongo questo esempio a scopo di introdurre, prossimamente, altre funzioni che ci permetteranno di posizionarci in una posizione qualunque del file e che quindi garantiscono un accesso diretto e non più sequenziale.
Esercizi sui file in C – problema
In un file binario sono memorizzati i dati di un vettore che contiene al massimo 50 elementi. Stampare i dati di questo file, se presenti, altrimenti dare come messaggio: “Nessun dato presente!”. Dopo chiedere quanti dati si vogliono aggiungere al vettore e creare una funzione che consenta di farlo. Creare un’altra funzione per il salvataggio di questi dati nel vettore. Infine ristampare nuovamente i dati del file aggiornati con il nuovo inserimento.
Le funzioni/procedure utilizzate sono dunque 4. Notate come la funzione init deve restituire un intero che corrisponde al numero di elementi che vengono inseriti nel vettore. Mentre le altre procedure non ritornano alcun valore.
Quindi la funzione init ha il compito di aprire in lettura il file binario, utilizzando fopen, e se l’operazione ha successo legge gli elementi in esso presenti utilizzando la funzione fread. Se non ci sono dati verrà stampato un messaggio: Nessun dato presente! Dopo chiudiamo il file binario con la funzione fclose.
La procedura print stampa semplicemente i dati presenti senza restituire alcun valore. Prende come parametri il vettore e il numero degli elementi.
La procedura add ha il compito di aggiungere gli elementi e quindi ha la necessità di prendere come parametri non solo il vettore ma anche il puntatore all’ultimo elemento inserito. Quindi chiediamo quanti elementi inserire e li aggiungiamo a quelli precedenti. Potremmo fare anche un controllo per far in modo che non si inseriscano più elementi rispetto alla dimensione massima dichiarata, che in questo caso è 50.
Infine la procedura save si occupa di salvare i dati inseriti nel file.
Ecco dunque il listato completo:
#include <stdio.h>
#define N 50
int init(int*V);
void print(int *V,int n);
void add(int *V,int *pn);
void save(int *V,int n);
void main(){
int a[N],i,n;
n=init(a);
print(a,n);
add(a,&n);
save(a,n);
printf("Ristampo i dati contenuti nel file con l'aggiunta");
print(a,n);
}
int init(int *V){
FILE *pf;
int i=0;
pf=fopen("vettori.dat","rb");
if(pf)
while(fread(&V[i],sizeof(int),1,pf)>0 && i<N)
i++;
else
printf("Nessun dato presente!");
fclose(pf);
return i;
}
void print(int *V, int n){
int i;
printf("\nElementi totali presenti: %d\n", n);
for(i=0;i<n;i++)
printf("%d\n", V[i]);
}
void add(int *V,int *pos){
int x,i;
printf("Elementi da aggiungere (max %d): ", N-*pos);
scanf("%d",&x);
for(i=*pos;i<*pos+x;i++){
printf("Numero %d: ", i+1);
scanf("%d",&V[i]);
};
*pos+=x;
}
void save(int *V,int n){
FILE *pf;
pf=fopen("vettori.dat","wb");
if(pf)
fwrite(V,sizeof(int),n,pf);
else
printf("Errore in scrittura\n");
}
Questi sono solo alcuni degli esercizi sui file in C che vi propongo in questo semplice tutorial.