
In molti percorsi universitari il linguaggio C è il primo e più importante linguaggio di programmazione da studiare e conoscere. Per questo motivo ho ritenuto interessante riesumare i miei vecchi appunti universitari di programmazione.
Il primo programma permette la stampa a video del valore ottale di qualsiasi carattere introdotto da tastiera. Poiche' si possono stampare anche caratteri speciali (es. \n), se il numero di caratteri introdotto e' < NCAR, per terminare si deve usare il carattere ^Z (fine file) seguito da <INVIO>. Questi ultimi 2 caratteri non vengono visualizzati in ottale:
#include <stdio.h>
#define NCAR 10
main()
{
int i;
int ncar; /* numero di caratteri effettivamente letti */
int c; /* carattere corrente in lettura */
unsigned char s[NCAR+1]; /* stringa da convertire */
printf("Visualizzazione del codice ottale dei caratteri ASCII\n");
printf("Introduci i caratteri (max. %d) seguiti da ^Z e <INVIO>: ", NCAR);
for (i = 0; i < NCAR && (c = getchar()) != EOF; i++)
s[i] = c;
ncar = i;
printf("\nValori ottali: ");
for (i = 0; i < ncar; i++)
printf("%03o ", s[i]);
printf("\n");
return 0;
}
******
Un altro programma molto semplice converte una temperatura introdotta da tastiera da gradi Fahrenheit a gradi Celsius o viceversa :
#include <stdio.h>
#define toupper(c) ((c) >= 'a' && (c) <= 'z') ? \
(c) - ('a' -'A') : c
main()
{
char risp, c[2];
float fahr, cels;
for (;;) /* loop infinito; si puo' usare anche "while (1)" */
{ printf ("Tipo di conversione (C = C->F , F = F->C, E = Esci : ");
scanf("%1s",&c); /* legge una stringa di un solo carattere */
fflush(stdin);
if ((risp = toupper(c[0])) == 'E')
return 0;
if (risp == 'C' || risp == 'F')
{ printf ("Temperatura : ");
if (risp == 'C')
{ scanf("%f",&cels); /* legge la temperatura Celsius */
fflush(stdin);
printf("%20.2f C sono pari a %.2f F\n\n", cels, 1.8*cels+32.);
}
else
{ scanf("%f",&fahr); /* legge la temperatura Fahrenheit */
fflush(stdin);
printf("%20.2f F sono pari a %.2f C\n\n", fahr, (fahr-32.)/1.8);
}
}
else
printf("Carattere non riconosciuto\n\n");
}
}
Utilizzando la funzione getchar() per l'input di un solo carattere si avrebbero dei problemi dovuti al fatto che l'elaborazione procede solo dopo la lettura del carattere <INVIO>. A questo punto la successiva chiamata di getchar() elaborerebbe il carattere <INVIO> Si potrebbe utilizzare la funzione getche() che richiede <conio.h> ma tale funzione non sarebbe standard ANSI.
La funzione fflush() serve a ripulire il buffer di ingresso nel caso che fossero stati introdotti piu' di un carattere.
******
Un altro programma classico della programmazione in linguaggio C e quello di costruire e stampare a video una matrice unitaria intera di ordine n utilizzando
la caratteristica di troncamento della divisione tra interi.
Questa versione realizza i cicli mediante l'istruzione "while" .
#include <stdio.h>
#define ORD 6 /* ordine della matrice */
main()
{
int i, j, a[ORD][ORD];
i = 1;
printf("\n");
while (i <= ORD)
{ j = 1;
while (j <= ORD)
{ a[i-1][j-1] = (i/j) * (j/i); /* calcolo dell'elemento i-1,j-1 */
printf("%5d%c", a[i-1][j-1], (j == ORD) ? '\n': ' ');
/* stampa dell'elemento i-1,j-1 */
j++;
}
i++;
}
return 0;
}
******
Calcola l'intersezione di due rette. Le rette sono assegnate mediante i loro coefficienti a, b e c nella forma: ax + by + c = 0
#include <stdio.h>
main()
{
int i;
float a1, b1, c1;
float a2, b2, c2;
float determ, x0, y0;
printf("Intersezione di due rette date nella forma: ax + by + c = 0\n");
printf("Fornisci i coefficienti a1, b1 e c1 della prima retta: ");
if ((i = scanf("%f%f%f", &a1, &b1, &c1)) == EOF)
return 0;
else if (i != 3)
{ printf("Errore nel formato dei dati\n");
return 1;
}
if (a1 == 0 && b1 == 0)
{ printf("I coefficienti a1 e b1 non possono essere entrambi nulli!\n");
return 2;
}
printf("Fornisci i coefficienti a2, b2 e c2 della seconda retta: ");
if ((i = scanf("%f%f%f", &a2, &b2, &c2)) == EOF)
return 0;
else if (i != 3)
{ printf("Errore nel formato dei dati\n");
return 3;
}
if (a2 == 0 && b2 == 0)
{ printf("I coefficienti a2 e b2 non possono essere entrambi nulli!\n");
return 4;
}
determ = a1*b2 - a2*b1; /* calcola il determinante */
if (determ == 0.)
printf("Le due rette non si incontrano perche' sono parallele\n");
else
{ x0 = (b1*c2 - b2*c1) / determ;
y0 = (a2*c1 - a1*c2) / determ;
printf("Le due rette si incontrano nel punto: "
"x = %.3f y = %.3f\n", x0, y0);
}
return 0;
}
L’ultimo è più interessante riguarda l’integrazione di una funzione seno tramite il metodo Montecarlo. Invito i più volenterosi a completare l’argomento sul metodo Montecarlo perché spessa si ritrova nelle riviste informatiche.
Questo programma esegue l'integrazione numerica della funzione sin(x) tra 0 e pigreco utilizzando il metodo Montecarlo con un numero di punti assegnato.
L'applicazione in oggetto ha solo carattere dimostrativo in quanto in questo caso il metodo Montecarlo ha un costo in termini di tempo molto superiore ai metodi classici e non garantisce un'elevata precisione.
Il metodo consiste nel circoscrivere l'area da integrare in un rettangolo e nell'estrarre coppie di numeri casuali che rappresentano le coordinate di punti interni al rettangolo. L'area sara' data dal rapporto dei numeri dei punti che cadono internamente all'area da misurare e il totale dei punti generati moltiplicato per l'area del rettangolo.
La funzione rand(), inizializzata mediante la srand(), genera solo numeri
(pseudo)casuali con distribuzione uniforme nell'intervallo [0,32767].
Questo intervallo viene modificato mediante una trasformazione lineare
in modo da adattarsi agli intervalli in cui variano ascisse ed ordinate.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main()
{
unsigned int seed; /* seme per iniziare la sequenza casuale */
long int i, np; /* np = numero di punti */
double in; /* contatori dei punti interni all'area */
double a, b, min, max; /* coordinate del rettangolo */
double x, y; /* coordinate del punto corrente */
double integ; /* risultato del calcolo */
printf("Esegue l'integrale di sin(x) per intervalli interni a [0,%c]\n",
'\343');
printf("Intervallo di integrazione: limite inferiore : ");
if (scanf("%lf", &a) != 1) return 0;
printf(" limite superiore : ");
if (scanf("%lf", &b) != 1) return 0;
/* Controlli sui limiti, M_PI = valore di pigreco definito in math.h */
if (a < 0 || a > M_PI || b > M_PI || b <= a)
{ printf("\nErrore nei limiti di integrazione\n");
return 0;
}
for (;;)
{ printf("Numero dei punti da generare e seme iniziale (^Z = Fine) : ");
if (scanf("%ld %u", &np, &seed) != 2) break;
if (np <= 0) break;
srand(seed); /* inizializzazione di rand() */
in = 0.; /* inizializzazione del contatore */
min = 0.; /* minimo di sin(x) per 0 <= x <= pigreco */
max = 1.; /* massimo di sin(x) per 0 <= x <= pigreco */
for (i = 0; i < np; i++)
{
/* trasformazioni lineari dell'intervallo standard */
x = a + (b - a) * rand() / 32767.;
y = min + (max - min) * rand() / 32767.;
if (y <= sin(x)) /* i punti sulla curva si assumono interni */
in++;
}
integ = (b - a) * (max - min) * in / np;
printf("No. punti : %6ld Integrale : %8.6f\n", np, integ);
}
return 0;
}
/code]
Tutti questi programmi derivano dai miei appunti di informatica di base corso del Politecnico di Torino del 2001.