Esercitazione 4: Tipi di dati del linguaggio C e - Cremona

Esercitazione n. 4
Tipi di dati
Puntatori
Queste slide sono distribuite con licenza Creative Commons
Attribuzione-Non commerciale-Condividi allo stesso modo 2.5 Italia
C/1: intersezione - Problema
Si vuole realizzare in linguaggio C lo stesso
programma già realizzato in linguaggio assembler
(un software che trovi gli elementi di intersezione
di due sequenze [non ordinate] di numeri interi
positivi e dove ogni sequenza è terminata dal
numero 0).
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
2
C/1: intersezione - Pseudocodice C
main()
{
\\ memorizza
\\ memorizza
\\ memorizza
\\ memorizza
il numero di
gli elementi
il numero di
gli elementi
elementi del primo insieme
del primo insieme nell'array ins1
elementi del secondo insieme
del primo insieme nell'array ins2
while (non ho finito di scandire ins1)
{
while (non ho finito di scandire ins2 e non ho già trovato
l'elemento corrente di ins1 in ins2)
{
if (elemento corrente di ins1 == elemento corrente di ins2)
{
\\ aggiungi l'elemento corrente all'array ins_int
\\ incrementa il contatore degli elementi di ins_int
}
}
}
}
\\ passa all'elemento successivo di ins2
\\ passa all'elemento successivo di ins1
\\ stampa gli elementi di ins_int
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
3
C/1: intersezione - Nuovi tipi di dati
Si introduce un tipo di dato strutturato:
➢
array: per rappresentare una sequenza di celle di memoria
consecutive e omogenee (cioè formata da elementi dello
stesso tipo semplice)
Es:
int lista[20]
identifica i 20 valori interi da lista[0] a lista[19]
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
4
C/1: intersezione - Codice sorgente /1
/* Dati 2 insiemi di numeri interi, il programma calcola
l'intersezione di questi due insiemi.
Gli insiemi sono memorizzati negli array 'ins1' e
'ins2', mentre l'insieme intersezione è contenuto
nell'array 'ins_int'.
Input: numero di elementi dell'insieme 1
elementi dell'insieme 1
numero di elementi dell'insieme 2
elementi dell'insieme 2
Output: elementi dell'insieme intersezione
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
5
C/1: intersezione - Codice sorgente /2
#include <stdio.h>
#define MAX_EL 100
typedef enum {false, true} bool;
main()
{
/* All'utente viene prima chiesto di inserire il numero di elementi
dell'insieme 1 (che non deve superare il numero massimo
consentito MAX_EL), e solo dopo di inserire gli elementi
dell'insieme.
Per leggere il numero degli elementi del primo insieme si usa un
ciclo while, che viene ripetuto finché l'utente non inserisce un
numero di elementi valido.
La variabile n_el1 (che contiene il numero di elementi del primo
insieme) viene inizializzata al valore MAX_EL+1, in modo che la
prima volta che il ciclo while viene eseguito la condizione sia
vera, per cui il ciclo venga eseguito almeno una volta.
*/
int ins1[MAX_EL], ins2[MAX_EL], ins_int[MAX_EL];
unsigned int i, j, k,
n_el1 = MAX_EL+1,
n_el2 = MAX_EL+1;
bool trovato;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
6
C/1: intersezione - Codice sorgente /3
while (n_el1 > MAX_EL) {
printf ("Inserisci il numero di elementi del primo insieme
(minore di %u): ", MAX_EL);
scanf ("%u", &n_el1);
}
for (i=0 ; i<n_el1 ; i++) {
printf ("Inserisci l'elemento numero %u di %u: ", i+1, n_el1);
scanf ("%d", &ins1[i]);
}
while (n_el2 > MAX_EL) {
printf ("Inserisci il numero di elementi del secondo insieme
(minore di %u): ", MAX_EL);
scanf ("%u", &n_el2);
}
for (i=0 ; i<n_el2 ; i++) {
printf ("Inserisci l'elemento numero %u di %u: ", i+1, n_el2);
scanf ("%d", &ins2[i]);
}
/* Come si nota, i pezzi di codice relativi alla lettura degli
elementi dei due array sono molto simili, cambiano solo per il
nome delle variabili coinvolte.
Si vedrà in seguito un metodo per 'fattorizzare' il codice
comune, e scriverlo una sola volta.
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
7
C/1: intersezione - Codice sorgente /4
/* Scorrere uno ad uno gli elementi del primo insieme, e
controllare se nell'insieme 2 c'è un elemento uguale.
Se si trova un elemento comune agli insiemi 1 e 2, lo
si inserisce nell'array 'ins_int'.
k è un contatore che indica quanti elementi sono stati
memorizzati nell'array 'ins_int'.
Una volta trovato un elemento comune tra ins1 ed ins2,
non serve più continuare la ricerca, per cui è possibile
uscire dal ciclo di scansione dell'insieme 2.
Quest'ultima condizione è rappresentata dal fatto che la
variabile (di tipo bool, definita dall'utente) sia
uguale a true.
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
8
C/1: intersezione - Codice sorgente /5
k = 0;
for (i=0 ; i<n_el1 ; i++) {
j = 0;
trovato = false;
/* Notare che in realtà esiste un modo per uscire dal ciclo
senza dover ricorrere al check di una variabile 'trovato',
e questo modo è tramite il 'break'. Questo è in effetti
pratica comune, però in questo modo (senza break) è
molto più chiara la condizione di uscita (ancora una
volta, il programma è più leggibile)
La condizione su 'trovato' si potrebbe anche scrivere, in
modo più compatto, come
while (j<n_el2 && !trovato)
e così in effetti assomiglia molto di più a una
formula logica
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
9
C/1: intersezione - Codice sorgente /6
while (j<n_el2 && trovato == false) {
if (ins1[i] == ins2[j]) {
ins_int[k] = ins1[i];
k++;
/* le due istruzioni precedenti possono, volendo, essere
compattate in una sola, sfruttando il significato del ++
ins_int[k++] = ins1[i];
*/
}
E' evidente sia la compattezza, sia la minor leggibilità
della seconda forma.
trovato = true;
}
j++;
/* In realtà il ciclo interno si può anche scrivere come:
for (j=0 ; j<n_el2 && trovato == false ; j++)
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
10
C/1: intersezione - Codice sorgente /7
/* anche qui, per uscire dal ciclo interno quando si è trovato un
elemento comune, si potrebbe, invece che ricorrere alla
variabile 'trovato', sfruttare il comando 'break'. Questo
comando, quando incontrato, fa uscire dal ciclo, per cui si
potrebbe scrivere il ciclo interno come:
while (j<n_el2) {
if (ins1[i] == ins2[j]) {
ins_int[k] = ins1[i];
k++;
break;
}
j++;
}
*/
peraltro, la scrittura con il 'break' è SCONSIGLIATA,
perchè rende più difficile capire quale è la condizione di
uscita dal ciclo (che non è più interamente contenuta
nella condizione dopo la parola chiave 'while').
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
11
C/1: intersezione - Codice sorgente /8
}
}
printf ("Sono stati trovati %u elementi comuni\n", k);
for (i=0 ; i<k ; i++) {
printf ("Elemento comune numero %u: %d\n", i, ins_int[i]);
}
/* Notare che se in ins1 c'è un elemento ripetuto (per esempio
3 volte) che è anche in ins2, questo elemento apparirà
in ins_int 3 volte, cioè tante volte quante esso compare
in ins1.
Se invece un elemento compare 1 sola volta in ins1 e, per esempio
5 volte in ins2, questo apparirà in ins_int una sola volta.
*/
Nota: da svolgere in autonomia
/*
*/
ESERCIZIO: provare a modificare questo programma
in modo che gli elementi ripetuti vengano scartati.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
12
C/2: battaglia navale - Problema
Si vuole realizzare in linguaggio C una semplice
simulazione del gioco classico della battaglia
navale.
Lo schema è prefissato, non cambia da partita a
partita...
I simboli usati sulla “griglia” sono:
'x'
'o'
'*'
'.'
=
=
=
=
elemento di una nave
"mancato"
"colpito"
casella sulla quale non è
stato effettuato nessun colpo
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
13
C/2: battaglia navale - Codice sorgente /1
/* Un esempio molto semplice di battaglia navale.
Lo schema è prefissato, non cambia da partita a partita,
per il resto è il normale gioco della battaglia navale.
Si distinguono due campi di battaglia: "schema" contiene
la disposizione delle navi sul campo di battaglia;
"battaglia" tiene traccia dei colpi effettuati dall'utente
(se il colpo ha dato come risultato 'mancato' o 'colpito').
I simboli usati sulla “griglia” sono:
'x' = elemento di una nave
'o' = "mancato"
'*' = "colpito"
'.' = casella sulla quale non è stato effettuato
nessun colpo
Nota: l'esempio mostra come sfruttare il fatto che in C
in realtà i char sono degli interi.
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
14
C/2: battaglia navale - Codice sorgente /2
#include <stdio.h>
#define DIM_OR 6
#define DIM_VERT 6
main()
{
/* gli array (doppi) "schema" e "battaglia" vengono
inizializzati al momento della dichiarazione.
Essendo questi degli array doppi di caratteri,
la sintassi per l'inizializzazione è quella vista sotto,
con stringhe di caratteri (comprese tra "") separate da
virgole e racchiuse tra parentesi graffe.
*/
char schema[DIM_OR][DIM_VERT] = {" 12345", "Axx...", "B...x.",
"Cx....", "D.xx..", "E....x"};
char battaglia[DIM_OR][DIM_VERT] = {" 12345", "A.....",
"B.....", "C.....",
"D.....", "E....."};
char c1, c2;
int i, j;
int pz_rim = 7;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
15
C/2: battaglia navale - Codice sorgente /3
printf ("\n");
do {
for (i=0 ; i<DIM_OR ; i++) {
for (j=0 ; j<DIM_VERT ; j++) {
printf ("%c", battaglia[i][j]);
}
printf ("\n");
}
printf ("\n* = colpito, o = mancato, . = acqua\n");
printf ("Composizione navi: xx xx x x x\n");
printf ("Scegli coordinate (lettera, numero) a cui
sparare: ");
scanf ("%c%c%*c", &c1, &c2);
/* La scanf legge 2 caratteri (le coordinate sono formate
da una parte letterale e da una parte numerica, per
esempio B5), per questo il codice contiene 2 %c, e a
destra devo mettere 2 variabili.
*/
printf ("\n");
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
16
C/2: battaglia navale - Codice sorgente /4
/* Nel fare tutte le operazioni di verifica della cella su cui
l'utente ha sparato si sfrutta il fatto che i char siano degli
interi (per cui 'A' corrisponde in realtà al codice ASCII del
carattere A)
*/
if (c1>='A' && c1<='E' && c2>='1' && c2<='5' &&
battaglia[c1-'A'+1][c2-'1'+1] == '.') {
if (schema[c1-'A'+1][c2-'1'+1] == 'x') {
battaglia[c1-'A'+1][c2-'1'+1] = '*';
/* Ogni volta che l'utente colpisce una nave, il valore
della variabile "pz_rim" (che contiene quanti sono i
pezzi di nave ancora da colpire) viene decrementato.
Quando pz_rim arriva a 0 vuol dire che l'utente ha
colpito tutti i pezzi di nave e il gioco è finito.
*/
pz_rim--;
printf ("\n***COLPITO!***\n\n");
} else {
battaglia[c1-'A'+1][c2-'1'+1] = 'o';
printf ("\nMANCATO!\n\n");
}
}
} while (pz_rim > 0);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
17
C/2: battaglia navale - Codice sorgente /5
printf
printf
printf
printf
("\n");
("******************\n");
("***HAI VINTO!!!***\n");
("******************\n");
}
Nota: da svolgere in autonomia
Realizzare una variante a questo programma che consenta
l'inserimento da parte di un utente dei pezzi nell'array schema
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
18
C/3: concatenazione - Problema
Si vuole realizzare in linguaggio C un programma
in grado di concatenare due stringhe di caratteri
date in input mettendo prima quella che, in ordine
lessicografico, viene prima.
Ma cos'è una stringa?
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
19
C/3: concatenazione - Codice sorgente /1
/* Il programma chiede all'utente di inserire 2 stringhe di
caratteri e le concatena, mettendo prima quella che, in
ordine lessicografico, viene prima.
L'acquisizione delle stringhe non avviene carattere per
carattere ma utilizzando la funzione “gets” fornita dalla
libreria “stdio.h”
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
20
C/3: concatenazione - Codice sorgente /2
#include <stdio.h>
#define MAX_LUNGH 50
main()
{
int i, j, k;
int l_a1, l_a2;
char tempCar;
char array1[MAX_LUNGH+1], array2[MAX_LUNGH+1],
array_conc[MAX_LUNGH*2+1];
printf ("Inserisci la prima sequenza di caratteri
(max %d caratteri): ", MAX_LUNGH);
gets (&array1[0]);
printf ("Inserisci la seconda sequenza di caratteri
(max %d caratteri): ", MAX_LUNGH);
gets (&array2[0]);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
21
C/3: concatenazione - Codice sorgente /3
l_a1 = 0;
while (array1[l_a1] != '\000') {
l_a1++;
}
l_a2 = 0;
while (array2[l_a2] != '\000') {
l_a2++;
}
i = 0;
while (i<l_a1 && i<l_a2 && array1[i] == array2[i]) {
i++;
}
/*Invece dei 3 cicli while precedenti si possono scrivere i
seguenti cicli for (molto più compatti):
for (l_a1=0; array1[l_a1]!= '\000'; l_a1++);
for (l_a2=0; array2[l_a2]!= '\000'; l_a2++);
for (i=0; i<l_a1 && i<l_a2 && array1[i] == array2[i]; i++);
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
22
C/3: concatenazione - Codice sorgente /4
if (i==l_a1 || array1[i]<array2[i]) {
k = 0;
for (j=0 ; j<l_a1 ; j++) {
array_conc[k] = array1[j];
k++;
}
for (j=0 ; j<l_a2 ; j++) {
array_conc[k] = array2[j];
k++;
}
} else {
k = 0;
for (j=0 ; j<l_a2 ; j++) {
array_conc[k] = array2[j];
k++;
}
for (j=0 ; j<l_a1 ; j++) {
array_conc[k] = array1[j];
k++;
}
}
array_conc[k] = '\000';
/* Chiudo la stringa concatenata con il carattere nullo '\0' */
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
23
C/3: concatenazione - Codice sorgente /5
printf ("La stringa concatenata è:\n");
for ( k=0 ; k<l_a1+l_a2 ; k++) {
printf ("%c", array_conc[k]);
}
printf ("\n");
/*Per le stringhe terminate dal carattere '\0' si può
usare, invece del ciclo for sopra scritto,
il comando 'printf' con il carattere di controllo '%s'
(che indica le stringhe)
Es:
printf ("La stringa concatenata è:\n%s\n", array_conc);
*/
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
24
C/4: conversione basi - Problema
Si vuole realizzare in linguaggio C un programma
in grado di convertire un numero in base 10 in
un'altra base compresa tra 2 e 9.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
25
C/4: conversione basi - Pseudo codice
main()
{
[memorizzare il numero, verificando che sia > 0]
[memorizzare la base in cui convertire, verificando
che sia <10 e >1]
num_tmp = numero;
while (num_tmp>0)
{
[dividere num_tmp per la base; il resto aggiungerlo
all'array conv, il risultato metterlo in num_tmp]
}
[stampare l'array conv, a partire dal fondo (cifra
più significativa)]
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
26
C/4: conversione basi - Codice sorgente /1
/* Il programma prende un numero in base 10, e lo
converte in una base scelta dall'utente (la nuova
base deve essere compresa tra 2 e 9)
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
27
C/4: conversione basi - Codice sorgente /2
#include <stdio.h>
main()
{
int num, base, num_tmp;
int conv[50];
int i, n_el;
do {
printf ("Inserire numero (>0) da convertire: ");
scanf ("%d", &num);
} while (num<=0);
num_tmp = num;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
28
C/4: conversione basi - Codice sorgente /3
do {
printf ("Inserire base (compresa tra 2 e 10) in cui
convertire il numero: ");
scanf ("%d", &base);
} while (base < 2 || base > 9);
/* Calcolo le singole cifre del numero rappresentato nella
nuova base; le singole cifre vengono messe, dalla MENO
significativa alla PIU' significativa, nell'array 'conv'
*/
/* Ad ogni ciclo, il numero num_tmp viene diviso (divisione
intera) per la base. Il resto della divisione è la prossima
cifra nella nuova base, mentre il risultato verrà
ulteriormente diviso nei cicli successivi
*/
for (i=0 ; num_tmp>0 ; i++) {
conv[i] = num_tmp % base;
num_tmp = num_tmp / base;
}
n_el = i;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
29
C/4: conversione basi - Codice sorgente /4
/* Il nuovo numero viene stampato, dalla cifra PIU'
significativa alla MENO significativa (quindi occorre
scorrere l'array in senso inverso)
*/
printf ("Il numero %u convertito in base %d è: ", num, base);
for (i=n_el-1 ; i>=0 ; i--) {
printf ("%d", conv[i]);
}
printf ("\n");
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
30
C/5: Bubblesort - Problema
Si vuole realizzare in linguaggio C un programma
in grado di ordinare un array di interi usando
l'algoritmo di bubblesort.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
31
C/5: Bubblesort - Codice sorgente /1
/* Ordina un array di interi usando l'algoritmo di
bubblesort */
#include <stdio.h>
typedef enum {false, true} bool;
#define MAX_DATI 100
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
32
C/5: Bubblesort - Codice sorgente /2
main()
{
int dati[MAX_DATI];
int i, n_dati, temp, dato_corr;
bool ordinato = false;
/* Leggo i dati dallo standard input;
la lettura termina quando l'utente inserisce uno 0.
*/
i = 0;
do {
printf ("Inserire dato intero n. %d (max %d dati, 0 per
terminare): ", i+1, MAX_DATI);
scanf ("%d", &dato_corr);
if (dato_corr != 0) {
dati[i] = dato_corr;
i++;
}
} while (i<MAX_DATI && dato_corr != 0);
n_dati = i;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
33
C/5: Bubblesort - Codice sorgente /3
/* Si continua a scorrere l'array finché non è ordinato. */
/* Attenzione a non scrivere
ordinato = false
al posto di
ordinato == false
perché sono 2 cose profondamente DIVERSE!
Nel primo caso viene effettuato l'assegnamento,
e viene ritornato il valore 'false'; il ciclo
while valuta la condizione 'false', e quindi esce!
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
34
C/5: Bubblesort - Codice sorgente /4
while (ordinato == false) {
/* Si comincia con il presupporre che l'array sia ordinato. */
ordinato = true;
/* Ad ogni scansione dell'array, se si trova che ci sono
due elementi adiacenti dati[i] e dati[i+1] per cui
dati[i] > dati [i+1] allora si scambiano i due elementi.
Se si scambiano due elementi, vuol dire che l'array non era
ancora ordinato, e quindi che sarà necessario fare almeno
un'altra scansione dell'array.
Quando si ottiene alla fine un array ordinato, non ci sono
più elementi da scambiare, il valore di 'ordinato' rimane
'true', e l'algoritmo si ferma.
for (i=0 ; i<n_dati-1 ; i++) {
if (dati[i] > dati[i+1]) {
temp = dati[i];
dati[i] = dati[i+1];
dati[i+1] = temp;
ordinato = false;
}
}
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
35
*/
C/5: Bubblesort - Codice sorgente /5
/* Stampa dell'array ordinato */
printf ("I valori ordinati in ordine crescente sono:\n");
for (i=0 ; i<n_dati ; i++) {
printf ("%d ", dati[i]);
}
printf("\n");
}
Nota: è possibile ottimizzare il programma?
(Come funzionava l'algoritmo implementato in assembler?)
Da svolgere in autonomia
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
36
C/ripasso – Nuova struttura di controllo: switch
Si introduce, per gli esercizi seguenti, uno nuovo tipo di
struttura di controllo: l'istruzione switch.
E' costituita da:
➢
➢
➢
la parola chiave switch seguita da
un'espressione tra () seguita da
una sequenza di istruzioni case racchiuse tra “{}”
ognuna delle quali è costituita dalla parola chiave case
seguita da un'espressione costante, seguita dai “:”,
seguita da una serie di istruzioni e terminata da una
istruzione break. In genere viene fornito un case di
default indicato appunto dalla keyword default.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
37
C/6: promozioni - Problema
Si vuole realizzare in linguaggio C un programma in
grado di chiedere all'utente di inserire una serie di nomi di
persone, i quali vengono considerati ufficiali dell'esercito.
Le persone partono tutte dal grado minimo di
“sottotenente”, e l'utente può poi scegliere se promuoverli
(fino al grado massimo di “tenente generale”) o
degradarli. Se l'utente chiede di degradare una persona
che è sottotenente, o di promuovere una persona che è
tenente generale, viene segnalato un errore, perché si è
arrivati ai limiti della scala gerarchica.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
38
C/6: promozioni - Codice sorgente /1
/* Il programma chiede all'utente di inserire una serie di
nomi di persone, i quali vengono considerati ufficiali
dell'esercito.
Le persone partono tutte dal grado minimo di
"sottotenente", e l'utente può poi scegliere se
promuoverli (fino al grado massimo di "tenente
generale") o degradarli. Se l'utente chiede di degradare
una persona che è sottotenente, o di promuovere una
persona che è tenente generale, viene segnalato
un errore, perché si è arrivati ai limiti della scala
gerarchica.
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
39
C/6: promozioni - Codice sorgente /2
#include <stdio.h>
/* L'elenco dei gradi possibili viene rappresentato da un
tipo 'enum', i cui identificatori sono le abbreviazioni
dei gradi. Definendo un tipo 'enum' si definisce
automaticamente anche l'ORDINAMENTO dei gradi (grazie alla
corrispondenza enum <-> int), per cui 'sten' è minore di
'ten' (in effetti 'sten' corrisponde al numero 0, 'ten' al
numero 1, etc.)
*/
typedef enum{sten, ten, cap, magg, ten_col, col,
brig_gen, magg_gen, ten_gen} tipo_gradi;
#define N_GRADI 9
#define MAX_LUNGH_NOMI 100
#define MAX_N_PERSONE 50
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
40
C/6: promozioni - Codice sorgente /3
main()
{
/* L'array 'nome_gradi' è un array di stringhe di caratteri
(quindi un array doppio di char) che contiene il nome per
esteso dei gradi possibili. Poiché i nomi per esteso sono
fissi, l'array è definito costante (grazie alla parola
chiave 'const' prima della dichiarazione), e viene
inizializzato con i nomi (costanti) alla dichiarazione
(l'unico punto in cui è possibile assegnare dei valori a
una variabile dichiarata 'const').
La corrispondenza tra identificatore del tipo 'enum' e nome
per esteso viene fatta ancora una volta sfruttando la
corrispondenza tra enum e int. Per esempio, 'sten', come
detto in precedenza, corrisponde al numero 0, e la parola
contenuta nell'elemento 0 dell'array 'nome_gradi' è in
effetti "sottotenente".
E' per esempio possibile scrivere direttamente
nome_gradi[sten], che restituisce il valore
"sottotenente".
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
41
C/6: promozioni - Codice sorgente /4
const char nome_gradi[N_GRADI][30] = { "sottotenente",
"tenente",
"capitano",
"maggiore",
"tenente colonnello",
"colonnello",
"brigadier generale",
"maggior generale",
"tenente generale"};
tipo_gradi gradi[MAX_N_PERSONE];
char persone[MAX_N_PERSONE][MAX_LUNGH_NOMI];
char op;
int n_pers, i, pers_corr;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
42
C/6: promozioni - Codice sorgente /5
do {
printf ("Inserire il numero di persone graduate (max %d): ",
MAX_N_PERSONE);
scanf ("%d", &n_pers);
} while (n_pers<1 || n_pers>MAX_N_PERSONE);
/* Leggere uno per volta, da standard input, i nomi delle
persone, e inizializzare man mano il grado di tutte le
persone inserite al grado di sottotenente */
for (i=0 ; i<n_pers ; i++) {
printf ("Persona n. %d (senza spazi): ", i+1);
scanf ("%s", &persone[i][0]);
gradi[i] = sten;
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
43
C/6: promozioni - Codice sorgente /6
do {
/* Stampare tutte le persone inserite con a fianco il grado */
printf ("\n********************************************\n");
for (i=0 ; i<n_pers ; i++) {
printf ("%d) %s: %s\n", i+1, persone[i],
nome_gradi[gradi[i]]);
}
printf ("\nScegliere la persona da promuovere/degradare\n");
printf ("(da 1 a %d, 0 per terminare): ", n_pers);
scanf ("%d", &pers_corr);
/* Se è stata selezionata una persona valida, chiedere prima
se deve essere promossa o degradata, e quindi eseguire
l'operazione, verificando che sia possibile (per esempio
non è possibile degradare un sottotenente e non è possibile
promuovere un tenente generale) */
if (pers_corr >= 1 && pers_corr <= n_pers) {
printf ("Scegliere P per promuovere o D per degradare: ");
scanf (" %c", &op);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
44
C/6: promozioni - Codice sorgente /7
switch (op) {
case 'P':
if (gradi[pers_corr-1] != ten_gen) {
gradi[pers_corr-1] = gradi[pers_corr-1] + 1;
} else {
printf ("\n####Non è possibile promuovere un tenente
generale!!!!!####\n");
}
break;
case 'D':
if (gradi[pers_corr-1] != sten) {
gradi[pers_corr-1] = gradi[pers_corr-1] - 1;
} else {
printf ("\n####Non è possibile degradare un
sottotenente!!!!!####\n");
}
break;
default:
printf ("\n####Operazione richiesta errata!!!!!!####\n");
break;
}
}
} while (pers_corr != 0);
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
45
C/6.1: promozioni – Versione alternativa
Si vuole realizzare in linguaggio C lo stesso programma
realizzato in precedenza, utilizzando un array di struct
invece che 2 array separati per contenere i dati delle
persone.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
46
C/6.1: promozioni - Codice sorgente /1
/* Questa versione del programma 'promozioni' usa un array di
di struct invece che 2 array separati per contenere i dati
delle persone.
*/
#include <stdio.h>
typedef enum {sten, ten, cap, magg, ten_col, col,
brig_gen, magg_gen, ten_gen} tipo_gradi;
#define N_GRADI 9
#define MAX_LUNGH_NOMI 100
#define MAX_N_PERSONE 50
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
47
C/6.1: promozioni - Codice sorgente /2
/* Invece di utilizzare 2 array separati per rappresentare i
dati delle persone, in questa versione del programma
useremo un array di struct.
Ogni struct conterrà i dati (nome, grado) di una
singola persona.
*/
typedef struct {
char nome[MAX_LUNGH_NOMI];
tipo_gradi grado;
} dati_uff;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
48
C/6.1: promozioni - Codice sorgente /3
main()
{
const char nome_gradi[N_GRADI][30] = { "sottotenente",
"tenente",
"capitano",
"maggiore",
"tenente colonnello",
"colonnello",
"brigadier generale",
"maggior generale",
"tenente generale"};
/* Invece di avere due array separati "gradi" e "persone"
si utilizzerà un solo array "persone", che è un array di
struct.
*/
dati_uff persone[MAX_N_PERSONE];
char op;
int n_pers, i, pers_corr;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
49
C/6.1: promozioni - Codice sorgente /4
do {
printf ("Inserire il numero di persone graduate (max %d): ",
MAX_N_PERSONE);
scanf ("%d", &n_pers);
} while (n_pers<1 || n_pers>MAX_N_PERSONE);
/* Leggere uno per volta, da standard input, i nomi delle persone,
e inizializzare il grado di tutte le persone inserite
a sottotenente */
for (i=0 ; i<n_pers ; i++) {
printf ("Persona n. %d (senza spazi): ", i+1);
scanf ("%s", &persone[i].nome[0]);
persone[i].grado = sten;
/* laddove in promozioni.c si usava 'gradi[i]', qui occorre
fare riferimento al campo 'grado' dell'elemento 'i', e quindi
scrivere
persone[i].grado
Allo stresso modo il nome di ogni persona è contenuto nel
campo 'nome' di ogni elemento i dell'array "persone":
persone[i].nome
*/
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
50
C/6.1: promozioni - Codice sorgente /5
do {
/* Stampare tutte le persone inserite con a fianco il grado */
printf ("\n********************************************\n");
for (i=0 ; i<n_pers ; i++) {
printf ("%d) %s: %s\n", i+1, persone[i].nome,
nome_gradi[persone[i].grado]);
}
printf ("\nScegliere la persona da promuovere/degradare\n");
printf ("(da 1 a %d, 0 per terminare): ", n_pers);
scanf ("%d", &pers_corr);
/* Se è stata selezionata una persona valida, chiedere prima
se si deve promuovere o degradare, e quindi eseguire
l'operazione, verificando che sia possibile (per esempio non
è possibile degradare un sottotenente e non è possibile
promuovere un tenente generale) */
if (pers_corr >= 1 && pers_corr <= n_pers) {
printf ("Scegliere P per promuovere o D per degradare: ");
scanf (" %c", &op);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
51
C/6.1: promozioni - Codice sorgente /6
switch (op) {
case 'P':
if (persone[pers_corr-1].grado != ten_gen) {
persone[pers_corr-1].grado += 1;
} else {
printf ("\n####Non puoi promuovere un tenente
generale!!!!!####\n");
}
break;
case 'D':
if (persone[pers_corr-1].grado != sten) {
persone[pers_corr-1].grado -= 1;
} else {
printf ("\n####Non puoi degradare un
sottotenente!!!!!####\n");
}
break;
default:
printf ("\n####Operazione richiesta errata!!!!!!####\n");
break;
}
}
} while (pers_corr != 0);
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
52
C/FAQ + feedback /1
➢
Formattazione/indentazione del codice
Si sottolinea ancora una volta che è importantissimo
scrivere il codice sorgente ben formattato e ben indentato al
fine di facilitarne la comprensione e il debugging
for (espr1; espr2; espr3) {
istruzione;
istruzione;
istruzione;
}
if (espressione) {
istruzione;
istruzione;
istruzione;
} else {
istruzione;
istruzione;
istruzione;
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
53
C/FAQ + feedback /2
➢
Formattazione/indentazione del codice
Fare molta attenzione ai casi di ambiguità...
if (n >= 0)
if (n >= 0)
for (i=0; i<n; i++)
for (i=0; i<n; i++)
if (s[i] > 0) {
if (s[i] > 0) {
printf (“....”);
printf (“....”);
}
}
else
else
printf (“n è negativo”);
printf (“n è negativo”);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
54
C/FAQ + feedback /3
➢
➢
➢
➢
Chiusura delle parentesi
Verificare che tutte le parentesi aperte siano anche chiuse...
Chiusura del file sorgente
Verificare che alla fine del codice sorgente (dopo l'ultima
riga) sia inserito un “new line” (è comunque un warning...)
Inizializzazione variabili
Assicurarsi che le variabili, prima del loro utilizzo, abbiano
un valore congruente all'uso che se ne intende fare
Confronti corretti
No: if ( a < b < c )
No: if ( a = b )
Si:
Si:
if ( a < b && b < c )
if ( a == b )
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
55
C/FAQ + feedback /4
➢
Utilizzo corretto della struttura di controllo IF ELSE
Utilizzare correttamente i controlli in cascata
Utilizzo SBAGLIATO
Utilizzo CORRETTO
if (espressione) {
istruzione;
istruzione;
istruzione;
} else {
istruzione;
istruzione;
istruzione;
} else {
istruzione;
istruzione;
istruzione;
}
if (espressione) {
istruzione;
istruzione;
istruzione;
} else if (espressione) {
istruzione;
istruzione;
istruzione;
} else {
istruzione;
istruzione;
istruzione;
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
56
C/7: bubblesort 2 – ordinamento di date - Problema
Si vuole realizzare in linguaggio C un
programma in grado di ordinare un array di date
(invece che, come nell'esempio svolto in aula, un
array di interi).
Ogni data dovrà essere rappresentata da
un'apposita struttura con giorno, mese e anno
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
57
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /1
/* Questa versione del 'bubblesort' invece che ordinare un
array di interi, ordina un array di date. Ogni data
è rappresentata da una struttura con giorno, mese e
anno
*/
#include <stdio.h>
typedef enum {false, true} bool;
/* Consideriamo solo gli anni DOPO CRISTO,
per questo il campo anno è unsigned e non
c'è nessuna specifica AC o BC.
*/
typedef struct {
unsigned short giorno;
unsigned short mese;
unsigned int anno;
} tipo_data;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
58
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /2
/* Si sarebbe potuto anche definire il campo mese in
modo diverso, con un enum del tipo
typedef enum { gen, feb, mar, apr, mag, giu,
lug, ago, set, ott, nov, dic } tipo_mese;
e poi dichiarando nella struct
tipo_mese mese;
*/
non sarebbe cambiato molto, perché questo tipo di formulazione
sarebbe stata equivalente a dichiarare, per come il C tratta i
tipi enum, che 'tipo_mese' in realtà assumeva valori tra
0 e 11 (NON tra 1 e 12, ATTENZIONE! ci sarebbe stato un problema di
disallineamento con il senso comune con cui vengono rappresentati
i mesi)
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
59
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /3
#define MAX_DATI 100
main()
{
tipo_data dati[MAX_DATI];
tipo_data dato_corr, temp;
int i, n_dati;
bool ordinato = false;
/* Leggo i dati dallo standard input;
la lettura termina quando l'utente inserisce uno 0.
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
60
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /4
i = 0;
do {
printf ("Inserire data n. %d nel formato \"gg/mm/aaaa\"\n", i+1);
printf ("(max %d dati, 0 per terminare): ", MAX_DATI);
scanf (" %hu/%hu/%u", &dato_corr.giorno, &dato_corr.mese,
&dato_corr.anno);
/* Alla scanf viene data una sequenza di caratteri che identifica
il formato in cui la scanf si aspetta che l'utente immetta i
dati.
In questo caso la scanf si aspetta che l'utente immetta:
*/
<unsigned short>/<unsigned short>/<unsigned int>
if (dato_corr.giorno != 0) {
dati[i].giorno = dato_corr.giorno;
dati[i].mese = dato_corr.mese;
dati[i].anno = dato_corr.anno;
i++;
}
} while (i<MAX_DATI && dato_corr.giorno != 0);
n_dati = i;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
61
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /5
/* Si noti che non viene fatta nessuna verifica che la data sia valida
(anche una data chiaramente sbagliata come 45/23/2000 viene
accettata: per esercizio si aggiunga una parte di codice in grado
di eseguire questo tipo di controllo)
*/
Nota: da svolgere in autonomia
while (ordinato == false) {
ordinato = true;
for ( i=0 ; i<n_dati-1 ; i++ ) {
/* Per verificare che una data sia maggiore/minore di un'altra
occorre fare una verifica campo per campo, prima sugli anni
poi, se gli anni sono uguali, sui mesi e, se sia gli anni
che i mesi sono uguali, sui giorni.
*/
if ( dati[i].anno > dati[i+1].anno ||
(dati[i].anno == dati[i+1].anno && dati[i].mese > dati[i+1].mese) ||
(dati[i].anno == dati[i+1].anno && dati[i].mese == dati[i+1].mese &&
dati[i].giorno > dati[i+1].giorno)
) {
Nota: da svolgere in autonomia (gestione di date uguali)
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
62
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /6
/* Si assegnano le variabili (di tipo struttura) campo
per campo.
*/
temp.giorno = dati[i].giorno;
temp.mese = dati[i].mese;
temp.anno = dati[i].anno;
dati[i].giorno = dati[i+1].giorno;
dati[i].mese = dati[i+1].mese;
dati[i].anno = dati[i+1].anno;
dati[i+1].giorno = temp.giorno;
dati[i+1].mese = temp.mese;
dati[i+1].anno = temp.anno;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
63
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /7
/* Notare che è possibile, con le strutture, scrivere assegnamenti
tra le strutture intere e non serve, come per gli array, farlo
elemento per elemento. L'assegnamento precedente si può dunque
scrivere, in modo più compatto (ed anche più leggibile; tra
l'altro non si rischia, con l'assegnamento globale, di dimenticare
di assegnare dei campi):
dati[i] = dato_corr;
*/
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
64
C/7: bubblesort 2 – ordinamento di date – Codice
sorgente /8
ordinato = false;
}
}
}
/* Stampo l'array ordinato */
printf ("I valori ordinati in ordine crescente sono:\n\n");
for (i=0 ; i<n_dati ; i++) {
printf ("%hu/%hu/%u\n", dati[i].giorno, dati[i].mese, dati[i].anno);
}
printf ("\n");
}
/* Variante: come esercizio si può provare a fare l'ordinamento
di elementi che rappresentano il gruppo data/ora
*/
Nota: da svolgere in autonomia
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
65
C/8: Numeri complessi - Problema
Si vuole realizzare un programma che acquisisca in
input due numeri complessi (definiti da parte reale e
parte immaginaria) e ne faccia somma, sottrazione,
moltiplicazione e divisione.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
66
C/8: Numeri complessi – Codice sorgente/1
/* Il programma prende in input due numeri complessi
(definiti da parte reale e parte immaginaria)
e ne fa somma, sottrazione, moltiplicazione e divisione
*/
#include <stdio.h>
/* In modo molto naturale un tipo "numero complesso" è definito
tramite una struttura che contiene 2 campi, uno per la parte reale
e uno per la parte immaginaria del numero
*/
typedef struct {
double re;
double im;
} complex;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
67
C/8: Numeri complessi – Codice sorgente/2
main()
{
complex n1, n2, sum, sub, mul, div;
printf ("Primo numero, parte reale: ");
scanf ("%lf", &n1.re);
printf ("Primo numero, parte immaginaria: ");
scanf ("%lf", &n1.im);
printf ("Secondo numero, parte reale: ");
scanf ("%lf", &n2.re);
printf ("Secondo numero, parte immaginaria: ");
scanf ("%lf", &n2.im);
sum.re = n1.re + n2.re;
sum.im = n1.im + n2.im;
sub.re = n1.re - n2.re;
sub.im = n1.im - n2.im;
mul.re = n1.re*n2.re - n1.im*n2.im;
mul.im = n1.im*n2.re + n1.re*n2.im;
div.re = (n1.re*n2.re + n1.im*n2.im)/(n2.re*n2.re + n2.im*n2.im);
div.im = (n1.im*n2.re - n1.re*n2.im)/(n2.re*n2.re + n2.im*n2.im);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
68
C/8: Numeri complessi – Codice sorgente/3
/* Per stampare i risultati a video uso una serie di 'if' perché
devo stampare il carattere '+' nel caso in cui la parte
immaginaria sia positiva (il carattere '-' di un numero negativo
viene automaticamente stampato, ma il '+' di un numero positivo no!)
printf ("\n");
if (sum.im < 0)
printf ("Somma
= %lf %lfi\n", sum.re, sum.im);
else
printf ("Somma
= %lf +%lfi\n", sum.re, sum.im);
if (sub.im < 0)
printf ("Sottrazione = %lf %lfi\n", sub.re, sub.im);
else
printf ("Sottrazione = %lf +%lfi\n", sub.re, sub.im);
if (mul.im < 0)
printf ("Moltiplica
else
printf ("Moltiplica
}
if (div.im < 0)
printf ("Divisione
else
printf ("Divisione
= %lf %lfi\n", mul.re, mul.im);
= %lf +%lfi\n", mul.re, mul.im);
= %lf %lfi\n", div.re, div.im);
= %lf +%lfi\n", div.re, div.im);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
69
*/
C/ripasso: Il costrutto “?:”
Si tratta di una versione molto compatta del costrutto
IF-ELSE.
Nel costrutto
<condizione> ? <ramo then> : <ramo else>
viene valutata la condizione, e poi viene restituito il
valore del ramo then o del ramo else a seconda del
risultato della condizione.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
70
C/8.1: Numeri complessi con “?:” - Problema
Si vuole realizzare un programma che acquisisca in
input due numeri complessi (definiti da parte reale e
parte immaginaria) e ne faccia somma, sottrazione,
moltiplicazione e divisione.
Rispetto alla versione precedente utilizzare il
costrutto “?:” al posto degli if
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
71
C/8.1: Numeri complessi con “?:” – Codice sorgente /1
/* Il programma prende in input due numeri complessi
(definiti da parte reale e parte immaginaria)
e ne fa somma, sottrazione, moltiplicazione e divisione
L'unica differenza con la versione precedente del programma è nel
modo in cui vengono stampati i numeri alla fine, per i quali viene
usata, invece che la catena di if vista in precedenza, una forma
più compatta, basata sul costrutto '?:'
*/
#include <stdio.h>
/* In modo molto naturale un tipo "numero complesso" è definito
tramite una struttura che contiene 2 campi, uno per la parte reale
e uno per la parte immaginaria del numero
*/
typedef struct {
double re;
double im;
} complex;
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
72
C/8.1: Numeri complessi con “?:” – Codice sorgente /2
main()
{
complex n1, n2, sum, sub, mul, div;
printf ("Primo numero, parte reale: ");
scanf ("%lf", &n1.re);
printf ("Primo numero, parte immaginaria: ");
scanf ("%lf", &n1.im);
printf ("Secondo numero, parte reale: ");
scanf ("%lf", &n2.re);
printf ("Secondo numero, parte immaginaria: ");
scanf ("%lf", &n2.im);
sum.re = n1.re + n2.re;
sum.im = n1.im + n2.im;
sub.re = n1.re - n2.re;
sub.im = n1.im - n2.im;
mul.re = n1.re*n2.re - n1.im*n2.im;
mul.im = n1.im*n2.re + n1.re*n2.im;
div.re = (n1.re*n2.re + n1.im*n2.im)/(n2.re*n2.re + n2.im*n2.im);
div.im = (n1.im*n2.re - n1.re*n2.im)/(n2.re*n2.re + n2.im*n2.im);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
73
C/8.1: Numeri complessi con “?:” – Codice sorgente /3
/* La parte di scrittura a video dei risultati si può anche scrivere
in questo modo molto compatto (il carattere '\000' è il carattere nullo,
di fatto non si stampa niente, neanche lo spazio)
Nel costrutto
<condizione> ? <ramo then> : <ramo else>
*/
viene valutata la condizione, e poi viene restituito il valore
del ramo then o del ramo else a seconda del risultato della condizione.
printf
printf
printf
printf
printf
("\n");
("Somma
("Sottr.
("Molt.
("Divis.
=
=
=
=
%lf
%lf
%lf
%lf
%c%lfi\n",
%c%lfi\n",
%c%lfi\n",
%c%lfi\n",
sum.re,
sub.re,
mul.re,
div.re,
sum.im
sub.im
mul.im
div.im
<
<
<
<
0
0
0
0
?
?
?
?
'\000'
'\000'
'\000'
'\000'
:
:
:
:
'+',
'+',
'+',
'+',
sum.im);
sub.im);
mul.im);
div.im);
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
74
C/9: assegnamento array - Problema
Si vuole realizzare un programma che dati due array
copi l'intero contenuto di un array nell'altro.
Nota: si vuole verificare una incongruenza del
linguaggio C che permette questo tipo di operazione
solo se gli array sono contenuti in una struttura ma
non permette un assegnamento diretto tra gli array.
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
75
C/9: assegnamento array – Codice sorgente/1
/* Questo programma mostra come sia possibile assegnare strutture
intere anche se queste contengono degli array, mentre non sia
possibile assegnare array interi che non siano dentro strutture. */
#include <stdio.h>
typedef int tipo_arr[10];
typedef struct {
tipo_arr a;
} tipo_s;
main()
{
int i;
tipo_arr a1, a2;
tipo_s s1, s2;
for (i=0 ; i<10 ; i++) {
a1[i] = i;
a2[i] = 2*i;
s1.a[i] = -i;
s2.a[i] = -i*2;
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
76
C/9: assegnamento array – Codice sorgente/2
/* Prima dell'assegnamento */
printf ("\nPrima dell'assegnamento:\n");
printf ("s1.a
s2.a\n");
for ( i=0 ; i<10 ; i++ ) {
printf ("%d
%d\n", s1.a[i], s2.a[i]);
}
/* Non valido!!!!
a1 = a2;
*/
/* Questo però è valido!!!! */
s1 = s2;
/* Dopo l'assegnamento */
printf ("\nDopo l'assegnamento:\n");
printf ("s1.a
s2.a\n");
for ( i=0 ; i<10 ; i++ ) {
printf ("%d
%d\n", s1.a[i], s2.a[i]);
}
}
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
77
C/ripasso: i puntatori /1
Si è già visto che a una variabile corrisponde un
nome, una locazione di memoria e l'indirizzo della
locazione di memoria
L'operatore &, già utilizzato con la scanf, ritorna
l'indirizzo di memoria di una variabile (&b è
un'espressione il cui valore è l'indirizzo di memoria
della variabile b)
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
78
C/ripasso: i puntatori /2
Un indirizzo può essere assegnato solo a un
particolare tipo di variabile (detta variabile derivata):
i puntatori.
I puntatori vengono definiti nel seguente modo:
tipoVariabile *variabilePuntatore;
in pratica variabilePuntatore viene utilizzata per
memorizzare l'indirizzo di variabili di tipo
tipoVariabile
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
79
C/ripasso: i puntatori /3
L'operatore unario *, detto operatore di indirezione,
viene applicato a una variabile di tipo puntatore per
accedere al contenuto dell'oggetto puntato.
int a;
int *pi;
// a è definita come intero
// pi è definita come puntatore a
// intero
pi = &a;
// il valore di pi è l'indirizzo di
// memoria in cui è memorizzata a
// Nota: a e *pi sono ora “legati”
a = 10;
printf (“Valore di a = %d\n”, a);
printf (“Valore di *pi = %d\n”, *pi);
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
80
C/ripasso: i puntatori /4
Esempi:
int x = 1; y = 2; z[10];
int *ip;
// ip è un puntatore a un intero
ip = &x;
y = *ip;
// ora ip punta a x
// ora y vale...
// 1
// ora x vale...
// 0
// ora ip punta a...
// z[0]
*ip = 0;
ip = &z[0];
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
81
C/nota: il primo compitino si avvicina...
✔
✔
✔
Testare tutti gli esempi fatti nelle esercitazioni e
inserire delle varianti
Provare i compitini degli anni precedenti
http://www.cremona.polimi.it/info1
Per problemi/dubbi/chiarimenti:
[email protected]
Esercitazioni di Fondamenti di Informatica – Politecnico di Milano sede di Cremona – A.A. 2010/2011 – Carlo Todeschini – [email protected]
82