Newsgroup: it.comp.lang.c
Titolo: EOF: quando finisce il programma? && [c-'0']

Ho comprato il libro che molti consigliavano in questo NG (di Kernigam
e Ritchie), ma di nuovo alcune cose non sono per me chiare, a partire
dagli esempi scritti sul libro.
A pag 19, si introducono i vettori.
Nel programma riportato sotto (trascrivo dal libro): quando termina il
programma in esecuzione?
Si parla di un EOF, ma io continuo ad immettere numeri, a mettere
anche -1 (che dovrebbe essere l'EOF), ma il programma continua ad
andare avanti.
Altra domanda, alla linea 16. Perchè ++ndigit [c-'0'] ? Non bastava 
++ndigit [c] (ok, se lo provo il programma si schianta però non
capisco la logica del sottrarre da c uno 0...) ?
Grazie per chiunque possa darmi una mano.
Nicola
#include <stdio.h>
//conta il numero fdi cifre, spazi bianchi e altri caratteri del testo
int main()
{
int c, i, nwhite,nother;
int ndigit[10];
//di seguito , si portano tutti le variabili contatore a zero,
comprese nell'array
nwhite=nother=0;
for (i=0;i<10;i++)
	ndigit[i]=0;
// inizia il conteggio
while((c=getchar()) !=EOF)
	if (c>='0' && c<='9')
		++ndigit [c-'0'];
	else if (c==' '|| c=='\n' || c=='\t')
		++nwhite;
	else
		++nother;
printf ("cifre = ");
for (i=0; i<10;++i)
	printf (" %d",ndigit[i]);
printf(", spazi bianchi= %d, altri= %d\n",nwhite, nother);
}

 capisco la logica del sottrarre da c uno 0...) ?
la spiegazione č poche righe piů sotto.
ciao.

 Grazie per chiunque possa darmi una mano.
Un semplice grazie bastava ed avanzava. Anche chi non ti risponde ha
perso tempo a leggersi il tuo post.
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 sul tuo sistema del carattere 0.
il valore numerico del mio sistema?
che vuol dire? 
Mi sento 'duro' assai, sembra una cosa cosi' ovvia, io non la capisco questo -0 .
Nicola


Spiegazione veloce: cerca "ASCII" su google.
Due parole in piu': ad ogni carattere, e' associato un numero (per 
renderla semplice...), la sua codifica. In C, i caratteri sono tipi 
numerici come gli int, i long, etc... - qual'e' il valore di un 
carattere? La sua codifica. Come faccio a trovare il suo valore? Lo 
standard non lo dice, perche' non fa assunzioni sulla codifica del 
sistema in cui ti trovi, giustamente. Pero', sul 99,99% dei computer in 
giro, e' ASCII.
Se qualcuno lassu' vuole, un giorno lavoreremo solo con Unicode e 
basta... ;-)
Anyway, sul mio K&R (la cui K e' KernigHaN, non Kernigam ;P), e' 
spiegato al paragrafo 1.5.3: "conteggio delle linee", poco prima 
dell'esempio che tu riporti. Leggiti questo libro con calma e facendo 
molti esercizi - e' parecchio denso, e come vedi e' facile perdere dei 
pezzi in giro! ;D
-- 
Mat/tia Belletti - Undergraduate student @ 
cs.unibo.it
ICQ: 33292311    - email: 
mbel...@cs.unibo.it
IRC: RedGlow     - site(s): 
http://mbellett.web.cs.unibo.it/
Jabber: RedGlow  - Linux registered user 299762 @ machine 213003

 
Questo lo sapevo, ma quelle righe non mi fanno capire. Senno non me ne
sarei venuto qui a 'rompere' al NG . :-)
Mi sa che mi manca qualche base sui caratteri Ascii o cose simili,
perchč il ragionamento del libro, in quel punto , rileggendolo piu
vole mi rimane incomprensibile.
Puoi per favore mettemi sulla buona strada, per capire quel c -'0' ?
Nicola

 Nicola
http://en.wikipedia.org/wiki/ASCII


 questo -0 .
Rileggi bene. Non c'è scritto:
   -0
C'è invece scritto:
   -'0'
Quei due "apostrofi" (o "apici singoli") non sono lì per bellezza. Il loro
significato è: "Caro compilatore, in questo punto mettimi il numero
corrispondente al codice ASCII del carattere che ho scritto in mezzo ai
due apostrofi".
E il codice ASCII(*) del carattere "cifra zero" è 48. Quindi, è come se tu
avessi scritto:
   -48
(* Pignoleria: ho scritto "codice ASCII" per semplificare: in realtà si
tratta del codice di quel carattere nella "codifica dell'ambiente di
esecuzione" del tuo programma. In pratica, comunque, nel caso specifico,
il carattere "cifra zero" ha il codice 48 in quasi tutte le codifiche
esistenti.)
--
Cingar
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 esistenti.)
Io ti ringrazio della tua pazienza nello spiegarmi, ma non ho capito
ugualmente.
Perche' per accedere e aumenarlo di un unita' non si puo scrivere
++ndigit [c];
?
perchè si deve aggiungere -'0', cioe un -49  (come mi hai spiegato) ?
Meccanicamente ho capito, quindi la prossima volta lo faro',
altrimenti il programma si piana, ma il ragionamento di base e la
logica non la comprendo.
E senza quella... altre volte mi sa che andro a "gambe a l'aria" nel
pensare un algoritmo.
Puoi pure dirmi che sono duro...ma ti prego di provare a spiegarmelo
in altra maniera.

 perchè si deve aggiungere -'0', cioe un -49  (come mi hai spiegato) ?
La tabella ASCII e' qualcosa che associa certi simboli grafici a certi
valori numerici. E parcchio usata e ti consigli di darci un'occhiata.
www.asciitable.com
Cio' premesso... Quando premi il tasto con il 9 sopra non stai
inserendo il valore numerico 9, ma stai inviando un cosiddetto
"scan code", che non ho la piu' pallida idea di quanto valga, ma
comunque NON ha nessuna attinenza con con il simbolo che e' stampato
sopra il tasto che genera un certo scan code.
Quando il sistema riceve lo scan code, va a cercare in una tabella
(char set utilizzato dal sistema) quale codice numerico corrisponde
a quello scan code e lo restituisce alla getchar().
Ringraziando il Padreterno, il simbolismo utilizzato per i numeri e'
lo stesso in buona parte del pianeta (tranne nei paesi di lingua araba
dove giustamente utilizzano le cifre arabe, che ironia della sorte non
sono equivalenti a quelle che noi chiamiamo cifre arabe).
http://web.unife.it/altro/tesi/A.Montanari/arabo.htm
Nei char set utilizzati normalmente, il valore numerico associato
agli scan codes corrispondenti ai tasti con simboli numerici (e anche
per una buona parte dei simboli alfabetici) e' quello della tabella
ascii a 127 caratteri.
Pertanto premendo il tasto con lo zero sulla tastiera, la getchar()
restituira' il valore numerico 48 che e' il valore decimale che
assume nella tabella ASCII il simbolo grafico 0.
Incredibile, ma vero, premendo il tasto con il 9 sopra la getchar()
restituira' 57 e cosi' via per tutti gli altri simboli.
Nel programma viene allocato un array di 10 elementi mer memorizzare
quante volte e' stato premuto un tasto numerico, per accedere all'array
viene utilizzato un indice dato da c - '0' (ovvero dal valore ASCII
del carattere premuto meno il valore ASCII del carattere 0) se sottrai
al valore ASCII del carattere 9 il valore ASCII del carattere zero
ottieni il valore numerico 9.
Pertanto il conenuto dell'elemento 9 dell'array sara' il numero di
volte che e' stato premuto il tasto 9.
Spero di essere stato chiaro, ma ci credo poco.
HTH



c - '0' significa che al valore contenuto nella variabile c ci sottraggo 
  il valore '0', che non e' 0, ma un certo numero intero (ossia e' una 
codifica ASCII).
Infatti, nel linguaggio C, la gestione dei caratteri (char) e la 
gestione degli interi si "interseca".
Quindi non farti ingannare da '0', non e' l'intero 0, ma il carattere 
ASCII '0', che ha valore (int) 48.
Quello che fa il programmino e' contare il numero di digit, di caratteri 
   di spaziatura (tab, spazio bianco, return) e tutti gli altri 
caratteri, ma questo credo ti fosse chiaro :-)
Ciao


Forse ho capito cosa stai chiedendo.
La questione e' che se inizializzi un array di dieci elementi, quindi da 
indice 0 a indice 9, poi non puoi andare a inserire i valori dall'indice 
48 all'indice 57, che e' quello che andresti a fare con le righe:
while((c=getchar()) !=EOF)
	if (c>='0' && c<='9')
		++ndigit [c];
...
Infatti, c vale da 48 a 57, a seconda del particolare digit, quindi 
faresti un assegnamento ndigit[48] = ndigit[48] +1 , in che puo' non 
piacere al compilatore in quanto non hai allocato memoria a sufficienza.
Ciao


Anzi, non e' neanche vero che si incacchia su linux, semplicemente ti 
restituisce  tutti 0 nel conteggio dei digit , ma attenzione perche' vai 
su memoria non allocata, quindi potenzialmente usata da altr variabile 
del tuo programma.
Su Windows Xp si incacchia e da' un'exception molto dettagliata.
ciao

 ciao
Il fatto che un programma scoppi a causa di un accesso sbagliato
alla memoria, non dipende dal S.O. ma dalle aree di memoria che
il codice errato e' andato a modificare. E questo dipende molto
da come il compilatore ha organizzato quel particolare codice.
Anche su XP e' possibile avere del codice che non crasha
nonostante si sia sforato i limiti di un array.


Angelo e poi anche Paolo (sotto), grazie. Finalmente ho capito.
Ma credetemi, non è per nulla scontato capire il ragionamento, quiando
uno è alle prime armi (e non sono comunque alle prime armi
informatiche.. in PHP smanetto un po).
Ciao grazie.
Nicola


Quind, il programma eseguibile va a pescare in un'area di memoria che, 
nel caso di Xp, provoca un errore, ma non perche' Xp ma perche' ho usato 
un compilatore diverso (Bcc 5.5).
Ma questo errore come viene gestito? Il programma rimane "congelato", mi 
appare la finestra di debug che mi mostra l'Exception ecc., poi do' un 
paio di ok (anche tre) e il programma vedo che termina. Non e' il SO che 
si occupa di cio'?
Ciao

 si occupa di cio'?
E' sempre il S.O. che, alla fine di tutto, interviene per terminare
il programma che si comporta in maniera scorretta, ma e' sempre bene
tenere a mente che l'intervento del S.O., nel caso di accessi scorretti
alla memoria, non e' ne' certo ne' automatico.
Spero di essere stato chiaro.
