• Non ci sono risultati.

Slide aggiuntive

N/A
N/A
Protected

Academic year: 2021

Condividi "Slide aggiuntive"

Copied!
22
0
0

Testo completo

(1)

Allocazione dinamica della memoria e gestione

dell’heap

Poiché il nome di un array è il puntatore al primo dei suoi elementi, dovrebbe essere possibile definire l’array mediante una variabile puntatore. Sintatticamente le due definizioni sono equivalenti.

C’è però un’importante differenza. Utilizzando la definizione solita di array il compilatore riserva un blocco di memoria per contenere i suoi elementi, invece definendo l’array mediante un puntatore ciò non accade. Occorre perciò fare allocazione dinamica della memoria mediante la funzione di libreria malloc.

La memoria del computer, durante l’esecuzione di un programma, è occupata dal sistema operativo e dal programma stesso includendo gli array e le variabili usate. Lo spazio rimanente viene detto heap e per prelevare al run time memoria dall’heap il C ci mette a disposizione la funzione di libreria malloc.

Ci si può chiedere perché serve l’heap nel momento in cui il compilatore ha riservato spazio per le variabili e le costanti presenti nel programma. Il problema nasce dal fatto che gli array sono strutture statiche: occorre definire le dimensioni dell’array e questo spazio può risultare sovrabbondante in certe situazioni e insufficiente in altre.

Invece l’heap viene utilizzato in modo flessibile allocando al run time solo la memoria che serve in quella esecuzione del programma.

Molto software che utilizziamo correntemente ha bisogno dell’heap. Pensiamo, ad esempio, a Word che utilizziamo per scrivere una relazione: è chiaro che le frasi che digitiamo vanno a finire in memoria ma lo è altrettanto il fatto che Word non sa quanto sarà lunga la relazione. Man mano che scriviamo, Word preleva dall’heap un blocco di memoria e quando si esaurisce ne preleva un altro e così via.

(2)

L’alternativa sarebbe allocare un grande array che potrebbe a volte risultare eccessivo e altre insufficiente. La memoria è una risorsa preziosa e lo è ancor di più in presenza di una rete in cui vari utenti compartiscono la memoria disponibile.

Ovviamente, occorre una funzione simmetrica alla malloc per liberare spazio in memoria quando non ci serve più. Ad esempio, quando cancelliamo un documento, Word rende disponibile lo spazio da esso occupato. A questo scopo il C ci fornisce la funzione free che rende disponibile un blocco di memoria che non serve più.

Facciamo un esempio. Supponiamo che un programma abbia bisogno di un vettore con 1000 elementi solo per un tempo molto breve durante la sua esecuzione. Se definissimo un vettore di dimensione 1000 lo spazio di memoria resterebbe bloccato per tutta la durata del programma.

Usando l’heap, invece, il programma quando ha bisogno del vettore chiama la malloc, utilizza l’heap allocato, quando non ne ha più bisogno chiama la free per liberare la memoria e quindi prosegue la sua esecuzione. Pertanto invece di definire:

int vettore[1000];

possiamo definire un puntatore a interi: int *vettore;

e poi quando, durante l’esecuzione del programma, serve spazio: vettore = (int *) malloc (1000 * sizeof (int));

Nel caso (improbabile) che manchi memoria viene restituito NULL.

Possiamo ora gestire lo spazio riservato dalla malloc nello stesso modo in cui gestiamo un array, ad esempio:

vettore [671] = 5;

e quando lo spazio non ci serve più chiamiamo la funzione free: free (vettore);

(3)

Prog 52A – Selection sort con puntatori

Prog 45 lo riscriviamo usando i puntatori e l’allocazione dinamica. #include <stdio.h>

#include <stdlib.h>

void selesort (int n, int *x); main( )

{

int i, n, *x;

printf ("\nquanti numeri da ordinare ? "); scanf ("%d", &n);

printf ("\n");

x = (int *) malloc (n * sizeof(int)); for (i = 0; i < n; i++) {

printf ("i = %d x = ", i); scanf ("%d", x+i);

}

selesort (n, x);

printf ("\nlista ordinata:\n\n"); for (i = 0; i < n; i++)

printf ("i = %d x = %d\n", i, *(x+i)); return 0;

}

void selesort (int n, int *x) { int i, j, temp; for (i = 0; i < n-1; i++) for (j = i+1; j < n; j++) if (*(x+j) < *(x+i)) { temp = *(x+i); *(x+i) = *(x+j); *(x+j) = temp; } return; }

(4)

Il discorso fatto per i vettori può essere esteso alle matrici. Infatti, ogni riga di una matrice può essere vista come un vettore e pertanto possiamo, invece di definire la matrice mat nel modo usuale:

int mat [10] [30];

dichiarare un array di puntatori a interi: int * mat [10];

Osserviamo che va chiamata la funzione malloc dieci volte prima di poter avvalorare le righe di mat. A un certo punto potremmo, ad esempio, avere la seguente situazione: mat[0] 0 1 2 3 4 mat[1] 0 1 2 3 4 mat[2] 0 1 2 3 4 *(mat[2]+3) (mat[2]+3) ………. mat[9] 0 1 2 3 4

(5)

Quando, ad esempio, vogliamo avvalorare la riga di indice 3, dobbiamo innanzitutto riservare spazio con la malloc:

mat[3] = (int *) malloc(30 * sizeof(int));

Ora però, a differenza degli array monodimensionali, per accedere ai singoli elementi della matrice abbiamo bisogno dell’operatore *:

printf (“%d\n”, * (mat [3] + 5)); * (mat [3] + 5) = 77

Quando non abbiamo più bisogno di mat, basta chiamare la funzione di libreria free:

free (mat);

I puntatori risultano particolarmente utili quando bisogna gestire stringhe (Prog 52B). Infatti, possiamo equivalentemente scegliere di avvalorare con una stringa un array char nome oppure un puntatore pnome a char. Se voglio cambiare la stringa contenuta nell’array nome o modifico i singoli caratteri contenuti negli elementi dell’array oppure uso la strcpy. Invece, eseguendo l’istruzione:

pnome = “Paola Bianchi”;

la conseguenza è che pnome punterà a un nome diverso, o meglio al primo carattere del nome, prima puntava alla “S”, ora punta alla “P” cioè contiene l’indirizzo della “P”.

Ovviamente, se la stringa va letta con la scanf occorre preventivamente usare la malloc, ad esempio:

nome = (char *) malloc (12 * sizeof(char));

Possiamo anche definire un array nomi di puntatori a char per memorizzare una serie di stringhe. In sostanza, il programma tratta facilmente l’array nomi come se fosse un array di stringhe, noi però sappiamo che è in realtà un array di puntatori.

(6)

Prog 52B -

Gestione stringhe con i puntatori

#include <stdio.h>

#include <stdlib.h> main()

{

char nome[] = "Carlo Rossi"; char *pnome = "Silvia Verdi";

printf ("\n\n%s\n", nome); printf ("%s\n", pnome);

pnome = "Paola Bianchi"; printf ("\n%s\n\n\n", pnome);

char *nomi[3] = {"Carlo Rossi", "Silvia Verdi", "Paola Bianchi"}; int i;

for (i=0; i<3; i++)

printf ("nome %d: %s\n", i+1, nomi[i]); printf("\n\n\n");

return 0; }

Nel caso in cui le stringhe abbiano lunghezze molto diverse la gestione mediante matrici mi obbliga a definire un array bidimensionale con un numero di colonne pari alla lunghezza della stringa più lunga (+1 per il carattere nullo “\0”), invece la gestione mediante array di puntatori mi consente di allocare una quantità di spazio diversa per ciascuna stringa, ad esempio:

nomi[2] = (char *) malloc(80 * sizeof(char));

Osserviamo che il carattere di conversione %s e tutte le funzioni sulle stringhe lavorano bene sia sugli array tipo char sia sui puntatori tipo char in quanto sono la stessa cosa.

(7)

Prog 52C - Conta le parole presenti in una frase

#include <stdio.h> #include <stdlib.h> #include <ctype.h> int contaparole(char *s); main() { int n = 0; char s[80];

printf (“\ndigita una frase: “); scanf (" %[^\n]", s);

n = contaparole (s);

printf ("\n\nla frase contiene %d parole\n\n\n", n); return 0; } int contaparole(char *s) { int cont = 0; while (*s != '\0') { while (isspace (*s)) s++; if (*s != '\0') { cont++;

while ( !isspace (*s) && *s != '\0') s++;

} }

return cont; }

digita una frase: siamo andati a cinema la frase contiene 4 parole

(8)

La funzione isspace, il cui prototipo si trova nell’header file ctype.h, se il carattere è blank restituisce un valore diverso da zero (vero), altrimenti restituisce zero (falso).

La funzione contaparole va attentamente analizzata per capire il suo funzionamento e la necessità dei tre while uno nell’altro.

Il primo while serve a ciclare fino a quando non si arriva alla fine della frase.

Il secondo serve a saltare gli eventuale spazi iniziali. Nel momento in cui esco dal secondo while devo controllare che non sia giunto alla fine della frase, in caso negativo incremento cont, entro nel terzo while e ci resto finchè non incontro uno spazio o \0.

Se la frase non è finita, entro di nuovo nel secondo while per saltare gli spazi presenti e così via fino alla fine.

L’espressione presente nel terzo while è, al pari di quelle presenti nei Prog 8, 16, 28 abbastanza “naturale”, comunque, se non si vuole utilizzare l’operatore AND, possiamo scrivere il terzo while come segue:

while ( !isspace (*s))

if (*s != ‘\0’ ) s++;

(9)

Prog 46A – Trasposta e traccia di una matrice

La trasposta di una matrice quadrata si ottiene scambiando le righe con le colonne. La traccia di una matrice numerica quadrata A è la somma degli elementi presenti sulla diagonale principale.

Ad esempio, se n=3 e abbiamo la matrice:

3 5 1

4 2 3

5 1 7

la traccia vale 3 + 2 + 7 = 12 e la trasposta è:

3 4 5

5 2 1

1 3 7

#include <stdio.h>

void readmatrix (int a[] [50], int n, int m); void writematrix (int a[] [50], int n, int m); main()

{

int a[50][50], b[50][50], n,m, i,j, s1, temp; printf("ordine della matrice: ");

scanf("%d", &n); readmatrix(a, n, n);

s1 = 0;

for (i=0; i<n; i++) s1 = s1 + a[i][i];

(10)

printf("\nmatrice trasposta (quadrata - stessa matrice): \n\n"); for(i=0;i<n-1;i++) { for(j=i+1;j<n;j++){ temp=a[i][j]; a[i][j]=a[j][i]; a[j][i]=temp; } } writematrix (a,n,n);

printf("\n\nn. righe e n. colonne della matrice: "); scanf("%d%d", &n, &m);

readmatrix(a, n, m); printf("\nmatrice trasposta (n x m) -> (m x n): \n\n"); for(i=0;i<n;i++) { for(j=0;j<m;j++) { b[j][i]=a[i][j]; } } writematrix (b,m,n); return(0); }

void readmatrix (int a[][50], int n, int m) {

int i, j;

for (i = 0; i < n; i++) {

printf ("\ninserisci gli elementi della i di indice%2d\n", i); for (j = 0; j < m; j++)

scanf ("%d", &a[i][j]); }

return; }

void writematrix (int a[] [50], int n, int m) { int i, j; for (i = 0; i < n; i++) { for (j = 0; j < m; j++) printf ("%4d", a[i] [j]); printf ("\n\n"); } return; }

(11)

Prog 46B - Prodotto di matrici

La moltiplicazione righe per colonne di due matrici A e B è possibile se il numero delle colonne di A è uguale al numero di righe di B. Il valore del generico elemento cij della matrice prodotto C si ottiene effettuando

il prodotto scalare tra la i-ma riga di A e la j-ma colonna di B.

Ad esempio, se A e B sono le seguenti matrici (2x3 e 3x3, risp.), ricaviamo la matrice prodotto C:

4 3 1

1 0 2 x 2 0 2 = 4 5 7

0 3 1 0 1 3 6 1 9

#include <stdio.h>

void readmatrix (int a[][50], int n, int m);

void computeprod (int a[][50], int b[][50], int c[][50], int n, int m, int p);

void writematrix (int a[][50], int n, int m); main( )

{

int nrigheA, ncolArigheB, ncolB; int a[30][50], b[30][50], c[30][50]; printf ("\nn. righe matrice A: "); scanf ("%d", &nrigheA);

printf ("\nn. colonne di A = n. righe di B: "); scanf ("%d", &ncolArigheB);

printf ("\nn. colonne di B: "); scanf ("%d", &ncolB);

printf ("\n\nprima matrice:\n");

readmatrix (a, nrigheA, ncolArigheB); printf ("\n\nseconda matrice:\n");

readmatrix (b, ncolArigheB, ncolB);

computeprod (a, b, c, nrigheA, ncolArigheB, ncolB); printf ("\n\nmatrice prodotto:\n\n");

writematrix (c, nrigheA, ncolB); return 0; }

(12)

void computeprod (int a[][50], int b[][50], int c[][50], int n, int m, int p)

{

int i, j, k;

for (i=0; i<n; i++) for (j=0; j<p; j++) { c[i][j]= 0;

for (k=0; k<m; k++)

c[i][j] = c[i][j] + a[i][k] * b[k][j]; }

return; }

Osserviamo che il terzo for effettua il prodotto scalare tra la i-ma riga di A e la j-ma colonna di B, cioè ricava la somma dei prodotti degli elementi della riga i-ma di A per i corrispondenti elementi della colonna j-ma di B.

n. righe matrice A: 2

n. colonne di A = n. righe di B: 3 n. colonne di B: 2

prima matrice:

inserisci gli elementi della riga di indice 0: 1 0 2 inserisci gli elementi della riga di indice 1: 0 3 1 seconda matrice:

inserisci gli elementi della riga di indice 0: 4 3 1 inserisci gli elementi della riga di indice 1: 2 0 2 inserisci gli elementi della riga di indice 2: 0 1 3 matrice prodotto:

4 5 7 6 1 9

(13)

Prog 46C – Derivazione numerica

Derivazione ed integrazione sono operazioni basilari in molte aree

applicative ed è pertanto necessario disporre di metodi efficienti per il calcolo di derivate ed integrali. Le usuali regole di derivazione sono importanti per il calcolo delle derivate, nel caso degli integrali, invece, spesso questi non possono essere calcolati con metodi simbolici e bisogna ricorrere ad approssimazioni numeriche la cui bontà deve essere valutata con attenzione calcolando gli errori di approssimazione.

La derivazione numerica di una funzione f(x) può essere utilizzata quando l’espressione analitica della funzione è molto complicata. Inoltre, spesso nelle applicazioni una funzione è nota solo per punti.

Ad esempio, poiché il sistema GPS ci consente di valutare la posizione di un’automezzo agli istanti scelti, noi vorremmo conoscere la sua velocità: se avessimo la posizione espressa come funzione continua del tempo, otterremmo la velocità derivando la funzione, poiché conosciamo solo la posizione in alcuni istanti, dobbiamo ricorrere alla derivazione numerica. Il linguaggio MATLAB include il comando “diff” che calcola il valore approssimato di una derivata, noi ci limitiamo solo a ricordare la definizione di derivata come limite del rapporto incrementale:

f ’(x) = lim h->0 f(x+h) – f(x)

h

Dalla definizione ricaviamo subito un valore approssimato per f ‘(x0):

f ’(x0)  f(x0+h) – f(x0)

h

In pratica, dato x0, consideriamo due punti x1 e x2 a destra e sinistra di

x0 e a lui vicinissimi e calcoliamo il valore:

f ’(x0)  f(x2) – f(x1)

(14)

#include <stdio.h> #include <math.h> main()

{

double der, delta, x0, x1, x2, y1, y2; x0 = 0.; delta = 1.0e-6; x1 = x0 - delta; x2 = x0 + delta; y1 = sin(x1); y2 = sin(x2);

der = (y2 - y1) / (x2 - x1); printf("\n%f\n\n", der); return 0; } FUNZIONE DERIVATA X0 f ‘(x0) sin cos 0 1 sin cos 3.14 -1 cos -sin 3.14 0 cos -sin 1.57 -1 sqrt ½ x1/2-1 1 0.5 sqrt ½ x1/2-1 25 0.1 exp ex 1 2.71 log 1/x 10 0.1

(15)

Prog 46D – Integrazione numerica: rettangoli e trapezi

L’integrale di una funzione f(x) integrabile in [a,b], se si conosce una primitiva F(x) della funzione, è dato da:

L’integrale può essere difficile da calcolare per vari motivi: - non si conosce la primitiva

- la si conosce ma è molto complicata - la funzione da integrare è nota per punti

In questi casi si cerca un valore approssimato dell’integrale. Ricordiamo che l’integrale definito in [a,b] ha un significato geometrico preciso: rappresenta l’area compresa tra il grafico della funzione f(x), l’asse x e le due rette verticali x=a e x=b.

Pertanto, è possibile valutare tale area considerando la somma delle aree dei rettangoli aventi base sull’asse x e altezza pari alla funzione calcolata nei vari punti.

Il metodo dei rettangoli consiste nel suddividere l’intervallo di integrazione in n parti di lunghezza h e poi calcolare il valore approssimato dell’integrale come somma delle aree di tali rettangoli.

L’area di ciascun rettangolo è data dalla formula: h * f (i) con i punto variabile tra a e b.

E’ possibile avere un’approssimazione migliore prendendo l’altezza pari al valore della funzione calcolata nel punto al centro della base.

(16)

Il metodo dei trapezi, invece, ricava il valore approssimato dell’integrale sommando le aree dei trapezi rettangoli aventi per basi i valori f (i) e f(i+h) e altezza h.

Ricordando che la formula dell’area di un trapezio avente basi B e b e altezza h è data da (B +b)*h/2, l’area di ciascun trapezio è data da (f(i)+f(i+h))*h/2.

#include <stdio.h> #include <math.h> float funz (float x); main() {

float h,a,b,integ = 0.,n,i;

printf("\nestremi dell'intervallo: "); scanf("%f%f", &a , &b);

printf("\nnumero intervalli di suddivisione: "); scanf("%f", &n);

h=(a+b)/n;

for(i=a; i<b; i=i+h) {

integ = integ + h * funz(i+h/2); }

printf("\nl'integrale della funzione (rettangoli) = %f\n\n", integ); integ = 0.;

for(i=a; i<b; i=i+h) {

integ = integ + (funz(i) + funz(i+h)) * h/2; }

printf("\nl'integrale della funzione (trapezi) = %f\n\n", integ); return 0;

}

float funz (float x) {

return (exp(x)+log(x)); }

(17)

Prog 57 – Compressione RLE (Prova pratica 2/2015)

L’algoritmo di compressione RLE (Run-Length Encoding) è un semplice algoritmo che serve a compattare runs (sequenze in cui lo stesso dato si ripete più volte consecutivamente) sostituendoli con una coppia (numero ripetizioni, dato). Funziona bene quando vi sono sequenze con molti dati ripetuti (ad esempio, immagini con pochi colori).

La “prova pratica” di febbraio 2015 prevedeva la stesura di un programma per la compressione RLE.

Il programma, letto da un file di testo un insieme di sequenze di caratteri in formato compresso o non compresso, nel primo caso espande le sequenze, mentre nel secondo le comprime. Il programma visualizza le sequenze input e output e memorizza in un file le sequenze output.

Ad esempio, la sequenza non compressa aaabaaaaccccc viene compressa in 3a1b4a5c, mentre la sequenza compressa 7v5c2b viene espansa in vvvvvvvcccccbb.

Assunzioni:

a) ogni riga del file contiene una sola sequenza da comprimere o decomprimere;

b) la scelta di comprimere o decomprimere viene effettuata al runtime c) lunghezza massima dei runs = 9

(18)

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <math.h> #define MAXSEQ 100 #define NCAR 100 FILE *Apri_File(char *);

int Leggi_Sequenze(FILE *, char [][NCAR]);

void Comprimi(char [][NCAR], char [][NCAR], int); void Decomprimi(char [][NCAR], char [][NCAR], int); void Write_Risultato(FILE *, char [][NCAR], int); void Stampa_Sequenze(char [][NCAR], int);

int main () {

FILE *fpin, *fpout;

char scelta, sequenze[MAXSEQ][NCAR], zip_unzip[MAXSEQ][NCAR]; int n;

do{

printf("Scegli cosa fare:\n"); printf("c - Comprimere:\n"); printf("d - Decomprimere:\n"); scanf("%c", &scelta);

getchar();

} while (scelta != 'c' && scelta != 'd'); if( scelta == 'c' ) {

fpin = Apri_File("r");

if((n = Leggi_Sequenze(fpin, sequenze)) == 0 ) { printf("Nessuna operazione da effettuare.\n"); system ("pause"); return EXIT_SUCCESS; } Stampa_Sequenze(sequenze, n); Comprimi(sequenze, zip_unzip, n); Stampa_Sequenze(zip_unzip, n); fclose(fpin); } else {

(19)

fpin = Apri_File("r");

if((n = Leggi_Sequenze(fpin, sequenze)) == 0 ) { printf("Nessuna operazione da effettuare.\n"); return EXIT_SUCCESS; } Stampa_Sequenze(sequenze, n); Decomprimi(sequenze, zip_unzip, n); Stampa_Sequenze(zip_unzip, n); fclose(fpin); } fpout = Apri_File("w"); Write_Risultato(fpout, zip_unzip, n); fclose(fpout); return EXIT_SUCCESS; } /*

La funzione ApriFile apre il file il cui nome e' specificato dall'utente nella modalità indicata dal parametro formale mode e restituisce il puntatore al file */

FILE *Apri_File(char* mode) {

char nome_file[NCAR]; FILE *fptr;

printf("\nInserire nome file: "); scanf("%s", nome_file);

if((fptr = fopen(nome_file, mode)) == NULL) {

printf("Errore apertura file %s.\n", nome_file); exit(EXIT_FAILURE);

}

return fptr; }

/*

La funzione Leggi_Sequenze prende in ingresso il puntatore al file di dati input e la matrice di caratteri destinata a contenere le sequenze da

immagazzinare. Legge le sequenze e restituisce il numero di sequenze lette. */

int Leggi_Sequenze(FILE *fpin, char str[][NCAR]) {

/* FUNZIONE DA COMPLETARE */ }

(20)

/*

La funzione Stampa_Sequenze prende in ingresso la matrice di char contenente le sequenze e il loro numero. Visualizza le sequenze. */

void Stampa_Sequenze(char str[][NCAR], int n) {

int i;

printf ("\n\n"); for (i=0; i<n; i++)

printf("%s\n", &str[i][0]); printf ("\n\n");

return; }

/*

La funzione Comprimi prende in ingresso la matrice str contenente le

sequenze da comprimere, la matrice zip che conterrà le sequenze compresse e il loro numero. Comprime le sequenze.

*/

void Comprimi(char str[][NCAR], char zip[][NCAR], int n) {

/* FUNZIONE DA COMPLETARE */ }

/*

La funzione Decomprimi prende in ingresso la matrice str contenente le sequenze da espandere, la matrice unzip che conterrà le sequenze espanse e il loro numero. Espande le sequenze.

*/

void Decomprimi(char str[][NCAR], char unzip[][NCAR], int n) {

/* FUNZIONE DA COMPLETARE */ }

/*

La funzione Write_Risultato prende in ingresso il puntatore al file di output, la matrice str contenente le sequenze (compresse o decompresse) e il loro numero. Inserisce le sequenze nel file di output.

*/

void Write_Risultato(FILE *fp, char str[][NCAR], int n) {

int i;

for(i = 0; i < n; i++)

fprintf(fp, "%s\n", str[i]); }

(21)

Le funzioni mancanti sono le seguenti:

int Leggi_Sequenze(FILE *fpin, char str[][NCAR]) { int k=0, j=0, n=0; while ( ! feof(fpin)) { fscanf (fpin,"%s", str[n]); n++; } return(n); }

void Comprimi(char str[][NCAR], char zip[][NCAR], int n) {

int runlun, lun, temp; int i, j,k;

for (k=0; k<n; k++) { lun = strlen(str [k]); j=0;

for(i=0; i<lun; i++) { zip[k][j++] = str[k][i]; runlun= 1;

while(i < lun-1 && str[k][i] == str[k][i+1]) { runlun++; i++; } zip[k][j++]=runlun+48; } lun = strlen(zip[k]); for (i=0; i<lun-1; i=i+2) { temp = zip[k][i]; zip[k][i]=zip[k][i+1]; zip[k][i+1]=temp; } zip[k][j] = '\0'; } return; }

(22)

void Decomprimi(char str[][NCAR], char unzip[][NCAR], int n) {

int runlun, lun; int i, j, k,l;

for (k=0; k<n; k++) { l=0;

lun = strlen(str[k]);

for(i=0; i<lun-1; i=i+2) { runlun=str[k][i]-48; for (j=1; j<=runlun; j++) { unzip[k][l] = str[k][i+1]; l++; } } unzip[k][l] = '\0'; } return; }

Accedere al “Blocco note” e digitare le sequenze (una per riga) da comprimere o espandere. Salvare con, ad esempio, il nome “inputrle”. Eseguire il programma:

scegli cosa fare: c – comprimere d – decomprimere c

inserire nome file: inputrle.txt yyywerss

kfbbbx 3y1w1e1r2s 1k1f3b1x

inserire nome file: outputrle.txt

Rieseguendo il programma con file input “outputrle.txt” si ha l’espansione.

Riferimenti

Documenti correlati

Immaginiamo ora di spostare il nostro strumento di acquisizione (la videocamera nel caso del paesaggio o la sonda ecografica nel caso dell’arteria) nello spazio all’interno di

I risultati dell’applicazione di una stessa trasformazione in RGB e HSI non sono, però, perfettamente identici (perché la conversione tra i due spazi colore può comportare

I: il valore di ciascun elemento dello array di numeri interi Pi: il numero degli elementi da inserire non può essere maggiore della cardinalità dell’array.. U: lo array

I: riempimento; il valore di ciascun elemento dello array Pi: il numero degli elementi da inserire (riempimento) non può essere maggiore della cardinalità dell’array.. U:

I: riempimento; il valore di ciascun elemento dello array Pi: il numero degli elementi da inserire (riempimento) non può essere maggiore della cardinalità dell’array.. U:

Conviene acquisire N flat field e bias e farne la media (l'errore sul valore medio cala come la ) √ N.

Per ogni studente, di cui viene dato un numero d’ordine e il numero di matricola, alla riga successiva viene dato il numero del compito e, nella riga dopo, il numero di domande a cui

CERTIFICAZIONI percorso finalizzato all’ottenimento o rinnovo delle certificazioni di prodotto necessarie per esportare in uno o più dei Paesi esteri target individuati nel