Skillbook Logo
foto profilo

Skill Factory

Tutte le categorie


Introduzione alla logica degli oggetti - Lezione 3

Gino Visciano | Skill Factory - 06/04/2018 00:17:32 | in Tutorials

In questa lezione iniziamo a descrive in modo più dettagliato l'architettura delle applicazioni software ad oggetti.

Nella lezione precedente abbiamo visto che oggi le applicazioni software sono insiemi di componenti che collaborano tra loro per per soddisfare le specifiche funzionali richieste.

Gli oggetti che compongono le applicazioni sono di tre tipi:

1) MODEL - Contengono dati (sono entità).
2) VIEW - Hanno il compito di permettere la visualizzazione oppure l'inserimento dei dati negli oggetti di tipo MODE, ad esempio in un'applicazione Web corrispondono alle Pagine HTML, mentre in un'applicazione Desktop corrispondono alle interfacce grafiche (GUI).
3) CONTROLLER, che hanno il compito di gestire il flusso logico applicativo. Un controller può svolgere anche il ruolo di servizio, mettendo a disposizione dell'applicazioni in cui è presente, funzionalità oppure azioni specifiche, che si possono richiamare attraverso i metodi dell'interfaccia esposta.

I simboli UML (Unified Modeling Language) che si usano per indicare i tre tipi di oggetti utilizzati per creare le applicazioni software, sono i seguenti:

Il diagramma UML che descrive l'architettura di un'applicazione software si chiama "Diagramma dei Componeti".

Diagramma dei componenti che descrive il processo di login di un'applicazione.

 

COME SI CREANO I COMPONENTI DELLE APPLICAZIONI
I componenti delle applicazione software si creano con i linguaggi di programmazione ad oggetti, questi linguaggi si differenziano da quelli procedurali o funzionali perché si basano prevalentemente sull'uso di classi ed oggetti e permettono d'implemetare i seguenti paradigmi di programmazione:

1) Incapsulamento;

2) Polimorfismo di metodi ed oggetti;

3) Ereditarietà.

I principali linguaggi di programmazione ad oggetti sono:

1) C++ (pronuncia: c plus plus);

2) Java (pronuncia: giava);

3) C# (pronuncia: c sharp);

4) Python (pronuncia: paiton).

Per i nostri esempi useremo il C++ il linguaggio di programmazione ad oggetti più insegnato nelle scuole superiori.


CLASSI ED OGGETTI
Le Classi  sono template creati dai programmatori, con i linguaggi di programmazione ad oggetti, servono per creare gli oggetti.
L'esempio seguente mostra una classe scritta in C++, che definisce il template di un oggetto di tipo Persona:

class Persona {
    private:
    string nome;
    string cognome;
    int eta;
    public:
    void setNome(string nome){
            this->nome=nome;
        };
    void setCognome(string cognome){
            this->cognome=cognome;
        };
    void setEta(int eta){
            this->eta=eta;
        };
     string getNome(){
            return this->nome;
        }
     string getCognome(){
            return this->cognome;
        }
    int getEta(){
            return this->eta;
        }
    Persona(){};
    Persona(string nome, string cognome, int eta){
            this->nome=nome;
            this->cognome=cognome;
            this->eta=eta;
        }
};

<Per approfondire la conoscenza del linguaggio C clicca qui.>

 

Gli Oggeti sono istanze delle Classi, istanziare significa creare un oggetto in memoria utlizzando la classe corrispondente.
Con la stessa classe si possono creare tanti oggetti dello stesso tipo.

L'esempio seguente mostra come s'istanzia l'oggetto persona di tipo Persona:

Attenzione *persona diventerà il puntatore che conterrà l'indirizzo dove è stato allocato l'oggetto costruito con il comando new.

I metodi e gli attributi degli oggetti istanziati possono essere usati associando il nome dell'oggetto all'elemento che si vuole usare con il simbolo ->, come mostra l'esempio seguente:

persona->setNome("Mario");
persona->setCognome("Rossi");
persona->setEta(35);

Le Classi definiscono il tipo di oggetto che state usando nell'applicazione, in fase di progettazione per disegnare una classe con il linguaggio UML (Unified Modeling Language) dovete usare un "Diagramma di Classe".

L'esempio seguente mostra il diagramma di classe dell'oggetto persona:


Per convenzione i nomi delle Classi iniziano sempre con la lettera maiuscola, se sono composti da più parole, devono iniziare tutte con la lettera maiuscola.
I nomi degli Oggetti  sono sempre scritti in minuscolo, se sono composti da più parole, le altre parole devono iniziare con la lettera maiuscola.

Gli Oggetti sono  Componenti  che contengono i seguenti elementi:

- attributi
- metodi
- costruttori

I programmatori per capire come sono fatti i componenti di un'applicazione e qual è il loro stato, devono leggere rispettivamente il  "Diagrammi di Classe" e il "Diagrammi degli Oggetti".

Nell'esempio seguente, il "Diagramma di componete" a sinistra, indica che il componete applicativo persona è un MODEL.
Il "Diagramma di Classe" al centro ne descrive la struttura  ed il tipo, infatti corrisponde alla classe Persona.
Il "Diagramma di Oggetto" a destra ne descrive lo stato in memoria dopo che è stato istanziato (creato), il Titolo del diagramma: persona:Persona indica rispettivamente il nome dell'oggetto e la classe corrispondente, cioè il tipo.

 

 

INCAPSULAMENTO
L'Incapsulamento è una proprietà dei linguaggi di programmazione ad oggetti, permette di utilizzare dei modificatori di accesso per regolare la visibilità degli elementi di una classe (attributi, metodi e costruttori), verso i metodi di altre classi che vogliono usarli.

I modificatori di accesso più usati sono:

1) public (in un diagramma UML corrisponde al segno +);

2) private (in un diagramma UML corrisponde al segno -);

3) prrotected (in un diagramma UML corrisponde al segno #), si comporta come private in caso d'istanza, come public in caso di ereditarietà, come vedremo nelle prossime lezioni;


ATTRIBUTI
Gli Attributi sono variabili che contengono informazioni, si possono definire le proprietà dell'oggetto. Ad esempio nei MODEL, gli attributi si usano per memorizzare i dati delle entità corrispondenti, come mostra l'esempio seguente:


persona->nome="Mario";
persona->cognome="Rossi";
persona->eta=30;

persona contiene l'indirizzo dell'oggetto a cui facciamo riferimento;
nome è un attributo dell'oggetto.

Gli Attributi  possono essere usati direttamente, come nell'esempio, da metodi di altre classi, solo se sono pubblici (+), se gli Attributi in una classe sono privati (-)  sono visibili solo ai metodi della stessa classe.

Quindi l'unico modo per gestire gli  Attributi privati di una classe è quello di usare i Metodi ed i Costruttori pubblici presenti nella stessa classe.

 

METODI
I Metodi sono funzioni che eseguono operazioni, le azioni dei Metodi determinano il comportamento ed il ruolo dell'oggetto.
I linguaggi di programmazione ad oggetti, permettono di scrivere le istruzioni necessarie per implementare la logica delle applicazioni, unicamente all'interno dei Metodi.

I  Metodi che hanno il nome che inizia con i prefissi get e set si usano per assegnare o leggere i valori degli Attributi privati dell'oggetto a cui appartengono. 
Ad esempio,  dato che gli  Attributi della clappe  Persona sono privati, per gestirli sono stati creati i seguenti Metodi pubblici:

- setNome
- getNome
- setCognome
- getCognome
- setEta
- getEta 

Nell'esempio seguente vediamo come si possono assegnare i valori agli  Attributi privati dell'oggetto  persona usando i  Metodi  set corrispondenti:

persona->setNome("Mario");
persona->setCognome("Rossi");
persona->setEta(30);

Mentre nel prossimo esempio vediamo come si possono leggere i valori degli  Attributi privati dell'oggetto  persona usando i  Metodi  get corrispondenti:

String nome = persona->getNome();
String cognome = persona->getCognome();
int eta = persona->getEta();

I Metodi se sono pubblici possono essere eseguiti anche dai Metodi di altri oggetti, se sono privati possono essere eseguiti solo dai Metodi dello stesso oggetto, perché non sono visibili a metodi di altre classi.
 

OVERLOAD
I'Overload insieme all'Override può essere definito polimorfismo dei metodi, è una prorpietà dei linguaggi di programmazione ad oggetti che permette di usare metodi con lo stesso nome, ma firma diversa, all'interno della stessa classe.
La firma di un metodo è composta dal nome del metodo più i tipi degli argomenti passati al metodo, come mostra l'immagine seguente:

Vediamo un esempio di Overload in C++:

Immaginate di voler colorare una figura geometrica, dando la possibilità al programmatore di usare le seguenti modalità d'impostazione del colore:

1) fornire direttamente il nome del colore da assegnare alla figura geometrica sotto forma di stringa;

2) indicare il colore da assegnare alla figura geometrica con un numero intero;

3) fornire i codici RGB del colore da assegnare alla figura geometrica.

Per evitare di assegnare nomi diversi ai metodi per colorare la figura geometrica,  dato che per ogni modalità d'impostazione del colore si usano tipi sono diversi, possiamo usare l'Overload.

class ColoraFiguraGeometrica{
// Attributi privati non visibli a metodi di altre classi classi
private:
string tipoFigura;
string coloreFigura;
// Metodi pubblici visibli a metodi di altre classi classi
public:
// Restituisce il tipo di figura geometrica
string getTipoFigura(){
return this->tipoFigura;
}
// Restituisce il colore della figura geometrica
string getColoreFigura(){
return this->coloreFigura;
}
// 1-Overload Firma = setColore string
void setColore(string colore){
    this->coloreFigura=colore;
}
// 2-Overload Firma = setColore int
void setColore(int colore){
    switch(colore){
    case 1:
         this->coloreFigura="Rosso";
         break;
    case 2:
         this->coloreFigura="Verde";
         break;
    case 3:
         this->coloreFigura="Giallo";
         break;
    default:
         this->coloreFigura="Nero";
         break;
    }
}
// 3-Overload Firma = setColore int int int
void setColore(int r,int g, int b){
        stringstream sr;
        stringstream sg;
        stringstream sb;
        sr << r;
        sg << g;
        sb << b;
        this->coloreFigura="R="+sr.str()+", G="+sg.str()+"B="+sb.str();
}
// Costruttore parametrizzato usato per indicare il tipo di figura geometrica
ColoraFiguraGeometrica(string tipoFigura){
      this->tipoFigura=tipoFigura;
}
};

<Per approfondire la conoscenza del linguaggio C clicca qui.>


COSTRUTTORI
I Costruttori sono Metodi che si usano per istanziare gli oggetti, vanno sempre indicati dopo il comando new usato per creare un oggetto, come mostra l'esempio seguente:

 

 

I Costruttori servono per inizializzare gli Attributi degli oggetti istanziati.

Ci sono due tipi costruttori, quello di base, senza parametri e quello parametrizzato, usato per inizializzare gli Attributi dell'oggetto con valori esterni, si riconoscono perché hanno lo stesso nome della Calsse e nella loro dichiarazione non è indicato il tipo restituito,

I Costruttori sono sempre pubblici, solo gli oggetti di tipo Singletone, particolari oggetti che possono essere istanziati una sola volta, hanno il costruttore privato.
 

COMUNICAZIONE E COLLABORAZIONE TRA COMPONENTI
Gli elementi pubblici di un oggetto rappresentano la sua Interfaccia. Come avviene anche per i componenti elettronici, l'Interfaccia viene usata per permettere la comunicazione con gli altri componenti.

 

 

Ad esempio l'Interfaccia dell'oggetto persona è la seguente:

- setNome
- getNome
- setCognome
- getCognome
- setEta
- getEta 

Gli attributi dell'oggetto persona non sono visibili, perche sono privati, quindi non appartengono all'interfaccia.

I Metodi degli oggetti che devono gestire l'oggetto persona lo fanno attraverso la sua interfaccia, come mostra Il "Diagramma dei Componeti" seguente:

Il simbolo usato in UML per rappresentare un'interfaccia è il lecca lecca (lollipop).

Quindi il metodo  di un componente applicativo (oggetto), per comunicare e  collaborare con un altro componente, usando i metodi e gli attributi pubblici della sua interfaccia, lo deve prima istanziare con il comando new, successivamente usando il riferimento del componente creato, può usare tutti gli elementi della  sua interfaccia.

In pratica il riferimento contiene l'indirizzo dell'oggetto che espone l'interfaccia, come mostra l'immagine seguente:

L'APPLICAZIONE GESTIONE PERSONE
Adesso vediamo quali sono i passaggi fondamentali per creare un'applicazione che permette di gestire persone.

Prima di tutto disegniamo il diagramma UML che mostra i principali  componenti applicativi e in che modo collaborano tra loro:

                                                            Figura 1

Analizzado i componenti del diagramma in Figura 1, vediamo che il componente gestionePersone, ha il ruolo di controller. Questo oggetto attraverso l'uso di due viewinserimeto_persona e visualizza_persona, permette di gestire i componenti persona,  che hanno  il ruolo di model.

Il Diagramma di Classi seguente, mostra la struttura degli oggetti che compongono l'applicazione Gestione Persone.

COME SI GESTISCE IL FLISSO LOGICO (PROCESSO) DELL'APPLICAZIONE GESTIONE PERSONE
Il metodo main() della classe GestionePersone , il controller, permette d'implementare il flusso logico dell'applicazione per gestire le persone.

Per fare questo lavoro, il metodo main()  esegue le seguenti operazioni:

1) usa il metodo inserimentoPersona() per  permette l'inserimento dei dati attraverso la maschera "Inserimento Persona" (Figura 2);


                                              Figura 2

2) usa i metodi set dell'intercaccia dell'oggetto persona:

persona->setNome(nome);
persona>setCognome(cognome);
persona->setEta(eta);

per memorizza i dati inseriti della maschera all'interno dell'oggetto persona;

3) usa Il metdo visualizzaPersona(persona:Persona) per visualizzare attraverso la maschera "Visualizza Persona" (Figura 3) il contenuto dell'oggeto persona.
Questo metodo usa i metodi get dell'intercaccia dell'oggetto persona:

persona->getNome();
persona>getCognome();
persona->getEta();

per leggere i dati memorizzati negli attributi dell'oggetto persona e visualizzarli nella maschera.


                                              Figura 3


Il Diagramme delle Attività in Figura 4, mostra il flusso delle attività svolte dal metodo  inserimentoPersona() per gestire l'inserimento dei dati nell'oggetto persona:

                                      Figura 4

Nella prossima lezione parleremo di Ereditarietà, per riusare e specializzare classi già esistenti.


<< Lezione precedente           Lezione successiva >>


Laboratori di Logica di Programmazione in C

Share Button

Angular e Ionic, il profilo più richiesto dai nostri Partners IT

Gino Visciano | Skill Factory - 30/03/2018 15:38:38 | in Formazione e lavoro

Il mondo delle APP e delle WebAPP è sempre in rapida evoluzione.
La rivoluzione Angular, il framework creato da Google, per la creazione di applicazioni fornt-end dinamiche, è senza dubbio l'ultima novità del momento.

Angular, attraverso l'integrazione con Ionic, permette anche di creare WebAPP cross-platform che girano su dispositivi mobile Android, iOS e Windows Phone

Questa nuova tecnologia sta rivoluzionando anche il mondo del lavoro, al punto che la richiesta di Programmatori Angular/Ionic, da parte dei nostri Partners, è diventata molto frequente.

Per sviluppare con questo potente framework, occorre imparare il linguaggio TypeScript, facile da apprendere per chi già conosce Java ed un valido investimento per chi intende imparare Java in futuro.

TypeScript non è altro che un'estensione di JavaScript, creata da Microsoft, basata sulle specifiche della versione 6 di JavaScript - ECMAScript 6.

Per lavorare con Angular servono i seguenti prerequisiti:

- Logica di Programmazione in C
- Buona conoscenza della programmazione orientata agli oggetti
- HTML/CSS
- JavaScript (controllo modello DOM)
- BootStrap

Per chi intendesse imparare a programmare con Angular ed Ionic, ad aprile a Napoli, in collaborazione con il nostro Competence Partner  Major Bit Academy,  abbiamo organizzato un corso gratuito di 1 mese,

É possibile accedere al corso solo dopo aver superato il test d'ingresso ed aver effettuato un colloquio.
Ulteriori dettagli sul programma del corso e le modalità operative saranno illustrate in sede di colloquio.
A fine percorso, alle risorse che risulteranno idonee e saranno disponibili a lavorare anche a Roma (con rimborso spese), verrà proposto uno Stage retribuito di 3 mesi, presso uno dei nostri Partners  e successivamente un contratto di apprendistato.

Se siete interessati al partecipare al corso di Angular/Ionic inviate il vostro curriculum a selezione@skillfactory.it.
Se già siete registrati su www.skillbook.it, cliccate qui per inviare la vostra candidatura.

Share Button

Laboratori di Logica di Programmazione in C- Lezione 4

Gino Visciano | Skill Factory - 25/03/2018 19:49:40 | in Tutorials

Benvenuti, nelle lezioni precedenti, per svolgere i nostri laboratori, abbiamo usato diverse funzioni, includendole  nei programmi attraverso librerie predefinite. in questa lezione introduciamo il concetto di funzioni definite dall'utente, con l'obiettivo di creare librerie di funzioni personalizzate.

Una funzione è un task di programmazione che qundo viene eseguito, può avere da 0 ad n dati in ingresso detti argomenti oppure parametri e restituire da 0 ad 1 risultato.
Le funzioni sono BLACK - BOX che restituiscono sempre lo stesso risultato se vengono passati gli stessi argomenti. 

Una funzione che non restiruisce  un risultato viene chiamata procedura.

L'uso delle funzioni e delle procedure rende i programmi più compatti ed affidabili, riduce i tempi di sviluppo e diventa più semplice testarli.

Il linguaggio C oltre ad essere Imperativo (composto da istruzioni e strutture logiche di programmazione), è anche Funzionale, perché permette sia di creare funzioni personalizzate, sia di usare funzioni di libreria che arricchiscono le potenzialità del linguaggio.

STRUTTURA DI UNA FUNZIONE

Se un funzione non restituisce un risultato, ovvero è una procedura, come tipo restituito dovete indicare void.

Gli argomenti di una funzione sono variabili locali, cioè sono visibili solo all'inteno della funzione,  quando la funzione termina non esistono più.
Nel corpo della funzione divisione gli argomenti dividendo e divisore vengono utilizzati per eseguire il calcolo richiesto.
Il risultato del calcolo viene assegnato alla variabile locale risultato che è anche il valore restituito con il comando return.

L'esempio seguente mostra come utilizzare la funzione divisione:

Esempio 1

#include <stdio.h>

/* Dichiarazione della funzione divisione */
double divisione(double dividendo, double divisore);
int main(){
/* %lf visualizza dove viene inserito il contenuto della variabile double corrispondente */
printf("Risultato %.2lf/%.2lf=%.2lf",15.0,3.0,divisione(15.0,3.0));
return(0);
}

/* Implementazione della funzione divisione */
double divisione(double dividendo, double divisore){
double risultato;
if (divisore>0){
    risultato=dividendo/divisore;
     } else {
    risultato=-1;
   }
return risultato;
}

PASSAGGIO DI ARGOMENTI ALLE FUNZIONI PER VALORE

Di default quando si passano gli argomenti ad un funzione, vengono passati per valore. Questo significa che vengono create nuove variabili locali all'interno dell'area di memoria che appartiene alla funzione e quando la funzione termina non esistono più, come mostra lo schema seguente:

1) In main è presente la variabile risultato=0.0;
2) Quando si esegue la funzione divisione, in main risultato=0.0, mentre in divisione vengono create tre variabili:
     risultato=0.0;
     dividendo=15.0;
     divisore=3.0;
3) Quando si esegue il calcolo in divisione risultato diventa 5.0;
4) Quando termina la funzione divisione, tutte le variabili locali di divisione vengono cancellate e per effetto del return risultato di main diventa uguale a 5.0.

PASSAGGIO DI ARGOMENTI ALLE FUNZIONI PER RIFERIMENTO

In C un riferimento è un indirizzo di memoria dov'è memorizzato un valore, come  mostra l'immagine seguente:

In realtà tutte le variabili, per gestire i contenuti corrispondenti, usano riferimenti (posizioni/indirizzi di memoria), in C per ottenere il riferimento associato ad una variabile basta far precedere il nome da una &, come mostra l'esempio seguente:

&a => A00FF011 => 10 (valore corrispondente in memoria).

Le variabili che contengono un riferimento si chiamano puntatori, si distinguono dalle variabili classiche perchè i nomi sono preceduti da un *, come mostra l'esempio seguente:

Esempio 2

int main(){
    int a=10;
    int *p=&a;
    printf("a=%d, *p=%d, p=%p", a, *p, p);
}

a=>nome varibile intera che contiene il valore 10;
*p=nome puntatore, attraverso il riferimento (indirizzo) assegnato permette di gestire il valore 10, ha lo stesso compostamento della variabile a;
p= nome varibile che contiene il riferimento (indirizzo) del valore 10;

quindi se *p=&a, allora:

a => 10:
*p => 10;
p => A00FF011.

Infatti, eseguendo l'esempio 2, si ottiene l'outpit seguente:

Per capire a cosa servono i puntatori ed i riferimenti facciamo due esemp:i

Immaginate di voler creare una funzione che inverte i valori contenuti in due variabili a e b.

Nel primo caso creiamo la funzione inverti e passiamo a e b  per valore, come nell'esempio seguente:

Esempio 3

void inverti(int a, int b);
int main(){
    int a=10;
    int b=20;
    printf("1) Main[a=%d - b=%d]\n",a,b);
    inverti(a,b);
    printf("3) Main[a=%d - b=%d]\n",a,b);
   return(0);
}

void inverti(int a,int b){
    int temp;
    temp=a;
    a=b;
    b=temp;
    printf("2) Inverti[a=%d - b=%d]\n",a,b);
}

Osservando i risultati potete capire che la funzione inverti ,con il passaggio degli argomenti per valore, ha invertito a e b locali, mentre a e b di main sono rimasti gli stessi.
Questo significa che quando eseguiamo una funzione e passiamo gli argomenti attesi per valore, viene creata una copia di quelli originali, come mostra lo schema seguente:

Nel secondo caso creiamo la funzione inverti, ma questa volta non passiamo i valori di a e b, ma i loro  riferimenti.

Passando alla funzione inverti i riferimenti di a e b, diventa posibile modificare direttamente i loro valori, naturalemente gli argomenti della funzione inverti non sono variabili ma puntatori, come mostra l'esempio seguente:

Esempio 4

void inverti(int *a,int *b);
int main(){
    int a=10;
    int b=20;
    printf("1) Main[a=%d - b=%d]\n",a,b);
    inverti(&a,&b);
    printf("3) Main[a=%d - b=%d]\n",a,b);
   return(0);
}

void inverti(int *a,int *b){
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
    printf("2) Inverti[a=%d - b=%d]\n",*a,*b);
}

Osservando i risultati, adesso vediamo che passando alla funzione inverti i riferimenti di a e b, cioè &a ed &b,  i valori di a e b di main sono stati invertiti.

Lo schema seguente descrive cosa accade in memoria durante l'esecuzione del programma:

 

FUNZIONI RICORSIVE

In C le funzioni sono ricorsive, questa proprietà è molto importante perché, grazie alla ricorsività, una funzione può richiamare se stessa.
Per capire praticamente la ricorsione vediamo un esempio.

Calcoliamo il fattoriale di un numero n, valore che si indica con il simbolo:

n!

Per cacloare Il fattoriale di un numero n dovete moltiplicare tra loro tutti i numeri compresi tra 1 ed n, come mostra la formula seguente:

1 * 2 * ... * n-1 * n

Ad esempio:

0! = 1 per convenzione;
1! = 1 * 1 = 1;
2! = 1 * 2 = 2;
3! = 1 * 2 * 3 = 6.

L'esempio seguente mostra come calcolare il fattoriale di n utilizzando una funzione ricorsiva in C.

Esempio 5

int fattoriale(int numero);
int main(){
   int numero;
   printf("Calcolo del Fattoriale\n");
   printf("\nNumero:");
   /* %d = input numerico,
   &numero passiamo alla funzione scanf il riferimento della variabile numero */

   scanf("%d",&numero);
   printf("Fattoriale di %d = %d\n", numero, fattoriale(numero));
   return(0);
}
int fattoriale(numero){
    if (numero==0)
        return 1;
    else
        return numero * fattoriale(numero-1);
}

La funzione fattoriale richiama in modo ricorsivo se stessa, passando ogni volta come argomento il valore numero-1.
Quando numero diventa uguale a zero la ricorsione s'interrompe ed i return di tutte le funzioni chiamate vengono eseguiti calcolando il risultato della formula numero * fattoriale (numero - 1), come mostra lo schema seguente:

Osservando il comportamento della funzione fattoriale si capisce che la ricorsione è una tecnica che permette di ripetre più volte le stesse operazioni, come accade per i cicli, infatti il fattoriale può essere calcolato anche nel modo seguente:

Esempio 6

int main(){
   int numero,x;
   int fattoriale=1;
   printf("Calcolo del Fattoriale\n");
   printf("\nNumero:");
   /* %d = input numerico,
   &numero passiamo alla funzione scanf il riferimento della variabile numero */

   scanf("%d",&numero);
   for(x=1;x<=numero;x++){
  /* fattoriale = fattoriale * x => fattoriale*=x */
      fattoriale*=x;
   }
   printf("Fattoriale di %d = %d\n", numero, fattoriale);
   return(0);
}


L A B O R A T O R I   D I   L O G I C A   D I   P R O G R A M M A Z I O N E   I N   C
L E Z I O N E  1
L E Z I O N E  2
L E Z I O N E  3
L E Z I O N E  4
L E Z I O N E  5
 


Introduzione alla logica degli Oggetti (Per imparare a programmare ad oggetti)


Share Button

IoT e criptovalute, la nuova frontiera del lavoro giovanile, partecipa al Webinar gratuito

Gino Visciano | Skill Factory - 18/03/2018 10:43:26 | in Formazione e lavoro

Negli ultimi anni le criptovalute hanno trasformato radicalmente il mondo del Fintech (Finanza e Tecnologia - Tecnologia Finanziaria) conquistando un ruolo credibile di scambio di valore e d'investimento, anche di elevati volumi economici,  nel mondo della finanza mondiale.

Una criptovaluta, per considerarsi tale, deve soddisfare in pieno almeno questi principi:
- deve esprimere un valore numerico;
- deve essere divisibile;
- deve essere trasferibile;
- non deve essere volatile;
- deve essere generata in un numero finito di modi equivalenti fra di loro.

Naturalmente le nuove “valute” come, ad esempio il Bitcoin, ci obbligano ad introdurre sul mercato nuovi strumenti dinamici e sicuri di scambio valori che possano facilmente tramutarsi in valuta corrente.

Questi strumenti richiedono l'uso di una tecnologia affidabile in grado di garantire la gestione dei flussi.

Oggi il paradigma di gestione dei flussi più affidabile è Blockchain, comunemente definita la “Catena di Blocchi”.

L’idea alla base è semplice e geniale: rendere un processo visibile e tracciabile da parte di tutti.

Tutto ciò è possibile grazie all'IoT (Internet of Things) che sta conquistando il mondo delle rilevazioni localizzate attraverso sensori collegati alla rete internet e quindi sorgenti di informazioni recepibili in qualunque parte del mondo.

Questa tecnologia applicata alla Blockchain può garantre:  
- la certificazione delle fonti: la blockchain è in grado di garantire che uno specifico dato sia stato emesso da uno specifico sensore;
- la certificazione delle informazioni: ancora la blockchain è soggetto garante che proprio quel dato sia stato prodotto esattamente in quel giorno ed a quell’ora;
- la sicurezza contro la manomissione dei sensori: se inseriti come “peer” (o nodi) nella catena di blocchi, i sensori trasmettono e ricevono solo da altri “peer” della catena, i quali sono a loro volta certificati e riconosciuti.

Quindi attraverso la Blockchain di fatto non sono più necessari soggetti certificatori, non serve più delegare istituti bancari, eliminando il margine di rischio che è sempre presente per scambi di valuta con soggetti sconosciuti.

Se siete interessati a lavorare nel settore dell'IoT e delle criptovalute, la società Adamantic ha organizzato un Webinar gratuito, allo scopo di introdurre i partecipanti al mondo della Blockchain, fornendo informazioni utili a comprenderne i principi di funzionamento,  l’architettura, la storia evolutiva di questo mercato e gli sbocchi professionali. 

Il Webinar è propedeutico al Master, programmato a Roma a maggio che offre ai partecipanti la possibilità di apprendere le competenze per comprendere il funzionamento degli algoritmi che stanno alla base della blockchain e di essere in grado di usare Composer di IBM HyperLedger per costruire un’architettura distribuita di classe enterprise.

Sia il Webinar che il Master verranno erogati direttamente dai dirigenti dell'Adamantic, con una grossa esperienza nel campo del controllo dei flussi finanziari utilizzando la tecnologia Blockchain,  con particolare riferimento ad Ethereum (solidity) e Hyperledger Fabric.
 

Luca Vignali
Chief Scientific Officer

Pierpaolo Foderà
Chief Executive Officer

Domenico Barra
Chief Technology Officer

A fine Master tutti i partecipanti riceveranno dalla società un attestato che certificherà il livello di competenza raggiunto ed ai primi tre partecipanti che dimostraranno di aver acquisito con successo le competenze trasmesse e risponderanno ai requisiti aziendali, Adamantic proporrà un contratto d'inserimento lavorativo.


Share Button

Laboratori di Logica di Programmazione in C- Lezione 3

Gino Visciano | Skill Factory - 16/03/2018 18:29:21 | in Tutorials

Benvenuti, in questa lezione verdermo le principali Funzioni di libreria che si possono importare in C.
Una Funzione è un task di programmazione che esegue un'operazione specifica. Le Funzioni sono importanti perché permettono di usare codice già scritto e quindi riducono i tempi di sviluppo e migliorano la qualità delle applicazioni.
Le Funzioni in C sono organizzate in librerie, file con l'estensione h (header) che si possono includere in un'applicazione con il comando #include, come mostra l'esempio seguente:

#include <stdio.h>

Le librerie più usate in C sono le seguenti:

- stdio.h (input/output)
- math.h (funzioni matematiche)
- string.h (gestione di stringhe)
- ctype.h (operazioni su caratteri)
- stdlib.h (gestione dinamica della memoria)


LIBRERIA STDIO.H
Le Funzioni di questa libreria permettono di gestire i flussi di caratteri in entrata (input) e in uscita (output).
Il canale standard di input, stdin, è la tastiera.
il canale standard di output, stdout, è il video.
Esiste un altro canale di output, riservato ai messaggi di errore, stderr, che coincide con il video.

L'esempio seguente mostra come leggere un flusso di caratteri dalla tastiera (input/stdin) con la funzione getchar() e visualizzarlo sullo schermo (output/stdout) con la funzione putchar(carattere).
EOF è una costante che indica la fine del flusso (file) di caratteri che arriva dalla trastiera. In ambiente Windows EOF=ctrl+Z, in ambiente UNIX EOF=ctrl+D.

Esempio 1

#include <stdio.h>
int main(){
   int c;
   printf("Per chiudere premi invio e poi ctrl+Z [Windows] oppure ctrl+D [Unix]\n\n");
   printf("Input:");
   while((c=getchar()) != EOF)
      putchar(c);
   return(0);
}

Per completare l'operazione di INPUT dovete premere invio e CTRL+Z con sistemi Windows oppure CTRL+D con sistemi UNIX.

Le Funzioni scanf e printf, utilizzate per gestire l'input da tastiera e l'output a video basono il loro funzionamento sulle funzioni getchar() e putchar().

La funzione scanf usa gli stessi placeholder della printf, come mostra la tabella seguente:
- int (valori interi) %d;
- float (valori a virgola mobile, decimali) %f;
- char (un singolo carattere) %c;
- char[] (stringhe composte da più caratteri) %s.

COME SI GESTISCONO I FILE DI TESTO
Per creare o aprire un file di testo sul disco dovete usare la funzione fopen(path,modalità_apertura).
La funzione fopen, dopo l'apertura del file, restituisce un puntatore di tipo FILE che permette di ricevere o inviare i caratteri al file in base alla modalità di apertura.
La funzione feof(puntatore) da come risutato vero se si raggiunge la fine del File.
La funzione fclose(puntatore) chiude il File.

In C un puntatore è una variabile che contiene un indirizzo di memoria dove sono memorizzate informazioni diverse da quelle standard (interi, decimali e caratteri).
Le variabili di tipo puntatore si differenziano dalle variabili classiche perché il nome è preceduto da un asterisco "*", ad esempio FILE *fp.

Le funzioni seguenti con modalità diverse permettono di scrivere o leggere File:

SCRITTURA (OUTPUT)
fputc;
fputs
;
fprintf;
fwrite.

LETTURA (INPUT)
fgetc;
fgets;
fscanf;
fread
.

La tabella seguente indica le modalità apertura:
"r"     Apre un file di testo per la lettura. Lo stream e' posizionato all'inizio del file.
"r+"     Apre un file di testo per la lettura e scrittura. Lo stream e' posizionato all'inizio del file.
"w"     Apre un file di testo per la scrittura. Il file viene creato se non esiste, altrimenti viene troncato (forza la lunghezza a 0). Lo stream e' posizionato all'inizio del file.
"w+"     Apre un file di testo per la lettura e scrittura. Il file viene creato se non esiste, altrimenti viene troncato (forza la lunghezza a 0). Lo stream e' posizionato all'inizio del file.
"a"     Apre un file di testo per la scrittura. Il file viene creato se non esiste. Lo stream e' posizionato alla fine file.
"a+"     Apre un file di testo per la lettura e scrittura. Il file viene creato se non esiste. Lo stream e' posizionato alla fine file.

Per leggere un file si usa sempre un ciclo while, perchè bisogna continuare a leggere  mentre non si arriva alla fine del file.
I file più semplici da gestire, sono quelli di tipo testo, sequenze di caratteri ascii che si possono leggere (input) o scrivere (output) sia singolarmente, sia per riga
Esistono anche I file binari, ad esempio immagini e documenti creati con programmi specifici. Naturalmente sono più difficili da gestire e non verranno trattati in questa lezione.

L'esempio seguente salva nel File "c:/esercizi_c/testo.txt" il contenuto della stringa testo.

Esempio 2

#include <stdio.h>
int main(){
   FILE *fp;
   fp=fopen("c:/esercizi_c/testo.txt","w");
   if(fp) {
      printf("Salvataggio in corso ...\n");
      char testo[50]="Questo è un testo.";
      fprintf(fp,"%s",testo);
      fclose(fp);
   } else {
      printf("Errore:File non aperto!!!\n");
   }
   printf("Fine programma.\n");
}

L'esempio seguente legge il contenuto del File "c:/esercizi_c/testo.txt" e lo visualizza.

Esempio 3

#include <stdio.h>

int main(){
   FILE *fp;
   char c;
   fp=fopen("c:/esercizi_c/testo.txt","r");
   if(fp) {
      printf("Lettura in corso ...\n");
      while (!feof(fp)){
          c = fgetc(fp);
          putchar(c);
          }
       fclose(fp);
       putchar('\n');
   } else {
      printf("Errore:File non aperto!!!\n");
   }
   printf("Fine programma.\n");
}

L'esempio seguente acquisice numeri interi e li salva nel File "c:/esercizi_c/numeri.txt".
Il processo termina quando s'inserisce un numero uguale a zero.

Esempio 4

#include <stdio.h>
int main(){
   FILE *fp;
   int numero;
   fp=fopen("c:/esercizi_c/numeri.txt","w");
   if(fp) {
      /* Inserisci 0 per finire */
      printf("Numero:");
      scanf("%d",&numero);
      while (numero!=0){
          fprintf(fp,"%d\n",numero);
          printf("Numero:");
          scanf("%d",&numero);
          }
       fclose(fp);
   } else {
      printf("Errore:File non aperto!!!\n");
   }
   printf("Fine programma.\n");
}

L'esempio seguente legge i numeri interi salvati nel File "c:/esercizi_c/numeri.txt".
Il programma implementa la logica del flow-chart seguente:
 

 

Esempio 5

#include <stdio.h>
int main(){
   FILE *fp;
   int numero;
   fp=fopen("c:/esercizi_c/numeri.txt","r");
   if(fp) {
      fscanf(fp,"%d",&numero);
      while (!feof(fp)){
          printf("%d\n",numero);
          fscanf(fp,"%d",&numero);
          }
       fclose(fp);
   } else {
      printf("Errore:File non aperto!!!\n");
   }
   printf("Fine programma.\n");
}

L'esempio seguente acquisice nomi e li salva nel File "c:/esercizi_c/nomi.txt".
Il processo termina quando s'inserisce un asterico.

In questo esempio abbiamo incluso la libreria string.h per utilizzare la funzione strcmp(stringa1,stringa2) che permette di confrontare due stringhe.
Questa funzione, se le due stringhe sono uguali, da come risultato 0, altrimenti un valore diverso da 0. 

Esempio 6

#include <stdio.h>
#include <string.h>
int main(){
   FILE *fp;
   char nome[50];
   fp=fopen("c:/esercizi_c/nomi.txt","w");
   if(fp) {
      /* Inserisci * per finire */
      printf("Nome:");
      scanf("%s",&nome);
      while (strcmp(nome,"*")!=0){
          fprintf(fp,"%s\n",nome);
          printf("Nome:");
          scanf("%s",&nome);
          }
       fclose(fp);
   } else {
      printf("Errore:File non aperto!!!\n");
   }
   printf("Fine programma.\n");
}

L'esempio seguente legge i nomi salvati nel File "c:/esercizi_c/nomi.txt".

Esempio 7

#include <stdio.h>
int main(){
   FILE *fp;
   char nome[50];
   fp=fopen("c:/esercizi_c/nomi.txt","r");
   if(fp) {
      fscanf(fp,"%s",&nome);
      while (!feof(fp)){
          printf("%s\n",nome);
          fscanf(fp,"%s",&nome);
          }
       fclose(fp);
   } else {
      printf("Errore:File non aperto!!!\n");
   }
   printf("Fine programma.\n");
}

LIBRERIA MATH.H
Per usare le FunzionI matematiche dovete includere la libreria math.h.
Le funzioni matematiche più utili sono le seguenti:

pow(x,y) calcolo di una potenza con base x ed esponente y;
exp(double x) funzione esponenziale ex;
sqrt(x= radice quadrata di x;
fmod(x,y) resto della divisione tra due numeri x e y;
abs valore assoluto di un numero;
ceil(x) arrotondamento per eccesso del numero x;
floor(x) arrotondamento per difetto del numero x;
sin(x) seno di x;
cos(x) coseno di x;
tan(x) tangente di x;
log(x) logaritmo naturale;
log10(x) logaritmo in base 10;
rand() genera un numero casuale tra 0 e 0.9999.

L'esempio seguente mostra l'utilizzo delle principali funzioni matematiche.

Esempio 8

#include <stdio.h>
#include <math.h>
#include <time.h>

int main(){
    int x;
    /*  %.0f indica che il valore decimale corrispondente verrà visualizzato con 0 cifre decimali.
         Il simbolo %.nf indica un valore decimale con n cifre decimali. */

    printf("base=%d,esponente=%d,potenza=%.0f\n",2,3,pow(2,3));
    printf("radice quadrata di %d=%.0f\n", 16, sqrt(16));
    printf("dividendo=%.0f,divisore=%.0f,resto=%.0f\n",10.0,3.0,fmod(10,3));
    printf("valore=%.1f,floor=%.1f,ceil=%.1f\n",1.6,floor(1.6),ceil(1.6));
   /* Inizializza il generatore di numeri casuali con il valore della funzione time (orologio di sistema) della libreria time.h */
    srand(time(NULL));
    printf("Numeri casuali(da 1 a 100)\n");
/* Stampa 10 numeri casuali compresi tra 1 e 100 */
    for(x=1;x<=10;x++)
        printf("%d) %d\n",x,rand()%100+1);
    return(0);
}

LIBRERIA STRING.H
Le stringhe di caratteri all'interno dei programmi C, per essere gestite,  richiedono l'uso delle Funzioni stringa, contenute nella libreria STRING.H.

L'elenco seguente, mostra le funzioni più usate:
strlen()         ritorna la lunghezza  di una stringa;
strcpy()        copia la prima stringa nella seconda stringa;
strcat()         concatena due stringhe;
strcmp()      compare due stringhe
sizeof()        numero di byte occupati da una stringa (strlen() conta i caratteri, sizeof() conta i byte).

L'esempio seguente mostra l'utilizzo delle principali funzioni stringa.

Esempio 9

#include <stdio.h>
#include <string.h>
int main(){
char titolo[]={"Logica di Porgrammazione in C"};
char titolo_completo[100];
char societa[]={"Skill Factory"};
int x=0;
printf("Titolo:%s\n",titolo);
printf("Lunghezza titolo:%d\n",strlen(titolo));
printf("Numero byte titolo:%d\n",sizeof(titolo));
for(x=0;x<strlen(titolo);x++){
     printf("%d)%c, %d byte\n",(x+1),titolo[x],sizeof(titolo[x]));
}
/* Concateniamo titolo con societa */
strcat(titolo," (");
strcat(titolo,societa);
strcat(titolo,")");
/* Copiamo il nuovo titolo nella stringa titolo_completo */
strcpy(titolo_completo,titolo);
printf("Titolo completo:%s\n",titolo_completo);
printf("Lunghezza titolo:%d\n",strlen(titolo_completo));
printf("Numero byte titolo:%d\n",sizeof(titolo_completo));
for(x=0;x<strlen(titolo_completo)-1;x++){
     printf("<%d>%c, %d byte, ",(x+1),titolo_completo[x],sizeof(titolo_completo[x]) );
}
printf("<%d>%c, %d byte.",(x+1),titolo_completo[x],sizeof(titolo_completo[x]));
return(0);
}

L'esempio seguente mostra l'utilizzo della funzione stringa strcmp(...).
Valori restituiti dalla funzione strcmp(...):

0 -> le stringhe sono uguali;
>0 -> la prima stringa è maggiore della seconda;
<0 -> la prima stringa è minore della seconda;

Nell'esempio abbiamo usato la funzione di libreria <stdbool.h> per poter usare i valori booleani true e false, non presenti nel linguaggio C standard.
I valori booleani servono per simulare il comportamento del comando goto e inserire di nuovo il secondo nome se non si digita l'asterisco "*".
Per ripetere nuovamente un task di programma, senza usare il goto, basta utilizzare un ciclo do {...}while(flag).
Posizionando il do nel punto del programma dove s'intende ritornare, ponendo la variabile flag=ture, il task si ripete, altrimenti, con flag=false, si esce dal ciclo senza ripetere.

Esempio 10

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(){
char nomeUno[100];
char nomeDue[100];
bool flag=true;
/* Inseriamo il primo nome da confrontare con il secondo nome */
printf("Primo nome:");
scanf("%s",&nomeUno);
do{
/* Inseriamo il secondo nome da confrontare con il primo nome */
  printf("->Per uscire inserisci * come secondo nome!\n");
  printf("Secondo nome:");
  scanf("%s",&nomeDue);
  if(strcmp(tolower(nomeDue),"*")!=0){
      if(strcmp(nomeDue,nomeUno)==0){
         printf("%s e %s sono uguali.\n",nomeUno,nomeDue);
      } else if(strcmp(nomeDue,nomeUno)<0){
              printf("%s e %s, il primo nome e' maggiore del secondo nome.\n",nomeUno,nomeDue);
      } else {
              printf("%s e %s, il primo nome e' minore del secondo nome.\n",nomeUno,nomeDue);
      }
  } else {
    flag=false;
  }
} while (flag);
printf("Fine programma\n");
}


L A B O R A T O R I   D I   L O G I C A   D I   P R O G R A M M A Z I O N E   I N   C
L E Z I O N E  1
L E Z I O N E  2
L E Z I O N E  3
L E Z I O N E  4
L E Z I O N E  5
 


Introduzione alla logica degli Oggetti (Per imparare a programmare ad oggetti)


Share Button
TOP