Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
PubblicatoBettina Rocca Modificato 10 anni fa
1
2000 Prentice Hall, Inc. All rights reserved. Capitolo 7 (Deitel) I puntatori Sommario 7.1 - Introduzione 7.2 - Dichiarare e inizializzare i puntatori 7.3 - Operatori per i puntatori 7.4 - Passare alle funzioni i parametri per riferimento 7.5 - Usare il qualificatore const con i puntatori 7.6 - Lordinamento Bubble Sort tramite una chiamata per riferimento 7.7 - Le espressioni con i puntatori e laritmetica dei puntatori 7.8 - La relazione tra puntatori e vettori 7.9 - Vettori di puntatori 7.10 - Caso di studio: simulare un mescolatore/distributore di carte
2
2000 Prentice Hall, Inc. All rights reserved. 7.1 - Introduzione I puntatori –Sono molto potenti, ma anche difficili da padroneggiare –Consentono il passaggio per riferimento dei parametri alle funzioni (che di default passerebbero invece per valore) –Sono strettamente correlati a vettori e stringhe Le variabili puntatori –Non contengono valori specifici (riferimento diretto) –Contengono indirizzi di memoria di altre variabili, che a loro volta contengono/immagazzinano dei valori specifici (riferimento indiretto) –Sono comunque variabili il cui valore sta dentro una cella di memoria –Deriferimento: operazione tramite cui si fa riferimento (si accede) al valore di una variabile per mezzo del un puntatore che punta ad essa Loperazione restituisce il valore della cella puntata (nellesempio sopra dà 7) count 7 7 countPtr
3
2000 Prentice Hall, Inc. All rights reserved. 7.2 - Dichiarare e inizializzare i puntatori Dichiarazioni di puntatori –Si possono dichiarare puntatori a qualsiasi tipo di dato, ma va sempre specificato quale sia tale tipo Non ha senso quindi parlare di tipo puntatore, non è un tipo di variabile E il classico esempio di tipo derivato I tipi di dato puntabili sono i soliti: char, int, float, double, ecc.. –Per dichiarare una variabile puntatore si usa il simbolo * int *myPtr; Dichiara un puntatore myPtr ad int (puntatore di tipo int *) Può puntare solo ad una cella di memoria che contiene una variabile intera –Per dichiarare più puntatori in una riga servono molteplici * int *myPtr1, *myPtr2; –I puntatori si possono inizializzare con 0, NULL, o con un indirizzo Se si usa 0 o NULL, non fanno riferimento a nessun dato (si preferisce NULL ) Si può anche inizializzare un puntatore con un indirizzo di una variabile non ancora inizializzata
4
2000 Prentice Hall, Inc. All rights reserved. 7.3 - Operatori per i puntatori (1/4) Operatore di indirizzo: & –Restituisce lindirizzo di memoria del suo operando, che è una variabile –Loperando può essere un puntatore ma non una costante o unespressione int y = 5; int *yPtr; yPtr = &y; //yPtr assume lindirizzo di y Da questo punto in poi yPtr punta a y e quindi yPtr e &y sono alias –Nota: Il tipo pointer non è compatibile con gli altri, quindi assegnamenti come double x = yptr non si possono fare, così come double x=&y yPtr y 5 500000600000 y 5 Lindirizzo di y è il valore yPtr
5
2000 Prentice Hall, Inc. All rights reserved. 7.3 - Operatori per i puntatori (2/4) Operatore di deriferimento: * –Restituisce il valore contenuto nella variabile puntata dal suo operando, che è necessariamente una variabile puntatore (mai una costante) –Di fatto variabile puntata e deriferimento del puntatore sono alias Usare *yPtr o y in una istruzione è indifferente (perché yPtr punta a y ) –* può quindi essere usato per eseguire assegnamenti Essendo un alias, il deriferimento del puntatore alla variabile da assegnare può essere sostituito alla variabile stessa *yPtr = 7; //aggiorna y a 7, come y=7 x = *yPtr; //aggiorna x a 7, come x=y Specifica di conversione %p –Serve a stampare a video un indirizzo di memoria, convertito in un formato che generalmente è un intero esadecimale –Essendo alias, sia &y che yPtr sono quindi stampabili in tale modo printf(Indirizzo di y: %p,&y); //Stampa 001F2BB4 printf(Valore di yPtr: %p,yPtr); //Stampa 001F2BB4
6
2000 Prentice Hall, Inc. All rights reserved. 7.3 - Operatori per i puntatori (3/4) * e & sono operatori inversi –Se combinati in cascata in qualsiasi ordine si annullano a vicenda –Se yPtr = &y allora *&yPtr &*yPtr yPtr *&yPtr é alias di yPtr –Sapendo che lindirizzo di qualsiasi variabile coincide con un puntatore a tale variabile e che questo vale anche per le variabili puntatori stesse [* (&yPtr)] [* (indirizzo di yPtr)] [* (puntatore a yPtr)] [yPtr] &*yPtr é alias di yPtr [& (*yPtr)] [& (y)] [indirizzo di y] [puntatore a y] [yPtr]
7
2000 Prentice Hall, Inc. All rights reserved. 7.3 - Operatori per i puntatori (4/4) 1/* Fig. 7.4: fig07_04.c – Uso degli operatori & e * */ 2#include 3 4int main(){ 5 int a; /* è un intero */ 6 int *aPtr; /* è un puntatore ad un intero */ 7 8 a = 7; 9 aPtr = &a; /* Assegna ad aPtr lindirizzo di a ->Punta ad a */ 10 printf( "Lindirizzo di a è %p" 11 "\nIl valore di aPtr è %p", &a, aPtr ); 12 printf( "\n\nIl valore di a è %d" 13 "\nIl valore di *aPtr è %d", a, *aPtr ); 14 printf( "\n\nDimostrazione che * e & sono operatori inversi.\n " 15 "&*aPtr = %p\n*&aPtr = %p\n", &*aPtr, *&aPtr ); 16 return 0; 17} 1. Dichiara le variabili 2. Inizializza le variabili 3. Stampa le varie casistiche Visualizzazione del programma Lindirizzo di a è 0012FF88 Il valore di aPtr è 0012FF88 Il valore di a è 7 Il valore di *aPtr è 7 Dimostrazione che * e & sono operatori inversi. &*aPtr = 0012FF88 *&aPtr = 0012FF88 Lindirizzo di a è il valore di aPtr. Loperatore * restituisce un alias della variabile puntata dalloperando. aPtr punta ad a, quindi *aPtr è alias di a. Fa notare come * e & siano inverse
8
2000 Prentice Hall, Inc. All rights reserved. 7.4 - Passare alle funzioni i parametri per riferimento (1/2) Si passano/usano i puntatori come parametri –Permettono di accedere al valore reale in memoria delle variabili e quindi alla fine della funzione ogni modifica ai parametri ha effetto sugli originali –Si passa alla funzione lindirizzo degli argomenti (ogni variabile che è un parametro attuale da inviare alla funzione) usando loperatore & –Nel prototipo/definizione della funzione i parametri formali sono puntatori –I vettori non sono passati con & perché il loro nome è già un puntatore Passare come parametro attuale vett equivale a passare &vett[0], sono alias Avere come parametro formale int vett[] equivale ad avere int *vett, sono alias Dentro la definizione di funzione, loperatore * –Si usa per dereferenziare il puntatore (parametro formale) e ottenere così un alias della variabile passata per indirizzo da usare poi nella funzione void raddoppia(int *numero){ //idem per il prototipo in *numero = 2 * (*numero); //cui si può usare (int *) } //senza il nome del puntatore *numero è un alias della variabile passata e come essa contiene quindi un intero, mentre numero punta alla variabile (contiene un indirizzo di memoria) Nel caso di vettori, invece, dentro la definizione di funzione * non va usato
9
2000 Prentice Hall, Inc. All rights reserved. 7.4 - Passare alle funzioni i parametri per riferimento (2/2) 1/* Fig. 7.7: fig07_07.c 2 Eleva al cubo una variabile usando una chiamata per riferimento 3#include 4 5void cuboPerRiferimento( int * ); /* prototipo */ 6 7int main(){ 8 int numero = 5; 9 10 printf( Il valore originale del numero è %d", numero ); 11 cuboPerRiferimento( &numero ); 12 printf( "\nIl nuovo valore del numero è %d\n", numero ); 13 return 0; 14} 15 16void cuboPerRiferimento( int *nPtr ){ 17 *nPtr = *nPtr * *nPtr * *nPtr;/* eleva al cubo number nel main */ 18} Il valore originale del numero è 5 Il nuovo valore del numero è 125 1. Prototipo – prende un puntatore a int 2. Chiama la funzione passando number per riferimento 3. Definisce la funzione che ha per parametro formale un puntatore Visualizzazione del programma Dentro cubeByReference, è usato *nPtr come alias di number. Si passa lindirizzo di number - cubeByReference aspetta un puntatore (indirizzo di variabile). Così facendo non serve più che la funzione ritorni qualcosa.
10
2000 Prentice Hall, Inc. All rights reserved. 7.5 - Usare il qualificatore const con i puntatori (1/2) Qualificatore const –Se anteposto a una variabile nella dichiarazione, essa va inizializzata in contemporanea alla dichiarazione ed il suo valore non può essere cambiato –È buona norma usare const per le variabili di una funzione se per certo questa non ha mai bisogno di cambiarne il valore in itinere –Tentare poi di cambiare una const genera un errore di compilazione Puntatori const –Puntano sempre alla stessa locazione di memoria, essa non può cambiare –Devono essere inizializzati per forza quando vengono dichiarati int *const myPtr = &x; Puntatore costante ad int: x può essere modificata, *Ptr no! const int *myPtr = &x; Puntatore (non const) a const int: x non può essere cambiata, *Ptr si! const int *const Ptr = &x; Puntatore costante a const int: né x nè *Ptr possono essere cambiati
11
2000 Prentice Hall, Inc. All rights reserved. 7.5 - Usare il qualificatore const con i puntatori (2/2) 1/* Fig. 7.13: fig07_13.c 2 Tentare di modificare un puntatore costante a dati variabili */ 3#include 4 5int main(){ 6 int x, y; 7 8 int * const ptr = &x; /* ptr è un puntatore costante a int. 9 Un intero può essere modificato tramite 10 ptr, ma ptr punta sempre alla stessa 11 locazione di memoria. */ 12 *ptr = 7; 13 ptr = &y; 14 return 0; 15} FIG07_13.c: Error E2024 FIG07_13.c 16: Cannot modify a const object in function main *** 1 errors in Compile *** 1. Dichiara le variabili 2. Dichiara il puntatore const ad int 3. Cambia *ptr (che è alias di x ) 4. Tenta di cambiare lindirizzo in ptr Visualizzazione del programma cambiare *ptr è permesso perchè x non è una costante Cambiare ptr è e dà un errore - ptr è un puntatore costante
12
2000 Prentice Hall, Inc. All rights reserved. Lordinamento a bolle usando i puntatori –Ordina gli elementi due a due per ogni passata, come al solito –Usa la funzione swap fare ordinamenti parziali due a due quando serve –La swap deve ricevere in input gli indirizzi (con &) degli elementi del vettore da scambiare per farlo direttamente nellambiente del chiamante Gli elementi del vettore sono quindi passati a swap per riferimento –Usando i puntatori e loperatore *, swap può ricevere i due elementi del vettore da riordinare e scambiarli direttamente anche nel vettore esterno Non necessita di ricevere il vettore, ma solo i due elementi da scambiare Col passaggio per valore non si potrebbe delegare lo scambio ad una funzione esterna, lalternativa è fare anche lo scambio dentro la funzione bubbleSort Pseudocodice Inizializza il vettore Stampa i dati nellordine originale Chiama la funzione per lordinamento a bolle Stampa il vettore ordinato Definisce lordinamento a bolle 7.6 - Lordinamento Bubble Sort tramite una chiamata per riferimento (1/3)
13
2000 Prentice Hall, Inc. All rights reserved. 7.6 - Lordinamento Bubble Sort tramite una chiamata per riferimento (2/3) 1/* Fig. 7.15: fig07_15.c 2 Questo programma inserisce dei valori in un vettore, ordina i 3 valori in modo ascendente, e visualizza il vettore risultante. */ 4#include 5#define SIZE 10 6void bubbleSort( int *, const int ); 7 8int main(){ 9 int i, a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 10 11 printf( Elementi nellordine originale\n" ); 12 for ( i = 0; i < SIZE; i++ ) printf( "%4d", a[ i ] ); 13 bubbleSort( a, SIZE ); /* ordina il vettore */ 14 printf( "\nElementi in ordine crescente\n" ); 15 for ( i = 0; i < SIZE; i++ ) printf( "%4d", a[ i ] ); 16 printf( "\n" ); 16 return 0; 17} 18 1. Inizializza il vettore 2. Stampa il vettore originale 3. Invoca bubbleSort 4. Stampa il vettore ordinato bubbleSort di fatto si aspetta di riceve un puntatore. Non a caso, perchè il nome di un vettore è un puntatore che contiene lindirizzo del primo elemento del vettore
14
2000 Prentice Hall, Inc. All rights reserved. 21 int pass, j; 22 for ( pass = 0; pass < size - 1; pass++ ) 23 for ( j = 0; j < size - 1; j++ ) 24 if ( vettore[ j ] > vettore[ j + 1 ] ) 25 swap( &vettore[ j ], &vettore[ j + 1 ] ); 26} 27 28void swap( int *elemento1Ptr, int *elemento2Ptr ){ 29 int temp = *elemento1Ptr; 30 *elemento1Ptr = *elemento2Ptr; 31 *elemento2Ptr = temp; 32} 19void bubbleSort( int *vettore, const int size ){ 20 void swap( int *, int * ); 5. Definizioni delle funzioni Visualizzazione del programma Elementi nellordine originale 2 6 4 8 10 12 89 68 45 37 Elementi in ordine crescente 2 4 6 8 10 12 37 45 68 89 7.6 - Lordinamento Bubble Sort tramite una chiamata per riferimento (3/3) Dentro la swap uso i puntatori con deferimento per lavorare su alias delle variabili originali perché tali puntatori puntano proprio alle variabili passate. I singoli elementi di un vettore sono come variabili comuni e quindi passarli per riferimento necessita luso di &
15
2000 Prentice Hall, Inc. All rights reserved. 7.7 - Le espressioni con i puntatori e laritmetica dei puntatori (1/3) Le operazioni aritmetiche possono agire anche su puntatori –Incrementare/decrementare del puntatore ( ++ o -- ) –Aggiungere/togliere un intero al puntatore ( + o +=, - o -= ) –I puntatori possono essere sottratti gli uni dagli altri –Tuttavia, esse hanno senso solo se eseguite su un vettore perché solo in tal caso si è certi di operare sempre su dati in celle di memoria consecutive Somma di un intero ad un puntatore e incremento –Dato un vettore di 5 elementi int su una macchina che usa 4 byte per ogni intero, se vPtr punta al primo elemento v[0] con locazione 3000 vPtr = 3000 vPtr+=2 pone vPtr = 3008 e quindi da ora vPtr punta a v[2] (lelemento con indice incrementato di 2) Variabile puntatore vPtr v[0]v[1]v[2]v[4]v[3] 30003004300830123016 Locazione
16
2000 Prentice Hall, Inc. All rights reserved. Somma di un intero ad un puntatore a vettore –Dopo aver dichiarato un puntatore vPtr al vettore v[], essi diventano alias –Inizialmente vPtr punta a v[0], ma in seguito ad unistruzione vPtr+=j; vPtr punterà sempre a v[j], perché conterrà lindirizzo &v[0]+j*(byte_rapp_tipo) –Ecco perchè lespressione *(vPtr+j) restituisce sempre un alias di v[j] –Lesito di tale operazione è comunque indipendente dal numero di byte con cui il calcolatore memorizza il tipo del vettore puntato dal puntatore –Per conoscere la rappresentazione interna di tale tipo si può usare sizeof La funzione sizeof –Ritorna la dimensione del suo operando in bytes –Se loperando è un vettore, ritorna la dimensione in byte di un elemento moltiplicata per il numero totale di elementi (dimensione del vettore) int mioArray[10]; printf( "%d", sizeof( mioArray ) ); Se sizeof(int) restituisce 4 bytes, allora la printf stamperà 40 –Gli operandi di sizeof possono essere nomi di variabili, nomi di tipi (come sopra) o valori costanti 7.7 - Le espressioni con i puntatori e laritmetica dei puntatori (2/3)
17
2000 Prentice Hall, Inc. All rights reserved. Sottrazione di puntatori –Restituisce il numero degli elementi compresi tra quelli puntati dai due puntatori (ovvero in pratica tra i due indici del vettore) Dato vPtr2 = &v[2] e vPtr1 = &v[0] vPtr2 – vPtr1 dà 2 Confronto di puntatori ( ) –Si usa per riconoscere quale puntatore punta allelemento del vettore con lindice più alto o per verificare se un puntatore punta a 0( se è NULL) Solo se sono dello stesso tipo, i puntatori possono essere assegnati uno allaltro –Se non fossero dello stesso tipo, si deve fare un cast per convertire di forza il tipo di quello a destra dellassegnamento nel tipo di quello di sinistra –Unica eccezione: il puntatore a void (con tipo void * ) E un puntatore generico, rappresenta qualsiasi tipo, per cui ad un puntatore a void si può assegnare qualsiasi altro tipo di puntatore (senza conversioni) Lo stesso viceversa, un puntatore void può essere assegnato a tutti gli altri tipi di puntatori senza effettuare alcun cast esplicito Però sui puntatori void non si può però applicare loperatore di deriferimento 7.7 - Le espressioni con i puntatori e laritmetica dei puntatori (3/3)
18
2000 Prentice Hall, Inc. All rights reserved. 7.8 - La relazione tra puntatori e vettori Vettori e puntatori sono strettamente correlati –Il nome di un vettore può essere visto come un puntatore costante al vettore –I puntatori possono essere usati per svolgere operazioni che coinvolgono gli indici di un vettore, compresa lindicizzazione del vettore stesso –Ad un puntatore posso assegnare o (con &) lindirizzo di un elemento di un vettore o il vettore intero stesso Dato un vettore b[] e un puntatore bPtr, è equivalente –Assegnare bPtr = b; dato che il nome è lindirizzo del primo elemento –Assegnare bPtr = &b[0]; usando lindirizzo del primo elemento Essendo b e bPtr alias, lelemento b[n] si può accedere –Con la notazione puntatore + offset: *( bPtr + n ) dove n è loffset –Usando sul vettore laritmetica dei puntatori, dato che anchesso lo è: *(b + n), equivalente a *(bPtr + n) somma di un intero al puntatore Da cui lindirizzo di un elemento del un vettore si ottiene con lo stesso principio: &b[n] equivale a bPtr + n per lauto-annullamento tra * e & combinati –Con la notazione puntatore + indice: bPtr[n] equivale a *(bPtr + n) I puntatori possono essere indicizzati come i vettori corrispondenti
19
2000 Prentice Hall, Inc. All rights reserved. 7.9 - Vettori di puntatori I vettori possono contenere a loro volta dei puntatori –Ogni elemento/cella del vettore contiene non un dato ma un indirizzo di memoria di unaltra variabile (punta ad un dato esterno al vettore) Lapplicazione più comune è creare un vettore di stringhe, finora realizzato esclusivamente come array bidimensionale char *suit[4] = {Hearts", Diamonds", Clubs", Spades" }; –char * ogni elemento del vettore suit è un puntatore ad un char –Il vettore non contiene realmente le stringhe ma solo puntatori alle stringhe –Una stringa è un vettore di caratteri salvati in indirizzi di memoria contigui Per accedere alla stringa è sufficiente un puntatore al suo primo carattere –Il vettore ha ovviamente una dimensione prestabilita, ma ora le singole stringhe possono avere dimensioni qualsiasi (ognuna diversa dalle altre) suit[3] suit[2] suit[1] suit[0]Hearts \0 Diamonds Clubs Spades
20
2000 Prentice Hall, Inc. All rights reserved. 7.10 - Caso di studio: simulare un mescolatore/distributore di carte (1/5) Il programma mescola e distribuisce le carte a 2 giocatori –Usa due vettori di stringhe correlati per identificare ogni carta da gioco (semi per i semi, figure per la figura), implementati come vettori di puntatori –Usa un vettore bidimensionale mazzo per rappresentare il mazzo di carte –Gli elementi della matrice contengono numeri in [1,52], che rappresentano la posizione di ogni singola carta nel mazzo –Questo sarà poi lordine con cui le carte verranno distribuite ai giocatori Ne viene data una a testa partendo dalla prima (in cima al mazzo) mazzo[2][12] rappresenta il Re di Fiori e indica che questa è la prima carta del mazzo Cuori Quadri Fiori Picche 0 1 2 3 AssoDueTreQuattroCinqueSeiSetteOttoNoveDieciJackReginaRe 0123456789101112 Fiori Re 1
21
2000 Prentice Hall, Inc. All rights reserved. 7.10 - Caso di studio: simulare un mescolatore/distributore di carte (2/5) Pseudocodice – Livello Top : mescola e distribuisci 52 carte Per ognuna delle 52 carte Assegna la sua posizione nel mazzo selezionando in modo casuale una carta non ancora inserita nel mazzo, ovvero una posizione casuale di deck tra quelle non ancora occupate Per ognuna delle 52 carte Trova nella matrice deck la carta avente la posizione specificata e stampane face/suit corrispondenti Scegli casualmente una posizione di deck Mentre la posizione di deck appena scelta è già occupata Scegli casualmente unaltra posizione Metti il numero di posizione corrente nel mazzo nella posizione libera scelta di deck Per ogni posizione del vettore deck Se contiene la posizione specificata stampa i relativi face/suit della carta corrispondente a tale posizione Secondo rifinimento Terzo rifinimento Primo rifinimento Inizializza il vettore suit Inizializza il vettore face Inizializza il vettore deck Mescola deck Distribuisci le 52 carte
22
2000 Prentice Hall, Inc. All rights reserved. 7.10 - Caso di studio: simulare un mescolatore/distributore di carte (3/5) 1/* Fig. 7.24: fig07_24.c 2 Programma per mescolare/distribuire delle carte da gioco */ 3#include 4#include 5#include 6 7void mescolaCarte( int [][ 13 ] ); 8void daiCarte( const int [][ 13 ], const char *[], const char *[] ); 9 10int main(){ 11 const char *semi[ 4 ] = 12 { Cuori", Quadri", Fiori", Picche" }; 13 const char *figure[ 13 ] = 14 { "Asso", "Due", Tre", Quattro", 15 Cinque", Sei", "Sette", Otto", 16 "Nove", Dieci", "Jack", Regina", Re" }; 17 int mazzo[ 4 ][ 13 ] = { 0 }; 18 19 srand( time( 0 ) ); 20 merscolaCarte( mazzo ); 21 daiCarte( mazzo, figure, semi ); 22 return 0; 23} 24 1. Inizializza i vettori suit, face e deck 2. Chiama shuffle per mescolare 3. Chiama deal per distribuire le carte
23
2000 Prentice Hall, Inc. All rights reserved. 7.10 - Caso di studio: simulare un mescolatore/distributore di carte (4/5) 29 do { 30 riga = rand() % 4; 31 colonna = rand() % 13; 32 } while( wMazzo[ riga ][ colonna ] != 0 ); 33 wMazzo[ riga ][ colonna ] = pos_carta; 34 } 35} 36 37void daiCarte( const int wMazzo[][ 13 ], const char *wFigure[], 38 const char *wSemi[] ){ 39 int pos_carta, riga, colonna; 40 41 for ( pos_carta = 1; pos_carta <= 52; pos_carta++ ) 42 for ( riga = 0; riga <= 3; riga++ ) 43 for ( colonna = 0; colonna <= 12; colonna++ ) 44 if ( wMazzo[ riga ][ colonna ] == pos_carta ) 45 printf( "%7s of %-8s%c", 46 wFigure[ colonna ], wSemi[ riga ], 47 pos_carta % 2 == 0 ? '\n' : '\t' ); 48} 25void mescolaCarte( int wMazzo[][ 13 ] ){ 26 int riga, colonna, pos_carta; 27 28 for ( pos_carta = 1; pos_carta <= 52; pos_carta++ ){ 4. Definisce le funzioni 5. Per ogni posizione nel mazzo, continua a generare carte in modo casuale finchè non ne trova una che non è ancora stata inserita nel mazzo 6. Simulazione della distribuzione di carte a 2 giocatori 6.1. Per ogni posizione nel mazzo, cerca tale posizione dentro la matrice delle carte e ne stampa suit e face 6.3. Usa un formato di stampa particolare per simulare una carta a me, una a te I numeri 1-52 (le posizioni delle carte) sono messi nel vettore mazzo casualmente Cerca in mazzo la carta che ha la posizione indicata e quindi ne stampa figure e semi.
24
2000 Prentice Hall, Inc. All rights reserved. 7.10 - Caso di studio: simulare un mescolatore/distributore di carte (5/5) Sei di Fiori Sette di Quadri Asso di Picche Asso di Quadri Asso di Cuori Regina di Quadri Regina di Fiori Sette di Cuori Dieci di Cuori Due di Fiori Dieci di Picche Tre di Picche Dieci di Quadri Quattro di Picche Quattro di Quadri Dieci di Fiori Sei di Quadri Sei di Picche Otto di Cuori Tre di Quadri Nove di Cuori Tre di Cuori Due di Pichhe Sei di Cuori Cinque di Fiori Otto di Fiori Due di Quadri Otto di Picche Cinque di Picche Re di Fiori Re di Quadri Jack di Picche Due di Cuori Regina di Cuori Asso di Fiori Re di Picche Tre di Fiori Re di Cuori Nove di Fiori Nove di Picche Quattro di Cuori Regina di Picche Otto di Quadri Nove di Quadri Jack di Quadri Sette di Fiori Cinque di Cuori Cinque di Quadri Quattro di Fiori Jack di Cuori Jack di Fiori Sette di Picche Visualizzazione del programma
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.