[:it]C++: librerie del programmatore, namespace, information hiding [:]

[:it]

Jacek Yerka

Il linguaggio C++ permette al programmatore di definire una propria libreria nella quale inserire blocchi di programma, utilizzabili da più sorgenti.

Essi possono essere inglobati nel listato del programma mediante la parola

#include<nome_del_namespace.h>

Ad esempio si crea il seguente blocco di programma:

namespace Rettangolo{
//dati
int base, altezza;
//funzioni
int Area(int, int);
int Perimetro(int,int);
}

int Rettangolo::Area(int b,int h)
{return b*h;
}

int Rettangolo::Perimetro(int b,int h)
{
return (b+h)*2;
}

si noti la seguente struttura:

  • si ha una parte dati,
  • una parte dichiarativa delle funzioni che verranno usate
  • la definizione delle funzioni stesse che hanno però prima il nome del namespace::

Ecco poi il listato del programma che usa il namespace rettangolo:

#include<iostream>
#include<rettangolo.h>

using namespace std;

int main()
{
cout<<“Base: “;
cin>>Rettangolo::base;
cout<<“Altezza: “;
cin>>Rettangolo::altezza;
cout<<Rettangolo::Area(Rettangolo::base,Rettangolo::altezza)<<endl;
cout<<Rettangolo::Perimetro(Rettangolo::base,Rettangolo::altezza)<<endl;
}

si nota :

#include<rettangolo.h>

che include il namespace o blocco di programma definito in maniera esterna.

Ho creato una libreria in cui ho definito tutti i miei namespace.

Per evitare di dover scrivere ogni volta il riferimento al namespace rettangolo si può usare

using namespace Rettamgolo;

il codice del sorgente diventa:

#include<iostream>
#include<rettangolo.h>

using namespace std;
using namespace Rettangolo;

int main()
{
cout<<“Base: “;
cin>>base;
cout<<“Altezza: “;
cin>>altezza;
cout<<Area(base,altezza)<<endl;
cout<<Perimetro(base,altezza)<<endl;
}

Questo progetto, pur essendo molto semplice, fornisce un’idea dell’importanza del namespace e delle librerie disponibili per il programmatore, il quale può utilizzare, nei suoi programmi dati e funzioni senza conoscere l’effettiva implementazione con il codice C++. In questo modo si realizza l’information hiding (nascondere le informazioni), con i vantaggio di poter modificare, in tempi successivi le funzioni (e in generale le librerie) per renderle più efficienti, senza dover cambiare i programmi che le utilizzano.

Per esempio, il programma precedente, utilizza le variabili base, altezza e le funzioni Area e Perimetro, ma la loro implementazione non è presente nel programma perché è definita nel namespace Rettangolo. In pratica le funzioni rappresentano le interfacce che il programmatore utilizza per effettuare le elaborazioni sul rettangolo.

Il nome del namespace delle principali librerie del linguaggio C++ è std (standard)[:]

Pubblicato in Senza categoria | Lascia un commento

[:it]C++: esercizi sulle funzioni con prototipi[:]

[:it]

  1. jacek yerka

    Sviluppare un programma che tramite funzioni prototipo fornisca all’utente la condizione di essere pari o dispari per un numero richiesto a video.

  2. Sviluppare un programma che sempre tramite funzioni prototipo fornisca la superficie di trapezio.
  3. Sviluppare un programma che tramite la funzione prototipo conta il numero di numeri immessi dall’utente.
  4. Scrivere il programma per calcolare l’ipotenusa, il perimetro e l’area di un triangolo rettangolo, dopo aver acquisito da tastiera le misure dei due cateti. Organizzare il programma utilizzando le funzioni ed individuando quali variabili possono essere dichiarate come locali delle funzioni.
  5. Costruire la funzione che simula il controllo sull’inserimento di una nuova password da parte dell’utente. Nella funzione chiamante si acquisiscono due stringhe: la prima per la password e la seconda per la conferma. Le due stringhe vengono passate come parametri alla funzione: se la stringa inserita per seconda è diversa dalla prima, il programma manda un messaggio di errore e richiede l’inserimento delle stringhe.
  6. Da tastiera vengono introdotti i dati dei prodotti con il nome del prodotto, la quantità venduta ed il prezzo unitario. Calcolare il prezzo medio, la quantità media e il valore totale delle vendite (sommatoria di prezzo e quantità).
  7. Dopo aver acquisito da tastiera le informazioni sugli studenti iscritti in una scuola (il nome, il Comune di provenienza e la distanza in km dalla scuola), si devono comunicare: il numero degli studenti residenti in comuni diversi dal capoluogo di provincia; la percentuale di questi rispetto al totale degli studenti considerati; la distanza media in km calcolata su tutti gli studenti.
  8. Per ciascun giorno del mese si conoscono le temperature minima e massima di una città. Dopo aver inserito i dati di ciascun giorno del mese, si calcoli il valore medio delle minime e delle massime.
  9. Dati due nomi di città con il numero di abitanti di ciascuna, scrivere le città prima in ordine alfabetico e poi in ordine crescente di abitanti.
  10. Di una persona si inseriscono il cognome, il nome, e l’anno di nascita. Il programma crea automaticamente un codice identificativo della persona prendendo i primi due caratteri del cognome, i primi due del nome e le cifre dell’anno di nascita.

[:]

Pubblicato in Senza categoria | 6 commenti

[:it]C++: Visibilità delle variabili[:]

[:it]

Jacek Yerka

PREMESSA

L’idea di organizzare i programmi in moduli funzionalmente indipendenti porta con sé la necessità di definire, all’interno della funzione, tutte le variabili necessarie al suo funzionamento: in realtà spesso, in un programma, una funzione può condividere variabili con altre funzioni.

SVILUPPO

In un programma si possono distinguere:

  • variabili globali: vengono definite all’inizio del programma e che possono essere usate dal programma principale e da tutte le funzioni
  • variabili locali: vengono dichiarate all’interno della funzione che le utilizza e che non sono visibili alle altre funzioni

Anche le variabili dichiarate nel main sono di tipo locale ossia visibili dal main stesso.

#include … prototipi delle funzioni predefinite
tipo nome;

variabili globali;
tipo nome funzione(parametri); prototipi delle funzioni del programmatore;
int main()

 

funzione principale
{

tipo nome;

return 0;

}

 variabili locali
tipo nomefunzione(parametri)
{tipo nome;

return…:

}

variabili locali

CONCLUSIONE

Sulla base del ragionamento fatto in precedenza, appare chiaro che un programma ben strutturato (ossia scritto in modo chiaro, efficace ed efficiente) avrà poche variabili globali e molte variabili  locali, proprio per consentire una facile manutenzione del software nel tempo e maggiori possibilità di riutilizzare moduli software in altri programmi.

Tutto questo è molto importante perché significa che per le variabili locali vengono riservate posizioni nella memoria centrale solo al momento dell’esecuzione della funzione. Lo spazio viene creato all’inizio e rilasciato al termine della funzione, liberando quindi spazio nella memoria utente: una ragione in più per usare molte variabili locali e poche variabili globali.

Tuto ciò rende possibile l’utilizzo dello stesso nome di variabile locale in due funzioni diverse.

 

ESEMPIO1 – nomi diversi nella funzione e nel main

//
// Francesco Bragadin
// visibilità variabili
// nomi diversi della variabile nel main e nella funzione area
//

#include <iostream>
using namespace std;

// definizione della funzione
int area(int a);

int main()
{
int lato;
cout<<“lato: “<<endl;
cin>>lato;
cout<<“Area: “<<area(lato);
return 0;
}

// sviluppo della funzione
int area(int a)
{
return a*a;
}

ESEMPIO 2 – stesso nome della variabile nel main e nella funzione

//
// Francesco Bragadin
// visibilità variabili
// nomi uguali della variabile nel main e nella funzione area
//

#include <iostream>
using namespace std;

// definizione della funzione
int area(int a);

int main()
{
int a;
cout<<“lato: “<<endl;
cin>>a;
cout<<“Area: “<<area(a);
return 0;
}

// sviluppo della funzione
int area(int a)
{
return a*a;
}

ESEMPIO 3- uso della variabile globale

//
// Francesco Bragadin
// visibilità variabili
// nomi uguali della variabile nel main e nella funzione e variabile globale
//

#include <iostream>
using namespace std;

// variabile globale
double pigreco=3.14;

// definizione della funzione
double superficie(int r);
double circonferenza(int r);

int main()
{
int r;
cout<<“raggio: “<<endl;
cin>>r;
cout<<“Superficie: “<<superficie(r)<<endl;
cout<<“Circonferenza: “<<circonferenza(r)<<endl;
return 0;
}

// sviluppo della funzione
double superficie(int r)
{
return r*r*pigreco;
}

double circonferenza(int r)
{
return 2*r*pigreco;
}[:]

Pubblicato in Senza categoria | Lascia un commento

[:it]C++: definizione delle funzioni mediante prototipi[:]

[:it]

jacek Yerka

Si è visto come chiamare ed usare le funzioni.

Adesso si affrontano alcuni approfondimenti in particolare:

  • una funzione non ne può richiamare un’altra se questa non è stata ancora definita

La dichiarazione della funzione, che si intente utilizzare nel programma, di norma, va posta in testa la programma stesso, immediatamente dopo la sezione dedicata alle direttive e alla dichiarazione delle variabili globali.

Tramite la dichiarazione, il programmatore si limita a comunicare al compilatore la sua intenzione di utilizzare una funzione che restituisca un dato di un certo tipo e che utilizza determinati parametri, riservandosi di specificarne il codice in seguito, nella fase di definizione.

Questa dichiarazione si chiama prototipo.

In pratica:

all’inizio del programma le funzioni vengono soltanto dichiarate, specificandone per ciascuna il tipo restituito e il nome dei parametri richiesti.

In questo modo si ottiene una semplice elencazione dei prototipi che facilita la comprensione del programma e realizza, in pratica la metodologia top-down.

Ad esempio il seguente programma dichiara la funzione che solo successivamente viene definita nei dettagli:

//
// Autore: Francesco Bragadin
// Oggetto: uso dei prototipi come funzioni
//

#include <iostream>

using namespace std;

// semplice definizione della fuznione
int maggiore(int a, int b);

int main()
{
int c,d;
cout<<“primo numero: “<<endl;
cin>>c;
cout<<“secondo numero: “<<endl;
cin>>d;
cout<<“il numero maggiore risulta: “<<maggiore(c,d);
return 0;
}

//dettagli della funzione
int maggiore(int a, int b)
{
int c;
if (a>b)
return a;
if (a<b)
return b;
}

 

 [:]

Pubblicato in Senza categoria | Lascia un commento

[:it]C++: function overloading[:]

[:it]

Jacek Yerka

Il linguaggio C++ offre la possibilità di definire due funzioni con lo stesso nome che differiscono tra loro solamente per l’elenco dei parametri.

Tale diversità può riguardare sia il numero di parametri passati, sia il loro tipo.

In base al tipo e al numero di parametri passati alla funzione, il compilatore riconosce la funzione che deve essere richiamata.

Questo meccanismo di ridefinizione delle funzioni si chiama function overloading.

Ad esempio questo programma utilizza la stessa funzione che si chiama area per due cose diverse ed il compilatore interpreta e decide quale chiamare:

//
// Autore: Francesco Bragadin
// Oggetto: function overloading
//

#include<iostream>
using namespace std;

// dichiarazione prima funzione per il calcolo dell’area di un quadrato
double area(double a)
{
return a*a;
}

// dichiarazione della stessa funzione area per il calcolo del triangolo
double area(double a, double b)
{
return a*b;
}

int main()
{
int i;
double l,b,h;
cout<<“Di quale figura vuoi calcolare la superficie?”<<endl;
cout<<” 1- Quadrato”<<endl;
cout<<” 2- Triangolo”<<endl;
cin>>i;
if (i==1)
{
cout<<“Inserisci il lato del quadrato: “<<endl;
cin>>l;
cout<<“La superficie del quadrato risulta: “<<area(l);
}
if (i==2)
{
cout<<“inserisci la base del triangolo: “<<endl;
cin>>b;
cout<<“inserisci altezza del triangolo: “<<endl;
cin>>h;
cout<<“La superficie del triangolo risulta: “<<area(b,h);
}

return 0;
}[:]

Pubblicato in Senza categoria | Lascia un commento

[:it]TPSIT: firma digitale[:]

[:it]

Vincent Van Gogh

La caratterizzazione dell’utilizzo della firma digitale è quella di essere:

  • autentica
  • integra
  • non ripudio

Autentica

Si deve riconoscere l’identità del mittente

Integra

Nessuna modifica sul documento originario

Non ripudio

Il documento firmato con la firma elettronica ha valore legale e colui che la utilizza non può negare di averla sottoscritta.

Si utilizza la crittografia a chiave asimmetrica:

  • si firma il documento con la chiave privata
  • per verificare l’integrità e l’autenticità usano la chiave pubblica

La firma digitale che cosa è?

Si parte dal documento originale e si crea una sequenza binaria (128 o 160 bit) chiamata impronta (fingerprint) che è proprio un riassunto  del documento (digest).

Questa fingerprint utilizza la funzione hash (sminuzzare, spezzettare) che ha alcune proprietà molto importanti:

  • deve identificare univocamente il messaggio, non è possibile che due messaggi differenti, pur essendo simili, abbiano lo stesso valore di hash;
  • deve essere deterministico, in modo che lo stesso messaggio si traduca sempre nello stesso hash;
  • deve essere semplice e veloce calcolare un valore hash da un qualunque tipo di dato;
  • deve essere molto difficile o quasi impossibile generare un messaggio dal suo valore hash se non provando tutti i messaggi possibili.

Operazioni del destinatario

  • Il destinatario riproduce l’impronta usando al chiave pubblica del firmatario
  • avendo ricevuto il messaggio in chiaro, crea la stessa funzione di hash per creare il digest e la confronta con quella del firmatario verifica che il documento non è stato modificato

FONDAMENTALE

ogni documento ha una forma digitale diversa

Utilizzo pratico

  • ci si deve rivolgere alla camera di commercio che verifica l’identità del richiedente e fornisce una chiave usb al cui interno vi è software che usa la chiave provata per firmare il documento
  • si crea un documento con estensione p7m
  • per poter verificare un documento si usa un software di nome dike fornito da infocert

 

Protocolli per la crittografia

PGP e GPG

SSH

SSL e TLS

HTTPS[:]

Pubblicato in Senza categoria | 1 commento

[:it]TPSIT: conclusioni differenza tra crittografia a chiave simmetrica ed asimmetrica[:]

[:it]

Crittografia simmetrica Crittografia asimmetrica
Un processo di crittografia simmetrica è caratterizzato nella pratica dall’utilizzo di una medesima chiave condivisa sia per l’operazione di cifratura che per quella di decifratura.

Negli schemi di cifratura simmetrica la sicurezza del processo risiede nella lunghezza della chiave utilizzata e nella capacità di mantenerla segreta.

La dimensione della chiave è un parametro fondamentale per valutare la robustezza dello schema usato, insieme alla resistenza dell’algoritmo agli attacchi di criptoanalisi. Nei processi di crittografia simmetrica è permesso l’uso di chiavi lunghe quanto il messaggio, rendendo il messaggio cifrato estremamente sicuro.

La criticità principale della crittografia simmetrica risiede nella necessità di doversi scambiare le chiavi in maniera sicura.

In processi completamente informatizzati ciò è in genere fatto ricorrendo alla crittografia asimmetrica (e.g. es. tramite algoritmo di Diffie-Hellmann), altro metodo consiste nell’incapsulamento di una chiave in un’altra ovvero si genera una chiave master che è scambiata attraverso un canale sicuro, le chiavi di cifratura sono quindi cifrate con la chiave master e scambiate.

Tra gli algoritmi di crittografia simmetrica più popolari ricordiamo:

DES, Triple-DES (3DES), IDEA, CAST5, BLOWFISH, TWOFISH.

La crittografia asimmetrica, anche nota come crittografia a chiave pubblica/privata, è un tipo di crittografia in cui a ciascuna entità è associata una coppia di chiavi:

  • Una chiave pubblica accessibile a tutti coloro che necessitano di scambiare informazioni con l’entità proprietaria.
  • Una chiave privata, custodita e tenuta segreta dal legittimo proprietario.

In un processo di crittografia asimmetrica, qualsiasi messaggio crittografato con una chiave privata potrà essere decifrato solo utilizzando la chiave pubblica corrispondente. Il processo svincola quindi l’utente dalla necessità di dover scambiare le chiavi prima di qualunque comunicazione.

I principali utilizzi della crittografia asimmetrica sono

  1. Invio di un messaggio cifrato ad un destinatario. Il mittente cifra il messaggio con la chiave pubblica del destinatario che sarà quindi l’unico a poter decifrare il messaggio utilizzando la sua chiave privata.
  2. Non ripudiabilità del messaggio. Il proprietario della chiave privata cifra il messaggio con la propria chiave privata, qualunque entità che possa accedere alla chiave pubblica del firmatario potrà decifrarlo con la stessa ed essere quindi certo della sua autenticità

 [:]

Pubblicato in Senza categoria | Lascia un commento

[:it]Java: esempio gestione di un vettore usato per il cifrario di Cesare[:]

[:it]

Vincent Van Gogh

Questo programma elaborato dallo studente Daniel Amadori che segue il corso di informatica e telecomunicazioni presso IISS Galileo Galilei di Bolzano, evidenzia come si può usare la definizione tradizionale di un vettore ed applicarlo al cifrario di Cesare:

import java.io.*;

class Vigenere{
char cifrario[];

int position(char x){
int i= 0;
while( i < 26){
if(x == cifrario[i])
break;
i++;
}
return i;
}

char shifter(char x,int p){
p += position(x);
if(p < 26)
return cifrario[p];
else
return cifrario[p-26];
}

String cifratore(String x, String password){
String tmp =””;
for(int i= 0,j= 0; i < x.length(); i++,j++){
if(j >= password.length())
j= 0;
tmp += shifter(x.charAt(i), position( password.charAt(j) ) );
}
return tmp;
}
String decifratore(String x, String password){
String tmp =””;
for(int i= 0,j= 0; i < x.length(); i++,j++){
if(j >= password.length())
j= 0;
tmp += shifter(x.charAt(i), 26-position( password.charAt(j) ) );
}
return tmp;
}
Vigenere(){
cifrario = new char[26];
cifrario[0] = ‘a’;
for(int i = 1; i < 26; i++){
cifrario[i] += cifrario[i-1]+1;
}
}

}

public class crittazione {

public static void main (String args[]) {
BufferedReader input = new BufferedReader(new InputStreamReader( System.in ) );
Vigenère a = new Vigenère();

String data =””, key =””, output =””;

System.out.print(“Scegliere se cifrare o decifrare\n 1. Cifrare\n 2.Decifrare\n Cosa scegli: “);
int chose =0;
try {
chose = Integer.parseInt(input.readLine());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(“Inserire il testo:”);
try {
data = input.readLine();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(“Inserire la chiave:”);
try {
key = input.readLine();
} catch (IOException e) {
e.printStackTrace();
}

if( chose == 1)
output = a.cifratore(data, key);
else if( chose == 2)
output = a.decifratore(data, key);
else
System.out.println(“Scelta non valida”);

System.out.println(output);
}
}

 [:]

Pubblicato in Senza categoria | Lascia un commento

[:it]Java: esempio di utilizzo classe con metodi void e costruttore[:]

[:it]

Vincent van Gogh

Questo programma è stato sviluppato dallo studente Simone Tagliapietra che segue il corso informatica e telecomunicazioni presso IISS Galileo Galilei di Bolzano.

Utilizza in maniera molto chiara la definizione dei metodi, il concetto di costruttore e come poter inserire i dati e poter mostrare il risultato a video

import java.io.*;

public class Rettangolo {

private int base;
private int altezza;

public void setBase() {

System.out.println(“Inserire la base: “);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); //immissione valori letti da tastiera su buffer
try {
base = Integer.parseInt(input.readLine()); //conversione dati del buffer in int
}
catch (IOException e) {
e.printStackTrace();
}

}

public void setAltezza() {

System.out.println(“Inserire l’altezza: “);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
try {
altezza = Integer.parseInt(input.readLine());
}
catch (IOException e) {
e.printStackTrace();
}

}

public Rettangolo() {

base = 0;
altezza = 0;

}

public int areaRettangolo(){

return base*altezza;

}

public static void main(String[] args) {

Rettangolo r = new Rettangolo();

r.setBase();
r.setAltezza();
System.out.println(“L’area vale: “+r.areaRettangolo());

}

}

Osservazioni:

il costruttore segue  in maniera molto lineare un costruttore usato nel linguaggio C++.

Infatti, poi per poterlo usare utilizza questa inizializzazione:

Rettangolo r = new Rettangolo();

 

Si può inserire anche questo costruttore:

public Rettangolo(int base, int altezza) {
this.base=base;
this.altezza=altezza;
}

in questo caso si può inizializzare nella seguente maniera:

Rettangolo r = new Rettangolo(3,4);

Consiglio quindi di usare sempre i due tipi di costruttore.[:]

Pubblicato in Senza categoria | Lascia un commento

[:it]Gaussiana e gaussiana normalizzata: approfondimenti[:]

[:it]La gaussiana normalizzata ha equazione:

f(x)=\frac{1}{\sigma \sqrt{2\pi }}e^-{\frac{\left ( x-\mu \right )^{2}}{2\sigma ^{2}}}

Essa ha simmetria proprio nel valor medio \mu.

Il suo grafico varia al variare della deviazione standard. Questa figura chiarisce il concetto:

Essa è una densità di probabilità ed effettuando la sua integrazione trovo proprio la distribuzione di probabilità che fornisce la probabilità che un evento possa accadere in un intervallo.

In pratica:

P\left [ a \leqslant x\leqslant b \right ]=F_{x}(b)-F_{x}(a)=\int_{a}^{b}\frac{1}{\sigma \sqrt{2\pi }}e^-{\frac{\left ( x-\mu \right )^{2}}{2\sigma ^{2}}}dx

Il calcolo di questo integrale non è banale e si preferisce calcolare l’integrale della stessa curva ma traslata nell’origine, standardizzandola ,ponendo:

z=\cfrac{x-\mu}{\sigma }

La gaussiana normalizzata standard avrà equazione:

p(z)=\cfrac{1}{\sqrt{2\pi}}e^{-\frac{1}{2}z^{2}}

con media nulla ossia \mu=0 e deviazione standard unitaria \sigma=1

Questo disegno chiarisce la cosa:

In generale:

\int_{-\infty }^{+\infty }\cfrac{1}{\sqrt{2\pi}}e^{-\frac{1}{2}z^{2}}dz=1

e per calcolare l’integrale in un opportuno intervallo si usa una tabella standard che lo calcola.

Ad esempio:

\int_{-\infty }^{1}\cfrac{1}{\sqrt{2\pi}}e^{-\frac{1}{2}z^{2}}dz

osservando la tabella allegata:

CLAMED-tavole-1

si deve trovare la riga corrispondente al valore z=1 e si nota che alla colonna 0.00 il valore è 0,8413.

Significa che la probabilità che un evento sia minore di 1 vale esattamente 84,13%.

Se avessi dovuto calcolare

\int_{-\infty }^{1,01}\cfrac{1}{\sqrt{2\pi}}e^{-\frac{1}{2}z^{2}}dz

mi sarei posto sempre sulla riga dell’1 ma alla colonna 0,01 e la probabilità sarebbe stata 0,8438 ossia in percentuale 84,38.

Ricapitolando la riga mi fornisce il valore della z per un il valore intero seguito da un decimale e la colonna mi fornisce il valore corrispondente a partire dal secondo decimale.

Passaggio dalla gaussiana normalizzata a quella standard attraverso la tabella fornita

Ma se un evento  ha media \mu=4 e deviazione standard \sigma=0,81 come faccio a collegarla alla gaussiana standard?

Devo calcolare la probabilità che il mio evento sia sempre minore di 3.

Allora dalla relazione:

z=\cfrac{3-4}{0.81}=-1.23

andando a vedere la tabella si vede che vale 0,10 ossia il circa il 10%.[:]

Pubblicato in Senza categoria | Lascia un commento