430 likes | 713 Views
Puntatori. Potenti, ma difficili da tenere sotto controllo Stare bene attenti!!! Simulano call-by-reference Legame stretto con array e stringhe. count. countPtr. count. 7. 7. Variabili puntatore e loro dichiarazione. Variabili puntatore Contengono indirizzi di memoria come valori
E N D
Puntatori • Potenti, ma difficili da tenere sotto controllo • Stare bene attenti!!! • Simulano call-by-reference • Legame stretto con array e stringhe
count countPtr count 7 7 Variabili puntatore e loro dichiarazione • Variabili puntatore • Contengono indirizzi di memoria come valori • Variabili normali contengono un valore specifico (direct reference) • Puntatori contengono indirizzo di una variabile che ha valore specifico (indirect reference) • Dichiarazioni di Puntatori • * indica che una variabile è un puntatore • int *myPtr; • dichiara un puntatore ad int, puntatore di tipo int * • Puntatori multipli richiedono asterischi multipli • int *myPtr1, *myPtr2; // myPtr2 e’ int * • int *myPtr1, myPtr2; // myPtr2 e’ int
Dichiarazione ed inizializzazione di variabili puntatore • Possibile dichiarare puntatori ad ogni tipo di dato (int, float, double, char, array, …) • Inizializzazione di puntatori • Possono essere inizializzati a 0, NULL, o ad un indirizzo • 0 o NULL non puntano a niente • 0 preferibile (cast) • Consiglio: • Includere sempre Ptr in nome di var puntatore…
y yptr y 5 500000 yPtr 600000 5 yptr dà indirizzo di y Operatori su puntatori • & (address operator) • Restituisce l’indirizzo del suo operando • Esempio int y = 5;int *yPtr;yPtr = &y; // yPtr gets address of y • yPtr “punta a” y 600000 int y = 5; int *yPtr; yPtr = &y;
Operatori su puntatori • * (indirection/dereferencing operator) • Restituisce il valore puntato dall’operando • Se yPtr punta a y, *yPtr restituisce y. • * Può essere usato per assegnare un valore ad una locazione di memoria *yptr = 7; // changes y to 7 • Puntatore deferenziato (operando di *) deve essere un lvalue (no costanti!) • * e & sono inversi l’uno dell’altro! • I loro effetti si cancellano: *&myVar == myVar and &*yPtr == yPtr
1 // Fig. 5.4: fig05_04.cpp L’indirizzo di a è il valore di aPtr. 2 // Using the & and * operators 3 #include <iostream> 4 L’operatore * restituisce un alias a ciò che è puntato dal suo operando. aPtr punta ad a, quindi *aPtr restituisce a. 5 using std::cout; 6 using std::endl; Nota come * e & sono inversi. 7 8 int main() 9 { 10 int a; // a is an integer 11 int *aPtr; // aPtr is a pointer to an integer 12 13 a = 7; 14 aPtr = &a; // aPtr set to address of a 15 16 cout << "The address of a is " << &a 17 << "\nThe value of aPtr is " << aPtr; 18 19 cout << "\n\nThe value of a is " << a 20 << "\nThe value of *aPtr is " << *aPtr; 21 22 cout << "\n\nShowing that * and & are inverses of " 23 << "each other.\n&*aPtr = " << &*aPtr 24 << "\n*&aPtr = " << *&aPtr << endl; 25 return 0; 26 } 1. Declare variables 2 Initialize variables 3. Print Program Output The address of a is 006AFDF4 The value of aPtr is 006AFDF4 The value of a is 7 The value of *aPtr is 7 Showing that * and & are inverses of each other. &*aPtr = 006AFDF4 *&aPtr = 006AFDF4
Call-by-reference e puntatori • Call-by-reference con argomento riferimento • Passato indirizzo dell’argomento con operatore & • Consente di modificare la locazione di memoria originale • “Eccezione”: array non passati con operatore & . Perché? Nome array è un puntatore! • Call-by-reference con argomento puntatore • Utilizzare puntatori e * per simulare call-by-reference • Operatore * usato come alias di variabile dentro funzione void doubleNum( int *number ) { *number = 2 * ( *number ); } • *number usato come alias per la variabile passata • All’atto dell’invocazione della funzione, deve essere passato un indirizzo doubleNum( &myNum );
1 // Fig. 5.7: fig05_07.cpp 2 // Cube a variable using call-by-reference Nota come viene passato l’indirizzo di number - cubeByReference si aspetta un puntatore (indirizzo di una variabile). 3 // with a pointer argument 4 #include <iostream> 5 6 using std::cout; Dentro cubeByReference siusa *nPtr (*nPtr è number!). Nota che operatore unario * ha precedenza più alta rispetto ad operatore binario *: = (*nPtr) * (*nPtr) * (*nPtr); 7 using std::endl; 8 9 void cubeByReference( int * ); // prototype 10 11 int main() 12 { 13 int number = 5; 14 15 cout << "The original value of number is " << number; 16 cubeByReference( &number ); 17 cout << "\nThe new value of number is " << number << endl; 18 return 0; 19 } 20 21 void cubeByReference( int *nPtr ) 22 { 23 *nPtr = *nPtr * *nPtr * *nPtr; // cube number in main 24 } 1. Function prototype - takes a pointer to an int. 1.1 Initialize variables 2. Call function 3. Define function Program Output The original value of number is 5 The new value of number is 125
Const con puntatori • Qualificatore const • Proteggere dati della propria applicazione: definire sempre accesso con privilegi minimi! • Variabile const non può essere modificata • const usato quando la funzione non deve modificare una variabile • Ogni tentativo di modificare una variabile const produce un errore di compilazione
Const con puntatori Puntatoreconst • Punta sempre alla stessa locazione di memoria • Deve essere inizializzato in fase di dichiarazione • Quattro possibilità (da accesso più ampio a più ristretto): • Punt. non costante a dato non costante (i.e., parte array da modificare): int *myPtr = &x; • Punt. non costante a dato costante (i.e., parte array da non modificare): const int *myPtr = &x; • Punt. costante a dato non costante (i.e., nome di array!): int *const myPtr = &x; • Punt. costante a dato costante (i.e., array da non modificare): const int *const Ptr = &x;
1 // Fig. 5.13: fig05_13.cpp 2 // Attempting to modify a constant pointer to 3 // non-constant data Si può cambiare *ptr -- x non è costante. 4 #include <iostream> 5 6 int main() Cambiare ptr è un errore - ptr è un puntatore costante!. 7 { 8 int x, y; 9 10 int * const ptr = &x; // ptr is a constant pointer to an 11 // integer. An integer can be modified 12 // through ptr, but ptr always points 13 // to the same memory location. 14 *ptr = 7; 15 ptr = &y; 16 17 return 0; 18 } 1. Declare variables 1.1 Declare const pointer to an int. 2. Change *ptr (which is x). 2.1 Attempt to change ptr. 3. Output Program Output Error E2024 Fig05_13.cpp 15: Cannot modify a const object in function main()
1 7 for ( int pass = 1; pass < size; pass++ ) 8 9 for ( int j = 0; j < size - 1; j++ ) 10 11 if ( a[ j ] > a[ j + 1 ] ) { 12 hold = a[ j ]; Codificare questo pezzo di codice tramite funzione swap che esegue lo scambio. Che parametri passare a swap ? 13 a[ j ] = a[ j + 1 ]; 14 a[ j + 1 ] = hold; 15 } 16 } 17 2 3 void bubbleSort( int a[], int size ) 4 { 5 int hold; 6 Define bubbleSort
Bubblesort con call-by-reference • Implementare bubblesort con puntatori • Vogliamo inserire nuova funzione swap che esegue lo scambio di due elementi che non rispettano ordine • Funzione swap deve ricevere l’indirizzo (&) degli elementi dell’array • Elementi di array hanno call-by-value per default… • Con puntatori e operatore *, swap può scambiare valori di elementi array (senza sapere affatto che si tratta di array!)
Bubblesort con call-by-reference • Stesso pseudocodice: 1. Initializza array 2. Stampa dati nell’ordine originale 3. Invoca la funzione bubblesort 4. Stampa array ordinato 5. Definisci la funzione bubblesort
1 // Fig. 5.15: fig05_15.cpp 2 // This program puts values into an array, sorts the values into BubbleSort riceve l’indirizzo degli elementi dell’array (puntatore). Il nome di un array è un puntatore! 3 // ascending order, and prints the resulting array. 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 void bubbleSort( int *, const int ); 14 15 int main() 16 { 17 const int arraySize = 10; 18 int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 19 int i; 20 21 cout << "Data items in original order\n"; 22 23 for ( i = 0; i < arraySize; i++ ) 24 cout << setw( 4 ) << a[ i ]; 25 26 bubbleSort( a, arraySize ); // sort the array 27 cout << "\nData items in ascending order\n"; 28 29 for ( i = 0; i < arraySize; i++ ) 30 cout << setw( 4 ) << a[ i ]; 31 32 cout << endl; 33 return 0; 34 } 1. Initialize array 1.1 Declare variables 2. Print array 2.1 Call bubbleSort 2.2 Print array
36 void bubbleSort( int *array, const int size ) La funzione bubbleSort riceve array come puntatore a int. Perfettamente equivalente a notazione int array[]. Parametro size passato come const (principo di minimo privilegio). 37 { 38 void swap( int * const, int * const ); Il prototipo della funzione swap è incluso all’interno del corpo della funzione bubbleSort. Solo la funzione bubbleSort può invocare la funzione swap! 39 40 for ( int pass = 0; pass < size - 1; pass++ ) 41 42 for ( int j = 0; j < size - 1; j++ ) La funzione swap riceve puntatori (indirizzi di elementi di array) e li dereferenzia per modificare gli elementi originali dell’array. I puntatori sono costanti!!! 43 44 if ( array[ j ] > array[ j + 1 ] ) 45 swap( &array[ j ], &array[ j + 1 ] ); 46 } 47 48 void swap( int * const element1Ptr, int * const element2Ptr ) 49 { 50 int hold = *element1Ptr; 51 *element1Ptr = *element2Ptr; 52 *element2Ptr = hold; 53 } 3. Define bubbleSort 3.1 Define swap Program Output Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 68 89
Operatore unario sizeof • sizeof • Restituisce dimensione dell’operando in byte • In caso di array sizeof restituisce (size of 1 elemento ) * ( numero di elementi ) • Se sizeof( int ) = 4, int myArray[10]; cout << sizeof(myArray); stamperà 40 • sizeof usabile con • Nomi di variabili (non necessarie parentesi) • Nomi di tipi • Valori costanti
Indirizzo 3000 3004 3008 3012 3016 variabile punt. vPtr v[0] v[1] v[2] v[4] v[3] Aritmetica con puntatori • Aritmetica con puntatori • Incrementare/decrementare puntatore (++ o --) • Addizionare/sottrarre intero da puntatore ( + o += , - o -=) • Si possono sottrarre due puntatori • Aritmetica con puntatori ha significato solo su array (altrimenti errore logico?) • 5 element int array su PC con 4 byte int • vPtr punta al primo elemento v[ 0 ], che è nella locazione 3000 • vPtr = 3000 • vPtr += 2; • aggiorna vPtr a 3008 • vPtr punta a v[ 2 ]
Aritmetica con puntatori • Sottrazione tra puntatori • Restituisce il numero di elementi tra due indirizzi vPtr2 = v[ 2 ];vPtr = v[ 0 ];vPtr2 - vPtr == 2 • Confronto tra puntatori • Testare quale puntatore punta ad indice più alto nell’array • Testare se un puntatore punta a 0 (NULL) if ( vPtr == ‘0’ ) statement
Aritmetica con puntatori • Assegnazione di puntatori • Se puntatori non sono dello stesso tipo, bisogna usare l’operatore di cast • Eccezione: puntatore a void (tipo void *) • Puntatore generico, rappresenta ogni tipo • Non è necessario casting per assegnare un puntatore ad un puntatore void • Non è vero il contrario: puntatore void non può essere assegnato ad altro puntatore senza casting • Puntatori void non possono essere deferenziati (compilatore non sa a quanti byte dereferenziare…)
Legame tra puntatori e array • Array e puntatori strettamente correlati • Nome di array è puntatore costante! • Puntatori possono indicizzare array! • Esempio: dichiaro array int b[ 5 ] e puntatore bPtr = b • bPtr è uguale a b bptr == b • bptr è uguale all’indirizzo del primo elemento di b bptr == &b[ 0 ]
Legame tra puntatori e array • Accesso a elementi di array con puntatori • Si può accedere ad elemento b[ j ] tramite *( bPtr + j ) • Notazione puntatore/offset (precedenza * > + ) • Anche l’array può usare aritmetica con puntatori: • b[ 3 ] equivale a *( b + 3 ) • Anche i puntatori possono essere indicizzati (Notazione puntatore/indice) • bPtr[ 3 ] equivale a b[ 3 ]
’\0’ ’\0’ ’\0’ ’\0’ ’n’ ’d’ ’o’ ’u’ ’a’ ’s’ ’d’ ’b’ ’m’ ’H’ ’s’ ’a’ ’D’ ’i’ ’a’ ’s’ ’l’ ’C’ ’r’ ’s’ ’S’ ’p’ ’e’ ’t’ ’e’ suit[0] suit[1] suit[2] suit[3] Array di puntatori • Array possono contenere puntatori • Usati a volte per memorizzare array di stringhe char *suit[ 4 ] = {"Hearts", "Diamonds","Clubs", "Spades" }; • Ogni elemento suit è puntatore a char * (stringa) • Le stringhe non sono nell’array, nell’array ci sono puntatori alle stringhe: • array suit ha dimensione fissa, ma le stringhe possono essere di ogni dimensione
Ace Deuce Three Four Five Six Seven Eight Nine Ten Jack Queen King 0 1 2 3 4 5 6 7 8 9 10 11 12 0 Hearts 1 Diamonds 2 Clubs 3 Spades deck[2][12] rappresenta King of Clubs Clubs King Esempio: Mischiare e distribuire mazzo di carte • Mischiare carte • Usa array di puntatori a stringhe, per memorizzare semi • Usa array bidimensionale (seme, valore) • Per mischiare il mazzo, scrivi una permutazione di 1-52 nell’array!
Raffinamento 1 • Inizializza array suit • Inizializza array face • Inizializza array deck • Mischia il mazzo • Distribuisci 52 carte Mischiare mazzo di carte • Pseudocodice per mischiare e distribuire carte: Raffinamento 2 Raffinamento 3 Per ognuna delle 52 carte: Scegli a caso slot in array deck while (slot già scelto prima) Scegli a caso slot in array deck Scrivi numero d’ordine in slot • Per ognuna delle 52 carte: • Assegna numero d’ordine in una posizione vuota, scelta a caso, dell’array deck • Per ognuna delle 52 carte: • Trova numero d’ordine j in array deck e stampane valore (face) e seme (suit) • Per ognuna delle 52 carte: • Per ogni slot di array deck: • if (slot contiene carta) Stampane face e suit
1 // Fig. 5.24: fig05_24.cpp 2 // Card shuffling dealing program 3 #include <iostream> 4 5 using std::cout; 6 using std::ios; 7 8 #include <iomanip> 9 10 using std::setw; 11 using std::setiosflags; 12 13 #include <cstdlib> 14 #include <ctime> 15 16 void shuffle( int [][ 13 ] ); 17 void deal( const int [][ 13 ], const char *[], const char *[] ); 18 19 int main() 20 { 21 const char *suit[ 4 ] = 22 { "Hearts", "Diamonds", "Clubs", "Spades" }; 23 const char *face[ 13 ] = 24 { "Ace", "Deuce", "Three", "Four", 25 "Five", "Six", "Seven", "Eight", 26 "Nine", "Ten", "Jack", "Queen", "King" }; 27 int deck[ 4 ][ 13 ] = { 0 }; 28 29 srand( time( 0 ) ); 30 31 shuffle( deck ); 32 deal( deck, face, suit ); 33 1. Initialize suit and face arrays 1.1 Initialize deck array 2. Call function shuffle 2.1 Call function deal
34 return 0; Memorizza nell’array deck una permutazione casuale dei numeri 1-52. 35 } 36 Cerca in deck il numero card, e stampane face e suit. 37 void shuffle( int wDeck[][ 13 ] ) 38 { 39 int row, column; 40 41 for ( int card = 1; card <= 52; card++ ) { 42 do { 43 row = rand() % 4; 44 column = rand() % 13; 45 } while( wDeck[ row ][ column ] != 0 ); 46 47 wDeck[ row ][ column ] = card; 48 } 49 } 50 51 void deal( const int wDeck[][ 13 ], const char *wFace[], 52 const char *wSuit[] ) 53 { 54 for ( int card = 1; card <= 52; card++ ) 55 56 for ( int row = 0; row <= 3; row++ ) 57 58 for ( int column = 0; column <= 12; column++ ) 59 60 if ( wDeck[ row ][ column ] == card ) 61 cout << setw( 5 ) << setiosflags( ios::right ) 62 << wFace[ column ] << " of " 63 << setw( 8 ) << setiosflags( ios::left ) 64 << wSuit[ row ] 65 << ( card % 2 == 0 ? '\n' : '\t' ); 66 } 3. Define functions
Six of Clubs Seven of Diamonds Ace of Spades Ace of Diamonds Ace of Hearts Queen of Diamonds Queen of Clubs Seven of Hearts Ten of Hearts Deuce of Clubs Ten of Spades Three of Spades Ten of Diamonds Four of Spades Four of Diamonds Ten of Clubs Six of Diamonds Six of Spades Eight of Hearts Three of Diamonds Nine of Hearts Three of Hearts Deuce of Spades Six of Hearts Five of Clubs Eight of Clubs Deuce of Diamonds Eight of Spades Five of Spades King of Clubs King of Diamonds Jack of Spades Deuce of Hearts Queen of Hearts Ace of Clubs King of Spades Three of Clubs King of Hearts Nine of Clubs Nine of Spades Four of Hearts Queen of Spades Eight of Diamonds Nine of Diamonds Jack of Diamonds Seven of Clubs Five of Hearts Five of Diamonds Four of Clubs Jack of Hearts Jack of Clubs Seven of Spades Program Output
Esercizi • Distribuire le carte • 52 * 4 * 13 = (52) 2 = 2704 passi • Possibile farlo più velocemente (in 52 passi)? • Simulare giochi di carte • Sette e mezzo • Asso pigliatutto • Ruba mazzo • Scopa • Briscola • Tresette • …
Puntatori a funzioni • Contengono indirizzo di una funzione • Così come nome array è indirizzo del primo elemento… • …nome funzione è indirizzo iniziale del codice che definisce la funzione • Puntatori a funzione possono essere: • Passati a funzioni, restituiti da funzioni • Memorizzati in array • Assegnati ad altri puntatori a funzione
Puntatori a funzioni • Esempio: bubblesort • Scrivere una funzione bubble che deve ordinare array sia in senso crescente che decrescente • Può essere risolto passando alla funzione bubble come argomento un puntatore ad altra funzione che decide come fare lo swap: bool ascending ( int a, int b ) // scambia se b < a { return b < a; } bool descending ( int a, int b ) // scambia se b > a { return b > a; }
Puntatori a funzioni • Può essere risolto passando alla funzione bubble come argomento un puntatore ad un’altra funzione bool ( *compare )( int, int ) • Dice a bubble di attendersi un puntatore ad una funzione che riceve come argomenti due int e restituisce un bool • Errore: dimenticare parentesi (precedenza * < ()) bool *compare( int, int ) • Dichiara una funzione che riceve due int e restituisce un puntatore a bool…
1 // Fig. 5.26: fig05_26.cpp 2 // Multipurpose sorting program using function pointers 3 #include <iostream> Nota il parametro puntatore a funzione! 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 void bubble( int [], const int, bool (*)( int, int ) ); 14 bool ascending( int, int ); 15 bool descending( int, int ); 16 17 int main() 18 { 19 const int arraySize = 10; 20 int order, 21 counter, 22 a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 23 24 cout << "Enter 1 to sort in ascending order,\n" 25 << "Enter 2 to sort in descending order: "; 26 cin >> order; 27 cout << "\nData items in original order\n"; 28 29 for ( counter = 0; counter < arraySize; counter++ ) 30 cout << setw( 4 ) << a[ counter ]; 31 32 if ( order == 1 ) { 33 bubble( a, arraySize, ascending ); 34 cout << "\nData items in ascending order\n"; 1. Initialize array 2. Prompt for ascending or descending sorting 2.1 Put appropriate function pointer into bubblesort 2.2 Call bubble 3. Print results
35 } 36 else { 37 bubble( a, arraySize, descending ); 38 cout << "\nData items in descending order\n"; ascending e descending restituiscono true o false. bubble invoca swap se la chiamata a funzione restituisce il valore true. 39 } 40 41 for ( counter = 0; counter < arraySize; counter++ ) Nota come i puntatori a funzione sono chiamati usando l’operatore di dereferenziazione *. * non è obbligatorio, ma mette in evidenza che compare è un puntatore a funzione e non una funzione! 42 cout << setw( 4 ) << a[ counter ]; 43 44 cout << endl; 45 return 0; 46 } 47 48 void bubble( int work[], const int size, 49 bool (*compare)( int, int ) ) 50 { 51 void swap( int * const, int * const ); // prototype 52 53 for ( int pass = 1; pass < size; pass++ ) 54 55 for ( int count = 0; count < size - 1; count++ ) 56 57 if ( (*compare)( work[ count ], work[ count + 1 ] ) ) 58 swap( &work[ count ], &work[ count + 1 ] ); 59 } 60 61 void swap( int * const element1Ptr, int * const element2Ptr ) 62 { 63 int temp; 64 65 temp = *element1Ptr; 66 *element1Ptr = *element2Ptr; 67 *element2Ptr = temp; 68 } 3.1 Define functions
69 70 bool ascending( int a, int b ) 71 { 72 return b < a; // swap if b is less than a 73 } 74 75 bool descending( int a, int b ) 76 { 77 return b > a; // swap if b is greater than a 78 } 3.1 Define functions Program output Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 1 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 68 89 Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 2 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in descending order 89 68 45 37 12 10 8 6 4 2
Caratteri e stringhe • Costante di tipo carattere • Valore (intero) di un carattere • Tra apici ' ' • 'z' è il valore (intero) del carattere z, ossia 122 • Stringa • Serie di caratteri trattata come entità unica • Può includere lettere, cifre, caratteri speciali (+, -, * , …) • String literal (costanti di tipo stringa) • Tra virgolette " " , ad esempio: "Adoro il C++" • Array di caratteri, terminano con carattere null '\0' • Stringhe sono puntatori costanti (come array) • Valore della stringa è indirizzo del primo carattere • NON confondere caratteri e stringhe!!!
Caratteri e stringhe • Come assegnare stringhe • Array di caratteri: char color[] = "blue"; • Crea char array di 5 elementi, di nome color, (ultimo elemento è '\0') • Variabile di tipo char * char *colorPtr = "blue"; • Crea un puntatore alla stringa "blue", di nome colorPtr, e lo memorizza da qualche parte in memoria • Se dichiarata così, di norma la stringa non sarà modificabile • Se la si vuole modificare, dichiararla come array di char
Caratteri e stringhe • Come leggere stringhe • Assegna input a char array word[ 20 ] cin >> word • Legge caratteri fino a blank, \t, \n o EOF • Stringa potrebbe eccedere dimensione array: cin >> setw( 20 ) >> word; • Legge 19 caratteri (ultimo carattere riservato per '\0')
Caratteri e stringhe • cin.getline( ) • Legge intera linea di testo • Come si usa: cin.getline( array, size, delimiter char ); • Copia input nell’array specificato finché • Si raggiunge la dimensione – 1 (size – 1) dell’array, • Oppure incontra delimiter char o EOF • Esempio: char sentence[ 80 ]; cin.getline( sentence, 80, '\n' );
String-handlingLibrary • Libreria per stringhe <cstring> contiene funzioni per • Manipolare stringhe • Confrontare stringhe • Ricercare stringhe • “Tokenize” stringhe (separarle in pezzi logici) • ASCII character code • Confronti tra stringhe avvengono in base alla codifica dei caratteri • Semplice fare confronti (greater than, less than, equal to) • “Tokenizing” • Spezzare stringhe in token, separati da user-specified char • Token: unità logiche, come parole (separate da spazi) • "This is my string" ha 4 token (separati da spazi)
strtok( ) char text[]; … tokenPtr = strtok( text, " " ); while ( tokenPtr != NULL ) { cout << tokenPtr << endl; tokenPtr = strtok ( NULL, " " ); } …