36
LdL - LP1 - lez 11 - ver 6 - aa 05-06 1 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

Embed Size (px)

Citation preview

Page 1: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 1

Linguaggi di programmazione IStringhe (II)

Prof. Luigi Di Lascio

Lezione 11

Page 2: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 2

Gli argomenti di questa lezione (12°)

• Richiami• La funzione sizeof• Allocazioni dinamica della memoria: malloc,

free• Input, Output di Stringhe, di Testo• Funzioni per il trattamento di stringhe nella

librerie standard• Stringhe e Puntatori• Stringhe come array di puntatori

Page 3: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 3

Richiami: Il tipo char (I)

Il dominio D del tipo char è dato da:• le lettere dell’alfabeto (maiuscole, minuscole)• segni di punteggiatura• cifre decimali: ‘0’, ‘1’, … ‘9’• altri simboli: quelli della tabella dei codici

ASCII • il dominio D associato al tipo char è ordinato,

l’ordine è dato dal codice ASCII: 0 … 255• il C rappresenta i dati di tipo char come degli

interi: ogni carattere è rappresentato dal suo codice ASCII

Page 4: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 4

• Dichiarazioni di variabili di tipo char: char nome_variabile

• Costanti di tipo char: ogni valore di tipo char viene specficato tra singoli apici: ‘a’, ‘b’, ‘2’, ....

• Dimensione della Rappresentazione: sizeof(char) (vedi dopo)

• Operatori relazionali: ==, !=, <=, =>, >, <• Relazione d’ordine x<=y sse

ASCII(x)<=ASCII(y)• Operatori aritmetici e logici: quelli visti per il

tipo int

Richiami: Il tipo char (II)

Page 5: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 5

‘C’ < ‘a’ VERO, perché 67<97‘1’+’A’=ASCII(‘1’)+ASCII(‘A’)=carattere(49+65) =

CARATTERE(114) = ‘r’!’A’ FALSO, ‘A’ && ‘a’ VERO

Richiami: Il tipo char (III)

#include <stdio.h>

int main() {

int x;

x='A'+'B';

printf("%d\n",x);

printf("%c\n",x);

return 0;}

131

â

Premere un tasto per continuare . . .

Page 6: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 6

Richiami: Stringhe e PuntatoriDichiarazioni equivalenti di stringhe:• char *corso = “LP1”;• char *corso; /* attenzione: occorre inizializzarlo */ • char corso[] = “LP1”;• char corso[4]; /* attenzione: occorre inizializzarlo */;• char corso[4] = {‘L’, ‘P’, ‘1’, ‘\0’};• char corso[] = {‘L’, ‘P’, ‘1’, ‘\0’};

Quando usate un puntatore per definire una stringa, l’imprevedibilità della lunghezza della stringa impone di allocare dinamicamente spazio in memoria per la gestione della stringa.

Page 7: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 7

sizeof(espressione) oppure sizeof(tipo) L’operatore sizeof restituisce la memoria necessaria per espressione o per tipo.

Dimensione della memoria utilizzata per rappresentare espressioni o dati: sizeof()

Esempi:char a[10]; int i; char c; double d;i = sizeof(a[10]);printf("L'array %s ha dimensione = %d\n", a, i);i = sizeof(int);printf("Gli interi hanno dimensione %d", i);c = sizeof(char);printf(“I caratteri hanno dimensione %c", c);d = sizeof(double);printf(“Un dato di tipo double hanno dimensione %lf", d);

Page 8: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 8

sizeof() : implementazione

#include <stdio.h>

int main(void) {

printf(“char:%3d byte\n”, sizeof(char));

printf(“int:%3d bytes\n”, sizeof(int));

printf(“long:%3d bytes\n”, sizeof(long));

printf(“float:%3d bytes\n”, sizeof(float));

printf(“double:%3d bytes\n”, sizeof(double));

printf(“long double:%3d bytes\n”, sizeof(long double));

return (0);}

char: 1 byte

int: 2 bytes

long: 4 bytes

float: 4 bytes

double: 8 bytes

long double: 10 bytes

Page 9: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 9

Allocazione dinamica di spazio in memoria

La funzione malloc() in <stdlib.h> è utilizzata a tal fine. Vediamo come.

Allocazione di memoria per una stringa di 100 caratteri

Dichiarazione char * str;

str = (char *) malloc(100*sizeof(char));

Allocazione di memoria per un array di 50 interi

Dichiarazione int *elementi;

elementi = (int *) malloc(50*sizeof(int));

(tipo *) malloc(n*sizeof(tipo))alloca un blocco di memoria per n dati di tipo tipo

Page 10: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 10

Allocazione dinamica di spazio in memoriaLa funzione malloc() in <stdlib.h> è utilizzata a tal

fine. Vediamo come.

Allocazione di memoria per una stringa di 100 caratteri

Dichiarazione char * str;

str = (char *) malloc(n_var*sizeof(char));

Allocazione di memoria per un array di 50 interi

Dichiarazione int *elementi;

elementi = (int *) malloc(n_var*sizeof(int));

(tipo *) malloc(n_var*sizeof(tipo))alloca un blocco di memoria per n dati di tipo tipo

Page 11: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 11

Allocazione dinamica di spazio in memoria: malloc

if((str=(char *) malloc(100*sizeof(char))) == NULL) { printf(“memoria insufficiente”);exit(-1);}

#include <stdio.h>

#include <stdlib.h>

char i, *pPtr, *p;

int main() {

/* riserva un blocco per stringa di 34 caratteri*/

pPtr=(char*)malloc(35*sizeof(char));

if(pPtr==NULL) {

{puts(“no memoria”); exit(-1);}

Ma bisogna assicurarsi che la memoria richiesta sia disponibile ogni volta che si usa malloc(). Come si fa?

p=pPtr; /* salviamo l’indirizzo iniziale */

for(i=65;i<91;++i)

*p++=i; /* {*p=i; p++;}*/

*p = ‘\0’;

puts(pPtr);

return 0;}

Out del programma: ABC……………XYZ

Page 12: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 12

Allocazione dinamica di spazio in memoria: free

#include <stdio.h>

#include <stdlib.h>

char i, *pPtr, *p;

int main() {

pPtr=(char*)malloc(35*sizeof(char));

if(pPtr==NULL) {puts(“no memoria”); exit(-1)};

……

pPtr=free(pPtr);

…..

return 0;}

Come si rende di nuovo libero un blocco di memoria allocato dinamicamente con malloc() ? Con free() in <stdlib.h>.

free(pPtr); /* rilascia il blocco di memoria al quale punta pPTR */

Page 13: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 13

Visualizzazione di stringhe e caratteri

Input di stringhe, caratteri e testo su più righe

Page 14: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 14

Visualizzazione di stringhe e caratteri

#include <stdio.h>

int main() {

char *parola =“oggi”;

puts(parola);

return 0;

}

La funzione puts()

Page 15: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 15

Visualizzazione di stringhe e caratteri

#include <stdio.h>int main() { char *parola =“oggi”; printf(“%s”, parola); return 0;}

La funzione printf()

Page 16: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 16

Visualizzazione di stringhe e caratteri

#include <stdio.h>

int main() {

char *parola =“oggi”;

while(*parola!=‘\0’) {

printf(“%c”, *parola);

++parola; }

return 0;}

Carattere per Carattere

Page 17: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 17

Input di stringhe dalla tastiera

gets() riceve una stringa dalla tastiera, leggendo tutti i caratteri digitati fino a quando non viene premuto INVIO, in tal caso scarta tale carattere e aggiunge il carattere di terminazione ‘\’0

La funzione gets() /1

#include <stdio.h>int main() { char input[81]; puts(“Inserire un testo e premere INVIO: “); gets(Input); printf(“\n%s”, Input); return 0;}

Page 18: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 18

Input di più righe di testo dalla tastiera

#include <stdlib.h>#include <stdio.h>int main(){ char input[81],*pPtr; puts("Inserire la riga premere INVIO. "); puts("Per terminare non digitare nulla e premere INVIO\n"); while(*(pPtr=gets(input))!= NULL) printf("DIGITATO: %s\n",input); /* printf("\nDIGITATO: %s\n",input);*/ return 0;}

La funzione gets() /2a

gets() restituisce un valore che rappresenta un puntatore al tipo char con l’indirizzo al quale è stata memorizzata la stringa

char *gets(char *str)

Page 19: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 19

Input di più righe di testo dalla tastiera

Inserire la riga premere INVIOPer terminare non digitare nulla e premere INVIO

oggiDIGITATO: oggisonoDIGITATO: sonoandatoDIGITATO: andatoal mareDIGITATO: al mare

DIGITATO:Premere un tasto per continuare . . .

La funzione gets() /2b

Page 20: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 20

Input di stringhe dalla tastiera

#include <stdio.h>int main() { char *parola =“oggi”; scanf(“%s”, parola); return 0;}

La funzione scanf()

AAA! scanf() non vede gli spazi vuoti!

Page 21: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 21

Funzioni per il trattamento di stringhe

nella libreria <string.h>

Page 22: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 22

size_int strlen(const char *s)

#include <stdio.h>#include <string.h>int main(void){ char *s1="abc"; char *s2="four"; char *s3="cinque"; printf("Lunghezza di %s = %d\n",s1, strlen(s1)); printf("Lunghezza di %s = %d\n",s2, strlen(s2)); printf("Lunghezza di %s = %d\n",s3, strlen(s3)); return(0);}

Funzioni per il trattamento di stringhe nella libreria <string.h> /1

Page 23: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 23

Funzioni per il trattamento di stringhe nella libreria <string.h> /2

char *strcpy(char *s1, const char *s2)

copia la stringa s2 nell’array s1 e ritorna s1

char *strncpy(char *s1, const char *s2, size_t n)

copia al più n caratteri di s2 nell’array s1 e ritorna s1

char *strcat(char *s1, const char *s2)

attacca la stringa s2 all’array s1, quindi ritorna s1.

char *strncat (char *s1, const char *s2, size_t n)

attacca al più n caratteri della stringa s2 all’array s1, quindi ritorna s1

Page 24: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 24

Funzioni per il trattamento di stringhe /2 : esempio/a

#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){ char x[]="Ciao"; char y[10], z[3];

strcpy(y,x); printf("stringa in x = %s, stringa in y = %s\n",x,y);

strncpy(z,x,2); z[2]='\0'; printf("stringa in z = %s\n",z);

return 0;}

Page 25: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 25

Funzioni per il trattamento di stringhe /2 : esempio/a

stringa in x = Ciao

stringa in y = Ciao

stringa in z = Ci

Premere un tasto per continuare . . .

Page 26: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 26

Funzioni per il trattamento di stringhe /2 : esempio /b

#include <string.h>#include <stdio.h>#include <stdlib.h>int main(){ char s1[20]="Happy "; char s2[]= "New Year "; char s3[]= " "; printf("s1 = %s\ns2 = %s\n", s1, s2); strcat(s1,s2); printf("s1+s2=%s\n",s1); strncat(s3,s1,6); printf("s3+s1(3 car) =%s\n", s3); strcat(s3,s1); printf("s3+s1=%s\n", s3); return 0;}

Page 27: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 27

Funzioni per il trattamento di stringhe /2 : esempio /b

s1 = Happy

s2 = New Year

s1+s2=Happy New Year

s3+s1(3 car) = Hap

s3+s1= HapHappy New Year

Premere un tasto per continuare . . .

Page 28: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 28

int strcmp( const char *s1, const char *s2)

confronta le stringhe s1 ed s2; se s1<s2 dà un numero negativo, se s1==s2 dà zero, se s1>s2 dà un numero positivo (ordine lessicografico)

int strncmp( const char *s1, const char *s2, size_t n)

confronta i primi n caratteri di s1 con i primi n caratteri di s2; il valore restituito segue le regole date sopra

Funzioni per il trattamento di stringhe nella libreria <string.h> /3

Page 29: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 29

Array di Puntatori: array di stringhe

Inizializzazione, Scansione per Stringhe

Immissione di un testo su più righe fissate

Passaggio di un array di puntatori ad una funzione

Page 30: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 30

Array di Puntatori: array di stringhe

#include <stdio.h>

int main() {

char *parole[3] = {“oggi”,”domani”,”mai”};

int i;

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

printf(“%s”, parole[i]);

return 0;

}

Inizializzazione, Scansione per Stringhe

Page 31: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 31

Array di Puntatori: array di stringheImmissione di un testo su più righe fissate

#include <string.h>#include <stdio.h>#include <stdlib.h>#define NUM_RIGHE 3int main() { char *parole[NUM_RIGHE], stringa[80+1]; int i; for(i=0;i<NUM_RIGHE;++i) { gets(stringa); parole[i]=(char *)malloc((strlen(stringa)+1)*

sizeof(char)); if(parole[i]==NULL) exit(EXIT_FAILURE); strcpy(parole[i], stringa); } for(i=0;i<NUM_RIGHE;++i) printf("%d: %s\n",i,parole[i]);return 0;}

exit(EXIT_SUCCESS)terminazione con successoexit(EXIT_FAILURE)terminazione con

fallimento

oggi sono

andato al

mare

0: oggi sono

1: andato al

2: mare

Premere un tasto per continuare . . .

Page 32: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 32

Array di Puntatori: array di stringhe

#include <stdio.h>

void visualizza(char *[], int);

int main() {

char *parole[3] = {“oggi”,”domani”,”mai”};

visualizza(parole, 3);

return 0;

}

Passaggio di un array di puntatori ad una funzione

void visualizza(char *pPtr[], int n)

{

int i; for(i=0;i<n;++i) printf(“%s\n”, pPtr [i]);return ;}

oggi domani mai Premere un tasto per continuare . . .

Page 33: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 33

Array di Puntatori: ultimo esempio /1La dichiarazione char *semi[4]={“cuori”, “picche”, “quadri”,

“fiori”} ha il seguente significato:• semi[4] indica un array di 4 elementi• char * indica che ogni elemento dell’array sarà del tipo

“puntatore a char”, quindi …• ognuno degli elementi sarà immagazzinato in memoria come

una stringa di caratteri terminata da ‘\0’. • Per accedere a questi elementi, basta sapere che: • semi[0] punta a (contiene l’indirizzo della locazione di

memoria con) ‘c’ (di cuori), semi[1] a ‘p’ (di picche), semi[2] a ‘q’ di (di quadri), semi[3] a ‘f’ (di fiori).

• ++semi[0]: permette di avanzare lungo “cuori”• ++semi[1]: permette di avanzare lungo “picche”• ++semi[2]: permette di avanzare lungo “quadri”• ++semi[3]: permette di avanzare lungo “fiori”

Page 34: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 34

Array di Puntatori: ultimo esempio /2

Input, Scansione per Carattere

per giovedi’

Progettare e implementare un programma che accetti a tempo di esecuzione l’array seguente {“cuori”, “picche”, “quadri”, “fiori”}, quindi visualizzi l’array carattere per carattere, segnalando la fine di ogni stringa

Progettare e implementare un programma che accetti a tempo di esecuzione l’array seguente {“cuori”, “picche”, “quadri”, “fiori”}, quindi visualizzi l’array carattere per carattere, segnalando la fine di ogni stringa, mediante un’opportuna funzione

Page 35: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 35

Array di Puntatori: ultimo esempio /3

Provate, allenatevi, riprovate, riallenatevi

Linguaggi di Programmazione 1Appello, 26 novembre 2004, ore 14, aule C31 (matr. 6), C38

(matr. 7)prof. Luigi Di Lascio

 3) Progetta ed implementa in C una funzione, i cui parametri di

input sono un array di n parole della lingua italiana e due caratteri dell’alfabeto della lingua italiana, che calcoli la frequenza dei due caratteri nell’array (p. 15)

Page 36: LdL - LP1 - lez 11 - ver 6 - aa 05-061 Linguaggi di programmazione I Stringhe (II) Prof. Luigi Di Lascio Lezione 11

LdL - LP1 - lez 11 - ver 6 - aa 05-06 36

Array di Puntatori: aiutoProvate, allenatevi, riprovate, riallenatevi

#include <stdio.h>int main() { char *semi[4]={"cuori", "picche", "quadri", "fiori"}; printf("%c\n",*semi[0]); /*c*/ printf("%c\n",*(semi[0]+2)); /*o*/ printf("%c\n",*semi[1]); /*p*/ printf("%c\n",*(semi[1]+1)); /*i*/ printf("%c\n",*semi[2]); /*q*/ printf("%c\n",*(semi[2]+3)); /*d*/ printf("%c\n",*semi[3]); /*f*/ printf("%c\n",*(semi[3]+1)); /*i*/ return 0;}