Corso di ingegneria elettronica: Fondamenti di informatica
Il linguaggio "C": Espressioni
Espressione concatenata: expr1, expr2 produce i side effect di expr1 e successivamente quelli di expr2, infine restituisce il valore di expr1 nel tipo di expr1.
Espressione ternaria: expr1 ? expr2 : expr3 valuta expr1 e produce i suoi side effects. Se il risultato è vero allora esegue expr2, altrimenti esegue expr3. Il valore e il tipo restituiti sono quelli di expr2 nel caso positivo e expr3 nel caso negativo.
Cast: type_expr expr1 produce i side effects di expr1 e restituisce il valore restituito da expr1, che viene però convertito al tipo di type_expr (es: int a = b + 2).
Puntatori
I puntatori sono variabili il cui valore è l'indirizzo di memoria di un'altra variabile (o puntatore). Le operazioni sono diverse dall'aritmetica classica. Somma e sottrazione avvengono in base al numero di byte di ogni indirizzo. Se i byte sono 4 allora, se ptr = 100, ptr + 1 = 104. In generale, l'incremento dell'indice di un puntatore è esprimibile come: x_ptr + 2 = x_ptr + 2 * (sizeof(typedecl)) con typedecl = tipo delle variabili.
Sui puntatori è definita l'operazione che consente al puntatore di referenziare la variabile stessa, è però necessario conoscere il tipo di tale variabile (Se il tipo non è noto, il puntatore può essere riferito a void e va bene sempre). Ciò avviene grazie al modificatore prefisso al tipo della variabile ricercata.
Es: x_ptr Referenzia un indirizzo. Con l'espressione x_ptr = &x il puntatore assume il valore dell'indirizzo della variabile int x. *(int*)x_ptr è un puntatore a intero che può modificare direttamente il valore della variabile x. Con l'espressione *(int*)x_ptr = 2 assegno il valore 2 alla variabile x.
Esiste anche la possibilità di creare la variabile puntatore a puntatore a variabile: x_ptr = &x; x_ptr_ptr = &x_ptr è un puntatore che punta alla locazione di memoria in cui è localizzato il puntatore x_ptr che punta alla locazione di memoria di x. **x_ptr_ptr = 4 assegna il valore 4 alla variabile x.
Arrays
Un array è un insieme di variabili dello stesso tipo che possono essere referenziate tramite un nome collettivo e un indice che le distingue fra loro. Consiste in una sequenza di locazioni contigue in memoria. Può essere formato sia da variabili che da puntatori. La dichiarazione è: <typedecl><decl>[<const>] ed è formata da un tipo, il nome e il numero di elementi: float X[200] "X" è un array di 200 variabili di tipo float. float *X[200] "X" è un array di 200 puntatori a float.
Ogni elemento è referibile in due modi: Referenziando l'elemento con l'indice: X[0] è il primo elemento dell'array X. Referenziando l'indirizzo a cui si trova un elemento (uso del puntatore: ptr = x ptr punta la prima locazione dell'array; ptr[0] = 2 assegna 2 alla prima locazione dell'array. (ptr + 1)[0] = 2 assegna 2 alla seconda variabile dell'array. (ptr + 1)[1] = 2 assegna 2 alla terza variabile dell'array.
Funzioni in linguaggio “C”
Esempio:
#include <stdio.h>
int square(int); // dichiarazione di funzione
int main () { // → il vuoto fra parentesi sta per void e significa che la funzione non restituisce output
int x;
for (x = 1; x <= 10; x++)
printf("...");
return 0;
}
int square(int y) {
return y * y;
} // definizione della funzione square
Dichiarazione
Si deve specificare: il nome della funzione per permetterne l'utilizzo. Gli argomenti (o parametri) della funzione, dichiarandone la quantità e il tipo. Il tipo del valore in uscita.
Esempio: funzione che calcola il massimo fra due valori, avremo quindi: Il nome “max”, 2 argomenti di tipo int, e un solo valore in uscita di tipo int. Dichiarazione → int max(int, int) // Si può specificare la variabile per chiarezza ma sarà comunque ignorata dal compilatore.
Definizione
Comprende due parti fondamentali:
Intestazione: Si devono rendere espliciti i due parametri fondamentali. Sempre sull'esempio precedente nell'intestazione si avrà: int max(int a, int b). Se non si specifica il tipo viene considerato int.
Corpo della funzione: è l'insieme delle espressioni che caratterizza la funzione e ne definisce le operazioni tramite le quali i valori in ingresso producono il valore in uscita. In ogni funzione non è possibile usare i parametri attuali dichiarati in main ma devono essere usate delle variabili diverse, denominate parametri formali.
Esempio di definizione: trovare il maggiore fra tre numeri float
#include <stdio.h>
float max(float, float, float); // Dichiarazione della funzione “max”
float main() {
float a, b, c; // dichiarazione dei tre numeri di cui si calcola il maggiore
printf("...");
scanf("%f%f%f", &a, &b, &c);
float maximum(float x, float y, float z) { // si inserisce la funzione maximum.
float max = x;
if (y > max) max = y; // x, y, z assumono i valori che nella main sono stati acquisiti da tastiera
if (z > max) max = z; // sotto il nome di a, b, c.
return max;
}
printf("Il massimo fra i tre numeri è %f", maximum(a, b, c));
} // chiamata di funzione “maximum”
Chiamata di funzione (attivazione)
La funzione viene attivata (o chiamata) quando viene nominata nella funzione principale “main”.
Esempio:
main() {
int x;
int y;
int max;
x = 3;
y = 4;
int maximum(int a, int b) {
max = maximum(x, y); // → La funzione “maximum” viene eseguita quando viene menzionata in “main”.
}
// Quando la funzione “maximum” termina, il controllo viene restituito a “main”.
}
Per essere eseguita la funzione deve essere dichiarata prima dell'inizio di “main” e definita prima della chiamata.
Creazione stack (l.i.f.o.) tramite funzioni
- Si include le librerie stdio e stdlib, si definisce il tipo booleano e la costante per il dimensionamento del buffer (#define N 20);
- Si dichiarano tutte le funzioni necessarie per il programma:
- int main(void); è la funzione principale che non riceve dati e restituisce un intero.
- void init(int*TOS_ptr); è la funzione di inizializzazione del TOS a 0: TOS_ptr è un puntatore a intero e con int*TOS_ptr ci si riferisce alla variabile TOS (top of stack) che è la variabile che determina il numero di valori del buffer. Se è < N accetta valori, altrimenti li rifiuta.
Void init(int*TOS_ptr) // Definizione di init
{
*TOS_ptr = 0; // inizializza a zero il TOS
}
- Boolean push(float*buffer, int*TOS_ptr, float value) è la funzione che caratterizza la funzione push della politica l.i.f.o. Se il buffer non è pieno (int*TOS_ptr < N) inserisce il valore "value" e restituisce TRUE, altrimenti non inserisce alcun valore e restituisce FALSE. Riceve in entrata il puntatore "buffer" a float, il puntatore "TOS_ptr" a intero e il valore float "value".
Boolean push(float* buffer, int* TOS_ptr, float value) {
if (*TOS_ptr < N) {
buffer[*TOS_ptr] = value;
(*TOS_ptr)++;
return TRUE;
} else {
return FALSE;
}
}
- Boolean pop(float*buffer, int*TOS_ptr, float*value_ptr) è la funzione che caratterizza l'estrazione di un valore dallo stack secondo la politica l.i.f.o. Se il buffer non è vuoto (*TOS_ptr > 0) estrae un valore e lo mette in *value_ptr e restituisce TRUE, se è vuoto restituisce FALSE.
Boolean pop(float* buffer, int* TOS_ptr, float* value_ptr) {
if (*TOS_ptr > 0) {
(*TOS_ptr)--;
*value_ptr = buffer[*TOS_ptr];
return TRUE;
} else {
return FALSE;
}
}
- void get_value(float* value_ptr) è la funzione che chiede l'inserimento di un valore da tastiera per essere inserito nello stack. Riceve float*value_ptr che è puntatore a una variabile float.
void get_value(float* value_ptr) {
printf("Insert a value ");
fflush(stdout);
scanf("%f", value_ptr);
getchar();
}
- void put_value(float value) è la funzione che stampa a video il valore che è stato estratto dallo stack. Riceve in entrata un valore float, quello che è stato estratto e deve essere stampato a video.
void put_value(float value) {
printf("The extracted value is: %f\n", value);
fflush(stdout);
}
- void notify_push_failure(void) è la funzione che notifica l'errore di un'immissione di valore.
void notify_push_failure(void) {
printf("Buffer full! Insertion cancelled.\n");
fflush(stdout);
} // accade quando il buffer è pieno.
- void notify_pop_failure(void) è la funzione che notifica il fallimento di un'estrazione.
void notify_pop_failure(void) {
printf("Buffer empty! Extraction impossible.\n");
fflush(stdout);
} // accade solo quando il buffer è vuoto.
- void notify_selection_failure(char selection) notifica un errore di inserimento di valore. Accade solo quando la funzione riceve un char da tastiera, per questo in ingresso presenta la variabile char denominata "selection".
void notify_selection_failure(char selection) {
printf("%c is not a legal selection.\n", selection);
fflush(stdout);
}
int main(void) {
// TOS rappresenta l'indice della prima locazione libera.
int TOS;
float* buffer = (float*)malloc(N * sizeof(float));
char selection;
float value;
Boolean exit_required;
Boolean result;
init(&TOS);
do {
printf("Insert i or I (push), o or O (pop), x or X (exit) >");
fflush(stdout);
exit_required = FALSE;
selection = getchar();
getchar();
switch (selection) {
case 'i':
case 'I':
get_value(&value);
result = push(buffer, &TOS, value);
if (result == FALSE)
notify_push_failure();
break;
case 'o':
case 'O':
result = pop(buffer, &TOS, &value);
if (result == TRUE)
put_value(value);
else
notify_pop_failure();
break;
case 'x':
case 'X':
exit_required = TRUE;
break;
default:
notify_selection_failure(selection);
break;
}
} while (exit_required == FALSE);
return 0;
}
Tipi strutturati
Un tipo strutturato è un insieme di variabili di diverso tipo, che possono essere referenziate attraverso un nome collettivo o un indice simbolico, ma è anche possibile dare un nome alle singole variabili. È molto utile per memorizzare dei dati connessi logicamente ma di diverso tipo.
Esistono tre tipi di dato strutturato: ARRAY (o vettore), STRUCT (o record), e RECORD VARIANTI (o union). Adesso trattiamo i DATI STRUTTURATI (record).
Definizione
Le variabili possono essere posizionate a distanza non regolare e per essere referenziate necessitano di una definizione di tipo del dato specifico a cui appartengono. Tale Definizione è data da “struct”, che costituisce una nuova categoria sintattica (<struct_def>).
Es: struct stack { ... } // è la definizione del dato strutturato di cui definiamo gli argomenti.
Dichiarazione
Le variabili del dato strutturato vengono dichiarate come una variabile normale, devono solamente essere contenute nelle parentesi graffe dello struct:
-
Riassunto esame Fondamenti di informatica, Prof. Bilotta Stefano, libro consigliato Fondamenti di programmazione. L…
-
Riassunto esame Informatica, prof. Carnevali, libro consigliato Fondamenti di Programmazione, Vicario: teoria
-
Riassunto esame Fondamenti di Informatica, prof. Dragoni, libro consigliato Fondamenti di Programmazione in C++ di …
-
Riassunto esame Fondamenti di Informatica, prof. Sernani, libro consigliato Fondamenti di programmazione in C++, Ag…