NGI.Home > Forum
  EOLO HOME  OFFERTE INTERNET WIRELESS EOLO  FORMULA ADSL
   
   
WEBMAIL
   
 
  > Register  
  > FAQ  
  > Members List  
 
  > Calendar  
  > Today's Posts  
   
 

Go Back   NGI Forum > Tech & Tech > Developer's Zone

Reply
 
Thread Tools Rate Thread
Old 6th December 2010, 14:34   #1
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,478
[Impariamo il C] Lezione 4

Buongiorno.

Prosegue il corso collaborativo di programmazione.

Riassunto delle puntate precedenti:
  1. installazione dell'IDE, cenni di architettura degli elaboratori
  2. sintassi del C, programmazione strutturata
  3. ancora sulla sintassi, i tipi di dato, le variabili
In questo capitolo:
  • ancora qualche parola sulle variabili: gli array

Variabili parte seconda

Abbiamo visto nella lezione 3 che esistono vari tipi di dato e principalmente sono: caratteri (1 byte), interi (4 bytes), reali a virgola mobile (4 bytes) o a doppia precisione (8 bytes).

Tuttavia, se ricordiamo l'hello world, non ci tornano i conti: gli argomenti delle nostre funzioni printf e system erano qualcos'altro.

Code:
void main()
{
  printf("Hello World!\n");
  system("pause");
}
Sappiamo già che quelle cose sono dette stringhe. Le stringhe sono sequenze di caratteri. Per questa ragione non sono detti tipi fondamentali: perché si realizzano a partire da un tipo più semplice (il carattere, appunto).

L'argomento stringa è complesso e lo vedremo di nuovo dopo le lezioni sui puntatori. Per ora immaginiamole così:

Ricordate il discorso sulle variabili? programmando diciamo al computer che vogliamo riservare un blocchetto di memoria di un certo tipo.

Usando le stringhe riserviamo blocchetti di memoria, dichiarati come caratteri e "compattati insieme" per formare, appunto, stringhe (ogni cubetto dell'immagine quì sopra è uno di quei blocchetti).

Si osservi come lo spazio è un carattere a tutti gli effetti. Si noti, inoltre, come ciò che noi scriviamo come "\n" (che è il ritorno a capo in C) è considerato dal computer un carattere unico.

Dunque, quando in C utilizziamo le virgolette per circondare del testo, lui lo considera una stringa e alloca la memoria necessaria.

Code:
"Hello World!\n"
A qualunque funzione di aspetti una stringa in ingresso possiamo passare una frase tra virgolette. Ma come dichiariamo una variabile di tipo stringa? Ecco che arriva la sintassi:

Code:
char frase[13] = "Hello World!\n";
In questo modo frase diventa una sequenza di blocchi di caratteri, inizializzata per contenere esattamente "Hello World!\n".


La sintassi appena introdotta con le parentesi quadre non è specifica delle stringhe, ma è quella più generale degli array, ovvero sequenze di un certo tipo di dato.

Dichiarando la variabile di tipo char "frase" con [13] gli abbiamo detto che frase rappresenta una sequenza di 13 caratteri. Ogni carattere ha una posizione che va da 0 a 12 (attenzione a questo fatto! in informatica, nei linguaggi SERI, si parte sempre a contare da zero).

Dunque, se io voglio leggere il terzo carattere della stringa, posso accedere ad esso con frase[2]:

Code:
printf ( frase[2] );
output = l


In sostanza stiamo dicendo "ehi, fammi dare un'occhiata al blocco numero 2"!

Con la stessa sintassi a base di parentesi quadre possiamo riferirci (stavolta) ad un singolo blocco dell'array e usare l'operatore di assegnamento:

Code:
frase[2]='k';      // metti k nel blocco #2 dell'array, cioé il terzo
printf ( frase );
output = Heklo World!


Si osservi che, a differenza di quanto avviene con le stringhe, quando ci si riferisce ad un carattere si deve usare il singolo apice ' .


Naturalmente, gli array non sono solo per i caratteri. Possiamo fare array di interi, float, double... perfino array di array! (e lo vedremo in una delle prossime lezioni). Ad esempio, una coordinata 3D potrebbe essere definita come

Code:
float coordinata[3];
Saremo noi a stabilire che la coordinata 0 si riferisce alle X, la coordinata 1 alle Y e la coordinata 2 alle Z. Suona un po' macchinoso? Forse sì, per questo sono state introdotte le struct, strutture dati complesse ma dal significato più chiaro che vedemo a metà corso.


Okay, ora sappiamo come creare delle variabili contenenti del testo libero o dei numeri. Potrà sembrare limitativo il fatto che dobbiamo dichiarare gli array della stessa dimensione del dato in ingresso (13 nell'esempio), ma vedremo in futuro come aggirare questo problema. Per ora cerchiamo di "intuire" quanto sia la dimensione minima per il nostro input. Chiariamo con l'esercizio.


Esercizio: sapendo che la sintassi per leggere una stringa e versarla in un array di caratteri chiamato "variabile" è

Code:
scanf( "%s", &variabile);
scrivete un codice che stampi a video

Inserire il proprio nome:

legga (con scanf) una stringa (cioè il nome di chi usa il programma, ad esempio "pippo") e scriva a video

Benvenuto Mr. pippo, che ne direbbe di una bella partita a scacchi?


Torneremo ancora sulle variabili con una terza lezione, ma dopo aver introdotto le funzioni. Alla prossima e buon ponte (per chi lo fa ).
Attached Images
File Type: png hw!.png (5.1 KB, 380 views)
__________________
Lode a Bacco, in saecula saeculorum.
Emergent

Last edited by Arësius; 7th December 2010 at 12:49.
Arësius is offline   Reply With Quote
Old 6th December 2010, 14:42   #2
Kaehell
l33t school
 
Kaehell's Avatar
 
Join Date: Mar 2008
Location: Zìria
Posts: 14,633
buco per esercitazione

edit: che palle ma solo array, e io che esercitazioni metto? ora mi invento qualcosa
__________________
"...the three great virtues of a programmer: laziness, impatience, and hubris." - Larry Wall
The e.Ngineering Xperience
BattleNet - Kaeh#2263 || Diablo3 - Kaeh

Last edited by Kaehell; 6th December 2010 at 14:44.
Kaehell is offline   Reply With Quote
Old 6th December 2010, 15:07   #3
nanomad
Dietro le sbarre
 
nanomad's Avatar
 
Join Date: Apr 2005
Location: Papia (olim Ticinum)
Posts: 5,221
AHHHH!!!! AHHH!!!
Aresio cosa mi combini, introduci il carattere "terminatore di stringa \0" oppure questi poveri fanciulli combinano un casino

Addendum sulle stringhe:

in C una stringa è un array di caratteri

char stringa[13]

Come fa a sapere il nostro computer dove finisce una stringa? Semplice l'ultimo elemento della stringa è un '\0'. Ad esempio:
Code:
"ciao" = 'c' + 'i' + 'a' + 'o' + '\0'
così facendo possiamo usare un array molto grande (e.g. char superlungo[255]) per metterci dentro stringhe molto corte.
Quando facciamo la scanf con "%s" C aggiunge per noi il terminatore di stringa, ma dobbiamo comunque ricordarci di fare un'array abbastanza grande (lunghezza della stringa + 1)

Se non è chiaro ditelo
__________________
Rivuoi i video nel forum? Usa questa estensione (chrome)
Source & firefox version
"(...) the three great virtues of a programmer: laziness, impatience, and hubris." -- LarryWall

Last edited by nanomad; 6th December 2010 at 15:11.
nanomad is offline   Reply With Quote
Old 6th December 2010, 19:04   #4
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,954
ho fatto il primo test ma dopo aver immesso il nome, il programma crasha
ma nella compilazione non da errori....

Code:
#include <stdio.h>
#include <stdlib.h>

int main() {
    char variabile;
    printf("Inserire il proprio nome: ");
    scanf("%s", &variabile);
    printf("Benvenuto Mr. %s, che ne direbbe di una bella partita a scacchi?", variabile);
    system("pause");
    return 0;
}
EDIT:
mentre scrivevo questo post mi sono accorto dell'errore....

il codice definitivo e funzionante è:
Spoiler:
Code:
#include <stdio.h>
#include <stdlib.h>

int main() {
    char variabile[4]; /*previsto per poi inserire solo "pippo" */
    printf("Inserire il proprio nome: ");
    scanf("%s", &variabile);
    printf("Benvenuto Mr. %s, che ne direbbe di una bella partita a scacchi?\n", variabile);
    system("pause");
    return 0;
}


comunque...
sono orbo io?
o non hai spiegato come dichiarare le variabili con stringhe? ma solo come memorizzare la stringa all'interno?
e a parte l'utilizzo di scanf...non hai detto come utilizzare la stringa con printf anche se ho notato è uguale allo scanf.

quindi...una breve spiegazione dell'utilizzo di %s %d etc? ^^
__________________
.: NoS - Nitrous Oxide System :.

Last edited by [En][gma]; 6th December 2010 at 19:06.
[En][gma] is offline   Reply With Quote
Old 6th December 2010, 19:06   #5
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,954
Quote:
Originally Posted by nanomad View Post
AHHHH!!!! AHHH!!!
Aresio cosa mi combini, introduci il carattere "terminatore di stringa \0" oppure questi poveri fanciulli combinano un casino

Addendum sulle stringhe:

in C una stringa è un array di caratteri

char stringa[13]

Come fa a sapere il nostro computer dove finisce una stringa? Semplice l'ultimo elemento della stringa è un '\0'. Ad esempio:
Code:
"ciao" = 'c' + 'i' + 'a' + 'o' + '\0'
così facendo possiamo usare un array molto grande (e.g. char superlungo[255]) per metterci dentro stringhe molto corte.
Quando facciamo la scanf con "%s" C aggiunge per noi il terminatore di stringa, ma dobbiamo comunque ricordarci di fare un'array abbastanza grande (lunghezza della stringa + 1)

Se non è chiaro ditelo
non è chiaro
il senso di fare quello che hai scritto? e quando farlo?

e se è necessario perché nell'esercizio appena fatto non si son creati problemi?
__________________
.: NoS - Nitrous Oxide System :.
[En][gma] is offline   Reply With Quote
Old 6th December 2010, 19:14   #6
nanomad
Dietro le sbarre
 
nanomad's Avatar
 
Join Date: Apr 2005
Location: Papia (olim Ticinum)
Posts: 5,221
Perchè hai avuto culo
Succede
Spoiler:

Facciamo due conti:
pippo è lungo 5 e già allochi 4 (char variabile[4]). Non tieni conto neanche del terminatore di stringa '\0'. La dichiarazione corretta dovrebbe essere
char variabile[6]
dove:
variabile[0] = p
variabile[1] = i
variabile[2] = p
variabile[3] = p
variabile[4] = o
variabile[5] = \0 <-- aggiunto da scanf

Perchè allora ti funziona? Perchè scanf non controlla quanto sia effettivamente lungo l'array che gli passi e quindi scrive "fuori dai margini".
La printf anche lei non sa quanto è lunga la stringa e quindi legge la memoria sequenzialmente a partire da variabile[0] fino a quando non incontra un '\0'
Ovviamente il compilatore non si lamenta perché a priori non sa quanto è lungo l'input della scanf

Prova a dichiarare un'altra cosa dopo variabile e vedi cosa succede
__________________
Rivuoi i video nel forum? Usa questa estensione (chrome)
Source & firefox version
"(...) the three great virtues of a programmer: laziness, impatience, and hubris." -- LarryWall

Last edited by nanomad; 6th December 2010 at 19:17.
nanomad is offline   Reply With Quote
Old 6th December 2010, 19:21   #7
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,954
perché char variabile[6] se poi compreso di terminatore occupi 5 spazi?
per "a scanso di equivoci"?

edit:
se al mio programma scrivo più di 5 caratteri al posto di terminare riparte da capo...e l'ha rifatto per 4 o 5 volte e poi è andato in crash xD
e.. il terminatore come si usa quindi?

edit2:
ah forse ho capito.
tengo l'ultimo byte libero così il sistema può allocare correttamente il \0 ?
__________________
.: NoS - Nitrous Oxide System :.

Last edited by [En][gma]; 6th December 2010 at 19:24.
[En][gma] is offline   Reply With Quote
Old 6th December 2010, 19:28   #8
nanomad
Dietro le sbarre
 
nanomad's Avatar
 
Join Date: Apr 2005
Location: Papia (olim Ticinum)
Posts: 5,221
P I P P O sono 5 caratteri, con il terminatore diventano 6.

Del terminatore non ti devi preoccupare piu' di tanto, diciamo che scanf lo inserisce in automatico e printf lo usa per leggere la fine della stringa.

Pero', mettiamo che tu faccia questo codice
Code:
 char variabile[6]; /*previsto per poi inserire solo "pippo" */
 printf("Inserire il proprio nome: ");
 scanf("%s", &variabile);
 variabile[5]='c';
 printf("Benvenuto Mr. %s, che ne direbbe di una bella partita a scacchi?\n", variabile);
 system("pause");
 return 0;
Quindi sostituendo il terminatore con un'altra roba....
Prova ed eseguirlo e guarda i risultati

Spoiler:

Come puoi vedere scanf non è una funzione "sicura" quando si tratta di stringhe. In questi casi la cosa migliore è usare altre funzioni come fgets:
[code]
char stringa[20]
int lunghezza = 20;
fgets(stringa,lunghezza,stdin);
[code]
stdin indica di leggere dalla tastiera e non va dichiarato, ci pensa il compilatore ad interpretarlo.
Così facendo la stringha viene troncata a (lunghezza-1) caratteri, anche se scrivi l'iliade come input del programma
__________________
Rivuoi i video nel forum? Usa questa estensione (chrome)
Source & firefox version
"(...) the three great virtues of a programmer: laziness, impatience, and hubris." -- LarryWall

Last edited by nanomad; 6th December 2010 at 19:35.
nanomad is offline   Reply With Quote
Old 6th December 2010, 19:30   #9
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,954
pippo son 5 caratteri ma essendo il primo il numero ZERO, 5 caratteri più terminatore fa 5! non 6!

come ho scritto sopra ho già fatto la prova...crasha il programma.

Comunque hai confermato quanto ho capito; basta tenere lo spazio in memoria libero e poi ci pensa in automatico scanf a metterci il carattere di termine.

EDIT:
comunque anche eseguendo il tuo o il mio e modificando l'ultimo carattere, a me non succede nulla....funziona tutto regolare.

EDIT2:
altra cosa appena venuta in mente
come fa il compilatore/software a sapere se all'istruzione frase[2] io voglio riferirmi alla seconda posizione e non al fatto che ne voglio avere disponibili 3?

quando la dichiaro lui automaticamente prende quel numero tra [] come "blocchi da rendere disponibili" e quindo lo uso insieme ad altre istruzioni lo prende come 'quella precisa posizione'?
__________________
.: NoS - Nitrous Oxide System :.

Last edited by [En][gma]; 6th December 2010 at 19:37.
[En][gma] is offline   Reply With Quote
Old 6th December 2010, 19:35   #10
Nemo
~~~~~
 
Nemo's Avatar
 
Join Date: Feb 1999
Location: /index.php
Posts: 19,723
Quote:
Originally Posted by [En][gma] View Post
pippo son 5 caratteri ma essendo il primo il numero ZERO, 5 caratteri più terminatore fa 5! non 6!


Se mangi 6 mele, ma la prima la chiami mela #0 non è che hai mangiato 5 mele eh
Nemo is offline   Reply With Quote
Old 6th December 2010, 19:37   #11
nanomad
Dietro le sbarre
 
nanomad's Avatar
 
Join Date: Apr 2005
Location: Papia (olim Ticinum)
Posts: 5,221
Eh, per i test a runtime come dicevo prima va a culo...
A me, con quel test, stampa
Salve signor pippc*/)SA cosa ne direbbe di una partita a scacchi?

A te probabilmente no perchè l'area di memoria che stai andando a toccare è piena di \0 (che poi non è altro che il carattere ASCII che viene salvato dal sistema con uno 0)

Per la questione della lunghezza, lo sapevo che ci sarebbe stato un casino quando aresio ha parlato di ZERO.

Facciamo chiarezza

se io scrivo:
int x[20]

sto dichiarando un array lungo 20 int. Per accedervi pero' devo usare i numeri da 0 a 19.
Quindi una stringa è lunga 5, indipendentemente se conto da 0 1 oppure 20
__________________
Rivuoi i video nel forum? Usa questa estensione (chrome)
Source & firefox version
"(...) the three great virtues of a programmer: laziness, impatience, and hubris." -- LarryWall

Last edited by nanomad; 6th December 2010 at 19:38.
nanomad is offline   Reply With Quote
Old 6th December 2010, 19:38   #12
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,954
si ma quando dichiaro la variabile e inzio a contare da 0...termino con 4 non con 5.

lo stesso nanomad ha scritto:
Quote:
variabile[0] = p
variabile[1] = i
variabile[2] = p
variabile[3] = p
variabile[4] = o
EDIT:
Quote:
sto dichiarando un array lungo 20 int. Per accedervi pero' devo usare i numeri da 0 a 19.
ah scusate ora è chiaro
__________________
.: NoS - Nitrous Oxide System :.

Last edited by [En][gma]; 6th December 2010 at 19:41.
[En][gma] is offline   Reply With Quote
Old 6th December 2010, 20:36   #13
Cece
- - - - - - - - - - - -
 
Cece's Avatar
 
Join Date: Apr 2002
Posts: 21,292
Quote:
Originally Posted by Arësius View Post


Quote:
float coordinata[2];


Saremo noi a stabilire che la coordinata 0 si riferisce alle X, la coordinata 1 alle Y e la coordinata 2 alle Z. Suona un po' macchinoso? Forse sì, per questo sono state introdotte...


Last edited by Cece; 6th December 2010 at 20:39.
Cece is offline   Reply With Quote
Old 6th December 2010, 20:44   #14
Cece
- - - - - - - - - - - -
 
Cece's Avatar
 
Join Date: Apr 2002
Posts: 21,292
ma quindi per fare un qualcosa di decente quando non si sa quanto grosso è l' input , e che non consumi molta memoria bisognerebbe fare una roba del genere ..

1-creare una variabile enorme
2- leggere l' input
3- usare qualche comando che legge la lunghezza reale della variabile inserita
4- creare variabile della giusta misura
5- riversare la variabile enorme su quella della giusta lunghezza
6- cancellare la variabile enorme

??

edit: anzi immagino esista qualche comando che si puo usare a fine inserimento , che crea la variabile giusta sul momento ..

edit2: googlando dovrebbe essere strlen .. e che mi sembra brutto avanzare nel corso a suon di google ..

Last edited by Cece; 6th December 2010 at 20:52.
Cece is offline   Reply With Quote
Old 6th December 2010, 20:46   #15
Valentin B.
Datemi un martello!
 
Valentin B.'s Avatar
 
Join Date: Dec 2010
Location: Leningrado
Posts: 52
Eh sì, benvenuto nel magico mondo della gestione della memoria

edit: ops, maledetto GDR su Agoro'
__________________
PV: 15/15 ~ FAME: 0/7 ~ INF: 0 ~ XP:50 ~ Nanomad

Last edited by Valentin B.; 6th December 2010 at 20:47.
Valentin B. is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 04:42.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright 1998-2014 by NGI SpA