#define MAX_LENGTH 20
int main() {
char parola1[MAX_LENGTH], parola2[MAX_LENGTH];
printf("Inserire due parole:\n");
scanf("%s %s", parola1, parola2);
int res = strncmp(parola1, parola2, MAX_LENGTH - 1);
if(res == 0) printf("Le due parola sono identiche!\n");
else {
printf("L'ordine alfabetico delle due parole è: ");
if(res < 0) printf("%s %s\n", parola1, parola2);
else printf("%s %s\n", parola2, parola1);
}
return 0;
}
```
```text
$ ./es_strcmp
Inserire due parole:
alfiere alfabeto
L'ordine alfabetico delle due parole è: alfabeto alfiere
```
---
# Lettura di stringhe da file: `fgetc`
* `int fgetc(FILE *stream)` legge un carattere alla volta da `stream`
```C [|2-9|11-14]
// definizione di main e variabili, apertura del file (che va chiuso alla fine)
while((c = fgetc(input)) != EOF) {
if(c != '\n') parole[n_parole][i++] = c;
else {
parole[n_parole][i] = '\0';
n_parole++;
i = 0;
}
}
printf("Ho trovato le seguenti %d parole:\n", n_parole);
for(i = 0; i < n_parole; i++) {
printf("%s\n", parole[i]);
}
```
```text
Ho trovato le seguenti 6 parole:
prova
ciao
mondo
parole
aula
sedia
```
---
# Lettura di stringhe da file: `fgets`
* `char *fgets(char *str, int num, FILE *stream)` legge al più `num` caratteri di una riga e li mette in `str`
* `fgets` restituisce `str` se è stato letto almeno un carattere, `NULL` altrimenti
```C [|2-5|7-10]
// definizione di main e variabili, apertura del file (che va chiuso alla fine)
while(fgets(parole[n_parole], MAX_LENGTH - 1, input) != NULL) {
n_parole++;
}
fclose(input);
printf("Ho trovato le seguenti %d parole:\n", n_parole);
for(i = 0; i < n_parole; i++) {
printf("%s", parole[i]); // fgets lascia il '\n' nella stringa
}
```
```text
Ho trovato le seguenti 6 parole:
prova
ciao
mondo
parole
aula
sedia
```
---
# Altre funzioni che possono essere utili
-
int fputs(const char *str, FILE *stream)
scrive str
su stream
-
char *strtok(char *str, const char *delimiters)
divide str
in token separati dai caratteri contenuti in delimiters
-
const char *strstr(const char *str1, const char *str2)
cerca str2
in str1
e restituisce un puntatore alla prima porzione di str1
uguale str2
-
const char *strpbrk(const char *str1, const char *str2)
restituisce un puntatore al primo carattere di str1
uguale a uno dei caratteri presenti in str2
-
sprintf(char *str, ...)
permette di scrivere su una stringa
```C
char filename[100];
int N = 100;
sprintf(filename, "dati_%d.dat", N);
printf("%s\n", filename); // stampa "dati_100.dat"
```
Lavorare con le stringhe non è mai facile, ma in C è particolarmente difficile!
---
# Integrazione numerica
Teorema fondamentale del calcolo integrale
$$
\int_a^b f(x) dx = F(b) - F(a)
$$
dove $F(x)$ è detta funzione primitiva
Che facciamo se $f(x)$ non ha un'espressione analitica o $F(x)$ non è nota (esempio: una gaussiana?)
---
# Integrazione numerica - metodo dei rettangoli
- L'integrale può essere visto come l'area sotto la curva (stando attenti ai segni!)
- Dividiamo l'intervallo $[a, b]$ in $n$ intervalli di larghezza $\Delta x = (b - a) / n$
- L'area della curva si può approssimare con la somma dei rettangoli di altezza $f(x_i)$ e larghezza $\Delta x$:
$$
A \approx \Delta x (f(x_0) + f(x_1) + \ldots + f(x_{n-1})) = \sum_{i=0}^{n-1} f(x_i) \Delta x
$$
---
# Un integrale di prova
Consideriamo l'integrale definito di $f(x) = x^2 - \frac{3}{5} x^3$ nell'intervallo $[0, 2]$:
$$
\int_0^2 \left(x^2 - \frac{3}{5} x^3\right) dx = 0.2\bar{6}
$$
---
# Metodo dei rettangoli - implementazione
Il programma si aspetta una macro `N` definita al momento della compilazione
```C [|8,9|4,10|5,11|13]
#include
#include
void leggi_dati(double x[], double fx[]);
double calcola_area_rettangoli(double x[], double fx[], int N_points);
int main() {
double x[N], fx[N];
leggi_dati(x, fx);
double integrale = calcola_area_rettangoli(x, fx, N);
printf("%d %lf\n", N, integrale);
return 0;
}
// qui il corpo delle due funzioni, vedi prossima slide
```
---
# Metodo dei rettangoli - lettura dei dati
```C [|1|5-6|8-12|14-17]
void leggi_dati(double x[], double fx[]) {
int i;
char filename[100];
// il nome del file da aprire dipende dal valore di N
sprintf(filename, "poly_N%d.dat", N);
FILE *input = fopen(filename, "r");
if(input == NULL) {
fprintf(stderr, "Errore, il file %s non è leggibile\n", filename);
exit(1);
}
for(i = 0; i < N; i++) {
fscanf(input, "%lf %lf", x + i, fx + i); // usiamo l'aritmetica dei puntatori
}
fclose(input);
}
```
---
# Metodo dei rettangoli - calcolo dell'area
```C [|1|2-4|6-8|10]
double calcola_area_rettangoli(double x[], double fx[], int N_points) {
int i;
double area = 0.0;
double dx = x[1] - x[0];
for(i = 0; i < N_points - 1; i++) {
area += dx * fx[i];
}
return area;
}
```
```text [1-3|4-6]
$ gcc -o integrazione_rettangoli integrazione_rettangoli.c -DN=10
$ ./integrazione_rettangoli
10 0.342387
$ gcc -o integrazione_rettangoli integrazione_rettangoli.c -DN=10000
$ ./integrazione_rettangoli
10000 0.266747
```
---
# Integrazione numerica - metodo dei trapezi
- L'approssimazione con i rettangoli porta a un errore piuttosto grande, e quindi richiede un gran numero di punti per convergere al "valore vero"
- Facciamo meglio: approssimiamo l'area della curva con la somma delle aree dei trapezi
$$
A \approx \sum_{i=0}^{n-1} \frac{1}{2}(f(x_i) + f(x_{i+1})) \Delta x
$$
---
# Metodo dei trapezi - calcolo dell'area
```C [|7]
double calcola_area_trapezi(double x[], double fx[], int N_points) {
int i;
double area = 0.0;
double dx = x[1] - x[0];
for(i = 0; i < N_points - 1; i++) {
area += dx * (fx[i] + fx[i + 1]) / 2.0; // unica differenza!
}
return area;
}
```
```text [1-3|4-6]
$ gcc -o integrazione_rettangoli integrazione_rettangoli.c -DN=100
$ ./integrazione_rettangoli
100 0.274639
$ gcc -o integrazione_trapezi integrazione_trapezi.c -DN=100
$ ./integrazione_trapezi
100 0.266558
```
---
# Risultato dell'integrale in funzione di $N$
## Il metodo dei trapezi converge prima!
- Questi metodi si generalizzano ai casi in più dimensioni
- L'errore può essere ulteriormente ridotto (usando più di due punti, $\Delta x_i$, ecc)