[C] Lezione 2

In questa lezione vedremo:

- come formulare una condizione;

- come costruire un ciclo;

- vari tipi di operatori.

Condizioni if () else e switch ()

 

Sappiamo già cosa sono le condizioni. Ecco un esempio con if ():

 

#include <stdio.h>

#include <stdlib.h>

 

int main() {

    int var;

    scanf("%d", &var);

    if (var == 10) {

        printf("var e' uguale a 10\n");

    }

    if (var < 10) {

        printf("var e' minore di 10\n");

    }

    if (var > 10) {

        printf("var e' maggiore di 10\n");

    }

    if (var != 10) {

        printf("var e' diverso da 10\n");

    }

    if (var <= 10) {

        printf("var e\' minore o uguale a 10\n");

    }

    if (var >= 10) {

        printf("var e' maggiore o uguale a 10\n");

    }

 

    if (var == 100) printf("var e\' uguale a 100\n");

    else printf("var e\' diverso da 100\n");

 

    system("PAUSE > NUL");

    return 0;

 

}

 

Sembra essere stato chiaro l'esempio. Le graffe sono obbligatorie se if () deve eseguire più di una istruzione. Inoltre nella condizione sono cosentite assegnazioni, esecuzioni di funzioni ecc... Se il comando è andato a buon fine o la condizione è vera ritornerà true (1), altrimenti ritornerà false (0). Il segno di not (!) ribalta il valore della condizione, quindi true diventa falsefalse diventa true. Ad esempio dire:

 

if (!(var > 4)) {...} // Se var non è maggiore di 4 ...

 

E' come dire:

 

if (var <= 4) {...} // Se var è minore o uguale a 4 ...

 

Quando si usa ! davanti a una condizione si consiglia mettere le parentesi tonde ( )

 

 

&& unisce due o più condizioni, e ritorna true solo se tutte le condizioni sono vere. 

|| unisce due o più condizioni, e ritorna true solo se almeno una condizione è vera.

 

Per non fare casini è buona abitudine mettere le parentesi fra due condizioni. Esempio:

 

if ((var == 4) || ((var == 2) && (var2 == 2))) {...}

 

switch () crea condizioni, ma solo su una variabile. Si utilizza così:

 

#include <stdio.h>

 

int main() {

    int var;

    scanf("%d", &var);

 

    switch (var) { // Condizioni su var

        case 0: printf("Hai inserito 0"); // Se vale 0 ...

        case 1: printf("Hai inserito 1"); // Se vale 1 ...

        case 2: {

            printf("Hai inserito 2");

        } // Si possono mettere le parentesi graffe

    }

    return 0;

 

E' più conveniente e veloce che mettere tanti if. default si mette alla fine, ed esegue le istruzioni con qualsiasi valore inserito. Se si usa default, è necessario utilizzare break, un'istruzione che ci permette di uscire dallo switch senza eseguire le istruzioni al suo interno.

 

#include <stdio.h>

 

int main() {

    int var;

    scanf("%d", &var);

 

    switch (var) {

        case 0:

            printf("Hai inserito 0");

            break;

        case 1:

            printf("Hai inserito 1");

            break;

        case 2:

            printf("Hai inserito 2");

            break;

        default:

            printf("Hai inserito un numero maggiore di 2 o minore di 0");

            break;

    }

    return 0;

}

 

 

Il ciclo while () (o do while ())

 

Un ciclo while ci permette di ripetere una o più istruzione fino a che la condizione fra parentesi non diventa falsa.

 

char Stringa[256];

while (!(Stringa[0] == 'P' && Stringa[1] == 'a' && Stringa[2] == 's' && Stringa[3] == 's' && Stringa[4] == 'w' && Stringa[5] == 'o' && Stringa[6] == 'r' && Stringa[7] == 'd' && Stringa[8] == '\0'))

{

    fflush(stdin);
    printf("Inserisci la chiave per uscire: ");
    scanf("%s", Stringa);
}

printf("[Fine esecuzione]");

 

\0 è il carattere nullo, e Stringa[8] == '\0' ci serve per capire se la stringa non è più lunga di 8 caratteri (9 con il carattere nullo). Output:

 

Inserisci la chiave per uscire: Ciccio

Inserisci la chiave per uscire: Passwordaaaa

Inserisci la chiave per uscire: Password

[Fine esecuzione]

 

In alternativa a while si può usare il do while, che invece di controllare la condizione prima delle istruzioni, controlla la condizione dopo aver eseguito le istruzioni:

 

int var;

do {

     printf("Inserisci la chiave numerica per uscire: ");
    scanf("%d", &var);
} while (var != 14);

printf("[Fine esecuzione]");

 

Qua è preferibile usare do while invece di while, perché quando si dichiara una variabile senza assegnargli un valore, questo allora assume un valore casuale, ed è possibile che questo sia 14 (una possibilità su 4294967296 in questo caso).

 

 

Come controllare che il buffer da tastiera sia vuoto e come svuotarlo

 

Funzioni come scanf e getchar possono scrivere su un buffer alcuni valori. Osserviamo l'esempio:

 

char var[2];

 

printf("Inserisci un carattere: ");

var[0] = getchar();

 

printf("Inserisci un altro carattere: ");

var[1] = getchar();

 

printf("[Fine esecuzione]");

 

Output:

 

Inserisci un carattere: a

Inserisci un altro carattere: [Fine esecuzione]

 

Cosa è successo? Perché non ha chiesto il secondo carattere? Pensateci: avete inserito due caratteri, non uno solo. Il secondo carattere è \n (ovvero l'accapo, quando avete premuto Invio). Infatti, il primo getchar assegna a var[0] il primo carattere inserito (a) e copia il carattere rimanente nel buffer. Il secondo getchar prende il carattere dal buffer, evitando così di chiederlo all'utente. Ecco come ovviare al problema:

 

char var[2];

 

printf("Inserisci un carattere: ");

var[0] = getchar();

 

if (var[0] != '\n')

    while (getchar() != '\n'); // In questo modo svuota il buffer

 

printf("Inserisci un altro carattere: ");

var[1] = getchar();

 

// Qui è inutile svuotare il buffer dato che non si usa più getchar

 

printf("[Fine esecuzione]");

 

Se var[0] è uguale a \n, vuol dire che non c'è buffer, perché quando si inserisce una stringa da tastiera, l'ultimo carattere è sempre \n. Ma se var[0] invece è diverso da \n, c'è necessariamente almeno un valore nel buffer. Quindi, ripetiamo la funzione getchar finché questa non è uguale a \n, perché vuol dire che abbiamo raggiunto la fine del buffer, quindi lo abbiamo svuotato tutto!

 

 

Il ciclo for ()

 

L'obiettivo principale del ciclo for è come quello del while, ovvero, ripetere le stesse istruzioni più volte. Ma, a differenza del while, qui troviamo un'assegnazione iniziale (inizio), una condizione, che viene controllata ad ogni iterazione, e se è falsa finisce il ciclo (fine), e un'assegnazione che si ripete ad ogni iterazione (incremento o decremento). Esempio:

 

int i; // i sta per Indice

for (i = 0 /* inizio */; i < 20 /* condizione */; i = i + 1 /* incremento */)

    printf("%d", i); // Scrive i numeri da 0 a 19

 

(senza commenti)

 

int i;

for (i = 0; i < 20; i = i + 1)

    printf("%d", i);

 

Altro esempio:

 

int i, j, Matrice[10][10]; // Si possono dichiarare più variabili

                           // nella stessa riga solo se sono dello

                           // stesso tipo.

for (i = 0; i < 10; i = i + 1)

    for (j = 0; j < 10; j = j + 1)

        Matrice[i][j] = i * j;

 

 

Il C ci permette di scrivere gli incrementi/decrementi in altri modi:

a++ o ++a : incrementa di un'unità.

a += x : incrementa di x unità

a-- o --a : decrementa di un'unità

a -= x : decrementa di x unità

a *= x : moltiplica a per x

a /= x : divide a per x

 

Gli operatori ++ e -- possono essere sia preposti che posposti, ma il loro significato non è lo stesso. Osserviamo l'esempio:

 

int a, b;

a = 0, b = 0; // Anche le assegnazioni si possono fare nella

              // stessa riga.

printf("++a: %d\nb++: %d", ++a, b++);

 

Output:

 

++a: 1

b++: 0

 

Infatti, con ++a la variabile viene prima incrementata, e poi usata, mentre con b++, la variabile viene prima usata e poi incrementata.

 

 

L'operatore ternario

 

L'operatore ternario funziona esattamente come un if (x) y else z.

 

int var, cond;

cond = 0;

var = (cond == 1) ? 0 : 1;

// cond è uguale a 1? Se è così 0, altrimenti 1.

printf("%d", var); // Stampa 1

 

Questo operatore può farvi risparmiare spazio nel codice, ma la velocità di esecuzione è pressoché identica a quella di un if (x) y else z.

 

<--- Torna alla lezione 1   |   Passa alla lezione 3 --->