Sqrt
Project setup
Per iniziare andiamo a stabilire lo scheletro applicativo utile. In questo caso la scelta è quella di sviluppare una libreria, e non un programma. Vogliamo una libreria perché vogliamo offrire ad altri programmi l'abilità di utilizzare il nostro square root.
Possiamo quindi impostare la seguente struttura al progetto
Makefile // per compilare
src/sqrt.h // contiene i prototipi
src/sqrt.c // contiene le funzioni, senza main()
src/main.c // il programma con il main()
Prime funzioni
Per iniziare andiamo ad implementare nella nostra libreria tre funzioni matematiche elementari che saranno poi necessarie per l'algoritmo finale. Queste funzioni sono le seguenti:
-
absolute value
Dato un numero \(x\) la funzione \(\texttt{absolute}(x)\) ritorna sempre il valore positivo, a prescindere dal segno iniziale.
-
square
Dato un numero \(x\) la funzione \(\texttt{square}(x)\) ritorna il quadrato del numero.
-
average
Dati due numeri \(x, y\) la funzione \(\texttt{average(x, y)}\) ritorna la media tra i due numeri.
L'obiettivo sarà implementare queste funzioni. Nel file sqrt.h
mettiamo i prototipi, mentre nel file sqrt.c mettiamo le
implementazioni. Possiamo utilizzare il tipo double per lavorare con
i numeri con la virgola.
Nello specifico abbiamo i seguenti prototipi da rispettare
double absolute(double x);
double square(double x);
double average(double x, double y);
Un primo main
Per iniziare implementiamo in main.c una semplice logica che legge
un numero e lo ristampa nel terminale. A tale fine possiamo utilizzare
la funzione scanf per leggere, e printf per stampare. Nello
specifico è necessario utilizzare queste format strings
scanf("%lf", &x); // per leggere
printf("%.6f\n", x); // per scrivere
È di particolare importanza la sintassi %.6f in quanto viene
utilizzata per fissare la precisione con cui lavoriamo: 6 cifre
decimali. Questo vale per tutto il progetto e sarà il formato
utilizzato durante i test.
Non tutto quello che arriva sullo standard input però è un numero. La
funzione scanf ritorna quanti valori è riuscita a leggere: su una
riga come ciao non ne legge nessuno e ritorna 0, lasciando x
senza un valore. Il risultato di scanf va quindi sempre controllato.
Quando l'input non è un numero il programma deve segnalarlo sullo
standard error e comunicarlo all'ambiente che lo ha lanciato
attraverso il codice di uscita, ovvero il valore ritornato da
main: 1 quando l'input non è valido, 0 quando è andato tutto
bene. È questo il numero che la shell, un Makefile o i test leggono
per capire se il programma ha funzionato.
if (scanf("%lf", &x) != 1) {
fprintf(stderr, "input non valido\n");
return 1;
}
Makefile
L'obiettivo del Makefile sarà produrre il binario finale. Nello specifico il make deve supportare i seguenti target:
-
alldeve compilare
src/sqrt.cesrc/main.ce produrre il programma./sqrt. -
cleanelimina il binario prodotto dalla compilazione. Deve funzionare anche quando il binario non è presente.
Da notare che la compilazione deve rispettare i seguenti flags
-Wall -Wextra -Werror -pedantic -std=c99
Risultato
Alla fine dobbiamo ottenere la seguente situazione
$ make
gcc -Wall -Wextra -Werror -pedantic -std=c99 -ggdb src/sqrt.c src/main.c -o sqrt
$ echo 2 | ./sqrt
2.000000
$ echo $?
0
$ echo ciao | ./sqrt
input non valido
$ echo $?
1
Inizia il progetto per avere un repository e poter consegnare gli step. Quello che leggi qui sopra è la versione per C: il linguaggio si sceglie iniziando il progetto.