slides

Transcript

slides
Università degli studi di Camerino
Scuola di scienze e tecnologia - Sezione Informatica
Programmazione C
Massimo Callisto De Donato
[email protected]
www.cs.unicam.it/massimo.callisto
LEZIONE 5 – ARRAY & STRINGHE
A.A. 2011/12
Array
• Un array (vettore) rappresenta una collezione di dati dello stesso
tipo identificati da indici progressivi che identificano la posizione.
• Gli array sono 0-index ovvero da 0 .. N – 1.
E.s: per N=6 implica un intervallo di indici in [0 .. 5]
• Se si esce fuori dal limite il comportamento non è prevedibile.
• Sintassi: tipo nome_variabile[DIMENSIONE_MAX];
• Esempio: int a[6];
Esempi
•
Inizializzazione tramite dati immessi dall’utente
int i;
for (i = 0; i < 6; i++){
printf(„„Inserisci un intero: ");
scanf(„„%d", &a[i]);
}
•
Ricerca del massimo
int max = a[0];
for (i = 1; i < 6; i++)
if (a[i] > max)
max = a[i];
printf(„„Valore massimo: %d\n", max);
•
Calcolo della media dei valori
int somma = 0;
float media;
for (i = 0; i < 6; i++)
somma = somma + a[i];
media = somma / 6;
•
Possiamo anche inizializzare l’array nella definizione:
int somma[] = {11,22,34,14,35,566};
Esempio: n concorrenti
• N concorrenti.
• Ogni concorrente sostiene 2 prove.
• Il punteggio corrisponde alla media aritmetica dei
risultati delle due prove.
• Creare una tabella che mostri:
– Risultato 1° prova
– Risultato 2° prova
– Punteggio finale
Esempio: n concorrenti
#include <stdio.h>
#define MAX CONC 100 // MAX CONCORRENTI
main()
{
/* 3 vettori: 1 e 2 prova e risultati */
float prova1[MAX CONC], prova2[MAX CONC],
totali[MAX CONC];
int i, n;
/* Inserimento numero concorrenti */
do {
printf(„„Inserire numero concorrenti: ");
scanf(„„%d", &n);
} while ((n < 1) k (n > MAX CONC))
/* Inserimento punteggi */
for (i=0; i < n; i++){
printf(„„\nConcorrente %d\n", i+1);
printf(„„Risultato prima prova: ");
scanf(„„%f", &prova1[i]);
printf(„„Risultato seconda prova: ");
scanf(„„%f", &prova2[i]);
}
/* calcolo media dei punteggi */
for (i=0; i < n; i++)
totale[i]=(prova1[i] + prova2[i]) /2 );
/* classifica */
for (i=0; i < n; i++) {
printf(„„%f\t‟‟, prova1[i]);
printf(„„%f\t‟‟, prova2[i]);
printf(„„%f\n‟‟, totale[i]);
}
} // main
Se volessimo stampare l’indice(i) del
vincitore(i) con relativo punteggio?
Esempio: array + switch
#include <stdio.h>
main(){
char espress[30];
int pg,pq,pt, c;
printf("\nEspressione algebrica ");
gets(espress);
pg=pq=pt=0;
for(c=0; c<30 && espress[c]!='\0';c++) {
switch(espress[c]) {
case '{„:
case '}':
pg++;
break;
case '[':
case ']':
pq++;
break;
case '(':; case ')':
pt++;
break;
}; };
printf("\nG = %d\nQ = %d\nT = %d",pg, pg, pt);
}
Esempio: somma incrociata
• Dati due vettori a e b di lunghezza N.
• Calcolare la somma incrociata degli elementi in un vettore c.
• Per somma incrociata intendiamo che gli elementi di c sono:
(a[0] + b[N-1], a[1] + b[N-2], ..., a[N-1] + b[0])
Esempio: somma incrociata
/* Somma incrociata (a[0] + b[N-1], a[1] + b[N-2], ..., a[N-1] + b[0]) */
#define N 6
main ()
{
int a[N], b[N], c[N];
int i, j;
for (i=0; i < N; ++i){
// Per a
printf("Inserisci l'elemento numero %d: ", i+1);
scanf("%d", &a[i]);
}
for (i=0; i < N; ++i){
// Per b
printf("Inserisci l'elemento numero %d: ", i+1);
scanf("%d", &b[i]);
}
for (i = 0; i < N; ++i) c[i] = a[i] + b[N - 1 -i];
printf(“Vettore c = ");
for (i = 0; i < N; ++i)
printf("%d\t", c[i]);
}
Array bidimensionali: matrici
• Array bidimensionale (matrice): righe e colonne.
• Sintassi:
tipo nome array[DIMENSIONE RIGHE][DIMENSIONE COLONNE];
E.s.: int matrice[4][3];
• Un elemento si identifica con il doppio indice compresi
in [0 .. r - 1] e [0 .. c - 1] (righe – colonne).
• Esempi su array bidimensionali:
Array multi-dimensionali
• Possiamo avere dimensioni arbitrarie:
tipo nome_array[DIM 1][DIM 2] ... [DIM N];
• Esempio: memorizzare i ricavi ottenuti dalla vendita di
10 prodotti in 5 punti vendita nei dodici mesi dell’anno.
int marketing[10][5][12]
• Ricavi ottenuti dalla vendita del terzo prodotto nel
quarto punto vendita nel mese di ottobre:
marketing[2][3][10]
Esempio: inizializzazione
#include <stdio.h>
main(){
int mat[4][3];
int i,j;
printf(„„\n\nCaricamento della matrice\n\n");
for(i = 0; i < 4; i++)
for(j = 0; j < 3; j++){
printf(„„El. di riga %d e colonna %d: ", i+1, j+1);
scanf(„„%d", &mat[i][j]);
}
printf(„„\n\nVisualizzazione matrice\n\n");
for(i = 0; i < 4; i++){
printf(„„\n‟‟);
for(j = 0; j < 3; j++)
printf(„„%d\t", mat[i][j]);
}
}
Esempio: prodotto matrici
• Date due matrici mat_1[N][P] e mat_2[P][M],
calcolare la matrice prodotto pmat[N][M].
• Ogni elemento pmat[i][j] (con i = 1..N e j = 1..M) è
definito da:
Esempio: prodotto matrici
/* prodotto di matrici */
#include <stdio.h>
main ()
{
int N = P = 2, M = 3
int mat1[N][P], mat2[P][M];
int pmat[N][M];
int i, j, k, somma;
printf("Matrice A (%d x %d) \n\n", N, P);
for (i=0; i < N; i++)
for (j=0; j < P; j++){
printf(“Riga %d e colona %d: ", i, j);
scanf("%d", &mat1[i][j]);
}
printf("Matrice B (%d x %d) \n\n", P, M);
for (i=0; i < P; i++)
for (j=0; j < M; j++){
printf(“Riga %d e colona %d: ", i, j);
scanf("%d", &mat2[i][j]);
}
//Calcolo del prodotto
for (i=0; i < N; i++)
for (j=0; j < M; j++){
somma = 0;
for (k=0; k < P; k++){
somma = somma + (mat1[i][k] * mat2[k][j]);
}
pmat[i][j] = somma;
}
//Visualizzazione prodotto
// (A e B analogo)
printf("\n\nMatrice prodotto\n\n");
for (i=0; i < N; i++){
printf("\n");
for (j=0; j < M; j++)
printf("%d ", pmat[i][j]);
}
} // chiuso main
Altri esercizi
1.
Data una matrice mat_1[N][P] calcolare la matrice trasposta
mat_2[P][M].
2.
Controllare se una matrice A è a diagonale dominante in senso debole
per righe:
gli elementi diagonali di A sono ≥ in valore assoluto della somma di tutti i restanti
elementi della stessa riga (in valore assoluto).
3.
Considerare la variante a senso stretto ovvero controllando
l’uguaglianza > .
Le stringhe
• Si lavora spesso su gruppi di caratteri che nell’insieme sono chiamati
stringa.
• In C non c'è un tipo specifico per le stringhe. Esse sono array di caratteri
char terminati con il carattere speciale “\0”:
char str[5];
char str[] = “ciao”;
• La dimensione in memoria degli array nei due casi è uguale.. Perché?
• Il carattere nullo ‘\0’ serve al compilatore per capire dove finisce la stringa.
str
C
I
A
O
\0
Le stringhe
• Modi equivalenti di dichiarare una stringa:
char str[] = “ciao”;
char str[] = {„c‟, „i‟, „a‟, „o‟,
„\0‟}
• Vale anche questo ma non si dovrebbe fare:
char str[] = {„c‟, „i‟, „a‟, „o‟};
• Chiaro ora che „A‟ è diverso da “A”!
Le stringhe
• La quantità di memoria occupato dell’array che contiene la stringa
viene fissata all’inizio ed è non modificabile.
char str[] = “ciao”;
char str[] = {„c‟, „i‟, „a‟, „o‟, „\0‟}
char str[5];
str[0] = „c‟;
str[1] = „i‟;
str[2] = „a‟;
str[3] = „o‟;
str[4] = „\0‟;
Esempio si riempimento
#include <stdio.h>
main()
{
char c1[100];
char c2[] = {'p','i','p', 'p', 'o', '\0'};
c1[0]
c1[1]
c1[2]
c1[3]
c1[4]
c1[5]
c1[6]
=
=
=
=
=
=
=
'c';
'a';
's';
'a';
'm';
'i';
'a';
printf("Lunghezza di 'c1': %d, di 'c2': %d\n", strlen(c1), strlen(c2));
c1[0] = 'c';
c1[1] = 'a';
c1[2] = 's';
printf("Lunghezza di 'c1': %d, di 'c2': %d\n", strlen(c1), strlen(c2));
c1[0]
c1[1]
c1[2]
c1[3]
=
=
=
=
'c';
'a';
's';
'\0';
printf("Lunghezza di 'c1': %d, di 'c2': %d\n", strlen(c1), strlen(c2));
return 0;
}
Le stringhe
• Le stringhe non sono un tipo di dato primitivo. Non
sono supportate le operazioni dirette come:
Copia? Concatenazione? Comparazione?
• Soluzione:
– ce le facciamo a mano
– usiamo le funzioni di libreria (se esistono)
• Esercizio: come facciamo a contare gli spazi contenuti
in una stringa? I caratteri ‘\n’?
Stringhe: copia e concatenazione
#include <stdio.h>
#define LEN 100
main ()
{
int i, j;
char c, s1[LEN], s2[LEN];
do{
printf(“Cosa vuoi fare? [0-copia,1-concatena]”)
c=getchar();
}while(c!= „0‟ or „1‟);
/* immissione stringhe */
printf("Inserisci le due stringhe separate da uno spazio\n");
scanf("%s %s", s1, s2);
switch(c){
case „0‟:
for (i=0; (s1[i]=s2[i]) != '\0'; i++);
break;
case „1‟:
for (i=0; s1[i]!='\0'; i++);
for (j=0; (s1[i]=s2[j])!='\0'; j++, i++);
break;
}
printf(“S1: %s\nS2: %s", s1, s2);
} // C‟è qualche problema potenziale su LEN?
Stringhe: comparazione
#include <stdio.h>
#define LEN 100
main ()
{
int i, flag;
char s1[LEN], s2[LEN];
/* immissione stringhe */
printf("Inserisci le due stringhe separate da spazio\n");
scanf("%s %s", s1, s2);
i=0;flag = 0;
while ((s1[i] !='\0') && (s2[i] != '\0')){
if(s1[i] != s2[i]){
flag = (s1[i] < s2[i]) ? -1: 1;
break;
}
i++;
}
if (flag == -1)
printf("%s e' minore di %s\n", s1, s2);
else if (flag == 1)
printf("%s e' maggiore di %s\n", s1, s2);
/* se flag=0, allora o entrambe le stringhe sono arrivate a '\0',
oppure qualcuna è arrivata prima dell'altra. */
else if (!flag){
if ( (s1[i] == '\0') && (s2[i] == '\0') )
printf("Le due stringhe %s e %s sono uguali\n", s1, s2);
else if (s1[i] == '\0')
printf("%s e' minore di %s\n", s1, s2);
else
printf("%s e' maggiore di %s\n", s1, s2);
}
} // Il controllo è case-sensitive… Per farne uno non case-sensitive?
Le stringhe palindrome
• Facciamo un programma che controlla se due
stringhe sono “palindrome”.
se, messa al contrario, si legge come l’originale.
Stringhe: palindrome
#include<stdio.h>
#define LEN 100
main ()
{
char stringa[LEN];
int i, j;
int len, palindroma = 1;
printf("Inserisci una frase: ");
scanf("%s", stringa);
for(i=0; stringa[i] != '\0'; i++){}
len = i;
i--;
j = 0;
while(palindroma && (j < (len/2))){
if (stringa[i] != stringa[j])
palindroma = 0;
j++;
i--;
}
if (palindroma)
printf("palindroma\n");
else
printf("non palindroma\n");
}
Stringhe e tabella ASCII
• Tutti gli esempi visti sono case-sensitive.
• Possiamo usare la tabella ASCII per creare programmi
non-case-sensitive.
• Osservazione:
tutte le lettere alfabetiche MAIUSCOLE sono comprese tra 65
(‘A’) e 90(‘Z’), distanziate dal valore 32 dalla rispettiva
versione minuscola (‘a’..’z’).
• Anche i numeri hanno un intervallo specifico…
Stringhe e tabella ASCII
Stringhe: esercizi
• Come possiamo cambiare il programma per le
stringhe palindrome affinché “Anna” sia uguale
ad “aNnA”?
• Come si può fare per convertire una stringa in
maiuscola?
• Fare un programma “calcolatrice” che usi solo
getchar() e realizzi le 4 operazioni fondamentali.
Stringhe: esercizi
• string.h: contiene delle funzioni standard che consentono di manipolare le
stringhe. Alcune sono molto simili a quelle viste finora.
• Funzioni principali di string.h
strcpy(str1, str2)
copia str2 in str1
strlen(str1)
ritorna la lunghezza di str1
strncpy(str1, str2, n) copia i primi n caratteri di str2 in str1
strcat(str1, str2)
concatena str2 a str1
strcmp(str1, str2)
confronta str1 con str2, restituisce zero se
le due stringhe sono uguali, un valore negativo
se str1 è minore di str2, un valore positivo
altrimenti
• Queste di seguito in stdlib.h
atoi(str) e atof(str)convertono str in un intero e in un decimale
rispettivamente
• Guardate il resto su Open Group