Skip to content
This repository has been archived by the owner on Jun 16, 2023. It is now read-only.

Commit

Permalink
lezione 11
Browse files Browse the repository at this point in the history
  • Loading branch information
mc-cat-tty committed Oct 28, 2021
1 parent 4a6caa1 commit ade63ad
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 0 deletions.
11 changes: 11 additions & 0 deletions 11_ascii_history.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Storia standard ASCII

Bob Bemer è stato il padre della codifica ASCII. Necessità nata dal fatto che esistevano più di 60 codifiche differenti.

ANSI - American National
ISO 8859-1 Latin-1

Codici carattere multilingue:
- TRON Character code
- UNIX e Mule
- Unicode ISO 10646-1:1993 (estensibile e modulare). Rigida imposizione per lingue orientali.
47 changes: 47 additions & 0 deletions 11_enum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Enumerati

Problema: il tipo *int* è troppo generico
Proposta: usare un nuovo tipo di dato per identificare meglio l'insieme dei valori assegnabili ad una data variabile

Vantaggi:
- leggibilità
- correttezza (non posso assegnare valori "fuori dal range")

## enum
=> insieme di costanti intere definite dal programmatore. Ogni costante è identificata da un nome (enumeratore).
Esempio: `enum colori_t {rosso, verde, giallo};`
Alle tre costanti sopra riportate vengono assegnati valori numerici a partire da 0 (rosso==0, verde==1, giallo==2)

Viene così creato un nuovo tipo di dato che permette di definire oggetti.

## Dichirazione
`<dichirazione_enumerato> ::= enum <identificatore> {<lista_dichiarazione_enumeratori>`
`<lista_dichiarazione_enumeratori> ::= <dich_enumeratore> {, <dich_enumeratore>}`
`<dich_enumeratore> ::= <identificatore> [= <espressione>]`

Il valore di un enumeratore viene stabilito a partire dal precedente, che viene incrementato di una unità.

## Definizione
Questa dichirazione segue le stesse regole di visibilità di qualunque altra dichiarazione.

Se dichiaro un enumeratore con lo stesso nome di un enumeratore già dichiarato, perdo la visibilità di quest'ultimo.

## Ordinamento
Gli enumerati sono tipi ordinati, quindi posso fare confronti tra gli enumeratori (sempre possibile stabilire una relazione di ordine).

## Rappresentazione in memoria
Tipicamente ogni enumerato occupa la stessa quantità di memoria occupata da un int (4 byte).

Il compilatore impedisce di assegnare ad un enumerato un valore differente dal tipo di dato (il casting è consentito).

Operazioni e confronti tra enumerati
=> possibile ma rompe la tipizzazione forte del Cpp

## enum class
=> risolve il problema posto sopra. Ogni volta che si vuole utilizzare un enumeratore definito in una enum class è necessario anteporre `<nome_classe>::`. In più è possibile evitare di perdere la visibilità di un operatore con lo stesso nome di uno già definito.

Altri vantaggi (a differenza degli enum):
- non permesse operazioni pericolose
- possibile associare gli enumeratori a valori diversi da int

Requisiti: standard C++11
40 changes: 40 additions & 0 deletions 11_ordinamento_caratteri.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Ordinamento
Ordine lessicografico: i caratteri sono ordinati e rispettano il seguente ordinamento. A seconda della codifica utilizzata posso avere ordinamenti differenti dei caratteri (ASCII e UNICODE hanno lo stesso ordinamento, perchè l'ultimo è estensione del primo).

eg: numeri < lettere maiuscole < lettere minuscole

## Casting
=> conversioni di tipo esplicite
Ricorda: il C è un linguaggio a tipizzazione forte, quindi il tipo di ogni variabile non cambia durante l'esecuzione del programma.
Esiste il *casting* o conversione esplicita, valido sia in C che in Cpp. Si effettua mettendo tra parentesi tonde il nuovo tipo di dato e successivamente una espressione:
- cast `(<tipo_di_dest>)<espressione>`
- notazione funzionale `<tipo_di_dest>(<espressione>)`
- operatore _static_cast_ (solo Cpp) `static_cast<<tipo_dest>>(<espressione>)`

In tutti e tre i casi il valore dell'espressione viene convertito (interpretato in un certo modo) in <tipo_dest>

### Operatore static_cast
Perchè usare una notazione più pesante quando sono disponibili le altre due:
1. i cast sono highly dangerous
2. da utilizzare solo quando non si riesce a farne a meno (per non complicare il programma)
3. notazione pesante permette di notarlo di più
4. controllo più rigido da parte del compilatore

## cout
Stampa carattere o intero in base al tipo della variabile.

## cin
Conversione come sopra.
Esempio: se su stdin ho '1'
cin >> (int)i; // in i trovo il valore 1
cin >> (char)c; // in c trovo il valore corrispondente al carattere '1' secondo la codifica ASCII

### noskipws e skipws
Il comportamento di base del cin prevede che venga inserito almeno un carattere diverso da whitespace (tab, return, space...)

Con i modificatori `skipws` e `noskipws` posso alterare il comportamento di default.

cin continuerà comunque ad aspettarsi un invio (line feed) per confermare l'inserimento dei caratteri da stdin. -> *configurazione caninica* del terminale: è il terminale che invia i caratteri presenti su stdin solamente dopo aver premutoinvio. La configurazione non canonica è possibile, vedi `man termios`

## Operazioni sui char
Sono possibili tutte le operazioni viste fin'ora sugli int
10 changes: 10 additions & 0 deletions 11_portabilità.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Portabilità
Un codice si dice portabile se può eseguire mantenendo il proprio comportamento invariato su differenti architetture. Non è portabile in caso contrario.

Un codice non portabile è altamente sconsigliato, almeno che non si stia lavorando su sistemi embedded (unica architettura utilizzata).

## Approccio bottom-up
Scrivo tutte le funzioni che mi servono e (forse) le utilizzo per implementare l'algo ad alto livello

## Approccio top-down
Scrivo solo i prototipi delle funzioni, commentandoli, e li utilizzo senza averli ancora implementati.
18 changes: 18 additions & 0 deletions esercitazioni/codice_car.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <iostream>

using namespace std;

int main() {
int n; // input number
char c; // output char

cout << "Inserisci numero: "; cin >> n;
if (!(n>=static_cast<int>(' ') && n<=static_cast<int>('~'))) {
cout << "Range non valido" << endl;
return 1;
}

c = static_cast<char>(n);
cout << "Carattere corrispondente: " << c << endl;
return 0;
}
27 changes: 27 additions & 0 deletions esercitazioni/giorni_lavoro.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <iostream>

using namespace std;

enum giorno_t {lun, mar, mer, gio, ven, sab, dom};

void stampa_turno(giorno_t);

int main() {
stampa_turno(lun);
stampa_turno(gio);
stampa_turno(dom);
}

void stampa_turno(giorno_t g) {
switch (g) {
case lun: case mer: case ven:
cout << "mattina e pomeriggio";
break;
case mar: case gio:
cout << "mattina";
break;
case sab: case dom:
cout << "riposo";
}
cout << endl;
}
22 changes: 22 additions & 0 deletions esercitazioni/maiusc_minusc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <iostream>

using namespace std;

const char maiuscolo(const char);

int main() {
char minus, maius;
cin >> minus;
maius = maiuscolo(minus);
if (maius == minus)
cout << "Il carattere " << minus << " non è minuscolo" << endl;
else
cout << "Il carattere " << minus << " è minuscolo - maiuscolo: " << maius << endl;
return 0;
}

const char maiuscolo(const char c) {
if (c>='a' && c<='z')
return c-('a'-'A'); // Add the shift between lowercase and uppercase letters
return c;
}
16 changes: 16 additions & 0 deletions esercitazioni/stampa_tabella_ascii.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <iostream>

using namespace std;

const char FIRST_CHAR = ' ';
const char LAST_CHAR = '~';

int main() {
for (char c=FIRST_CHAR; c<=LAST_CHAR; c++) {
cout << static_cast<int>(c) << " " << c << "\t";
if (static_cast<int>(c-FIRST_CHAR+1)%8 == 0)
cout << endl;
}
cout << endl;
return 0;
}
95 changes: 95 additions & 0 deletions esercitazioni/traccia_car_codici_immediato.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
Partendo dal frammento di programma di seguito fornito, scrivere un
programma che legge e stampa i codici di tutti i caratteri letti in
ingresso, senza dover aspettare l'imissione del newline, finche' non
viene immesso il carattere -
Un possibile output sullo schermo e' il seguente:
Inserisci un carattere e
Il codice ASCII del carattere e' 101
Inserisci un carattere
Il codice ASCII del carattere e' 32
Inserisci un carattere ,
Il codice ASCII del carattere e' 44
Inserisci un carattere
Il codice ASCII del carattere e' 10
Inserisci un carattere -
Il codice ASCII del carattere e' 45
*/

/*
* Segue il frammento di programma da cui partire
*
* Per lo svolgimento dell'esercizio non e' di nessuna importanza
* capire come si ottiene il cambio di modalita' del terminale. Quello
* che va fatto e' solo scrivere le righe mancanti!
*/

#include <iostream>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

using namespace std ;

/*
* Configura il terminale in modo non canonico
*/
void vai_in_modo_non_canonico()
{
struct termios nuovo ;
if (tcgetattr(STDIN_FILENO, &nuovo) < 0) {
cout<<"Salvataggio modo terminale fallito"<<endl ;
exit(1) ;
}

nuovo.c_lflag &= ~ICANON ;

if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &nuovo) < 0) {
cout<<"Settaggio modo terminale fallito"<<endl ;
exit(1) ;
}

}

void salva_modo_terminale(termios &modo)
{
if (tcgetattr(STDIN_FILENO, &modo) < 0) {
cout<<"Salvataggio modo terminale fallito" ;
exit(1) ;
}
}

void assegna_modo_terminale(termios &modo)
{
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &modo) < 0) {
cout<<"Salvataggio modo terminale fallito" ;
exit(1) ;
}
}

int main()
{
termios vecchio_modo_terminale ;
// si salva la modalita' corrente per ripristinarla al termine del
// programma
salva_modo_terminale(vecchio_modo_terminale) ;

vai_in_modo_non_canonico() ;


char c;
do {
cout << "Carattere: ";
cin >> noskipws >> c;
cout << endl << "Valore: " << static_cast<int>(c) << endl;
} while (c != '-');

// qui il terminale viene riportato nella modalita' precedente
assegna_modo_terminale(vecchio_modo_terminale) ;

return 0 ;
}

0 comments on commit ade63ad

Please sign in to comment.