Newsgroup: it.comp.lang.c
Titolo: isdigit()

Per fare il controllo su ciň che viene inserito dall' utente mi avete
consigliato(in un altro topic)  di utilizzare isdigit(), ma non mi funziona
:-(
io faccio:
printf("Inserisci qualcosa\n\n");
scanf("%d", &s);
if(isdigit(s) == 0) exit(0);
ma non ho capito perchč non mi funziona.
mi fa uscire dal programma anche se inserisco degli interi.
cosa č che sbaglio?
grazie per l' eventuale suggerimento... ciao
--
______________________________
I Programmatori non si arrendono MAI
----------------------------------------

La funzione ritorna un valore non sempre uguale, dipende dall'ambiente e
sistema in cui programmi...
// su win il valore di ritorno della funz dipende dal sistema locale
anzicchč scrivere: if (isdigit(s) == 0) // su *nix dovrebbe funzionare
prova if (isdigit(s) != true) oppure if ( ! isdigit(s) )
perchč in caso di successo, viene restituito un valore diverso da 0.
--------------------------------
Inviato via 
http://usenet.libero.it

 [snip]
Non funziona perche' una cosa e' una cifra numerica e un'altra e' la sua
rappresentazioe tramite un carattere ASCII. 1 e' la cifra 1, mentre '1' e'
il carattere 1 = 0x31 o se preferisci 49 in decimale. Per farlo funzionare
leva la scanf e metti:
s = getchar();
Supponendo che s sia definito come int (s = (unsigned char)getchar() se
invece s e' un unsigned char).
Luca

 cosa č che sbaglio?
di che tipo e' la variabile s ??
guardando la scanf che hai scritto s si direbbe un intero.
La isdigit la devi invocare su un char, letto con la scanf.
Se nella scanf metti "%d" la forzi gia' a leggere un intero
e non puoi fare poi il test autonomamente.
g.

 oppure if ( ! isdigit(s) )
Questa e' la soluzione giusta.

 ha scritto nel messaggio
news:bhvhln$arg$1...@galileo.it.ip-plus.net...

Sto provando di tutte le maniere ma niente...
1) la variabile la dichiaro int o char?
2) come specificatore di formato devo mettere %d o %c?
3) mi potete fare un esempio?
-----------------------------------------------------
grazie ;-)

 perch? in caso di successo, viene restituito un valore diverso da 0.
Appunto. Quindi la prima e la seconda forma fanno la stessa cosa.
Kronos
-- 
Home: 
http://kronoz.cjb.net
You and me baby ain't nothin' but mammals
So let's do it like they do on the Discovery Channel

 E true che cos'è? Ad esempio in C89 non esiste, ma solo in C99.
Beh dipende dall'implementazione...se usi Visual C++ o BorlandC++Builder
ecc.. esiste.
Dipende sempre dal compilatore che usi e ho specificato tutti i casi
possibili.


 Questo e` sbagliato. true/false si possono usare solo per il tipo bool,
Ma che dici?!? sai che in C false č 0 e true č tutto ciň che č diverso da
false?!?
All'occorrenza vengono convertiti i valori.
Qui non si mischiano bool con valori interi; isdigit restituisce un
risultato della funzione e viene uguagliato nel test con un valore piů che
lecito.


 > > prova if (isdigit(s) != true)
ma il test deve essere fatto con FALSE, se definito dall'utente come 0, o
false se definito nell'ambiente.


L'errore è nella dichiarazione della variabile che deve essere di tipo char
e non di tipo intero.


Allora:
isdigit() e tutte le altre funzioni prendono e restituiscono interi come
parametri/ritorno, questo per supportare anche i caratteri estesi che non
entrano in un char anche se definito unsigned. Le variabili che ospitano il
risultato possono essere sia di tipo char che int, naturalmente con un char
si può rischiare un buffer overflow...
Il test di confronto può essere fatto con lo 0 (zero) per controllare il
valore della funzione:
if (isdigit(car) != 0) // car è un numero!
o, se supportato il tipo bool, il seguente è identico al precedente:
if (isdigit(car) != false) // car è un numero!
Questo perchè i tipi bool vengono convertiti se necessario in numeri interi
(C++ standard ISO 1998)
Con scanf, se si usa "%c" con una var dichiarata come char, tutto funziona
bene; ma se si usa un "%d" con una var dichiarata come int o char, la
isdigit non funziona.
E' un problema solo della scanf perchè con una var dichiarata int e getchar,
tutto funziona bene!
Ciao


 grazie ;-)
#include <stdio.h>
#include <ctype.h>
int main(void)
{
    int c;
    printf("Inserisci un caratere\n");
    c = getchar();
    if(isdigit(c) != 0)
        printf("Cifra numerica\n");
    else
        printf("Altro carattere\n");
}
Luca

 possibili.
Ma qui in generale non si dovrebbe parlare di implementazioni 
specifiche. E comunque il valore di ritorno di isdigit() e' int e non 
_Bool (o bool che dir si voglia).

 lecito.
E' si' sbagliato, in quanto mentre e' vero che 0 e' falso e qualsiasi 
altra cosa vero, il valore true rappresenta solo 1. Se isdigit() 
ritornasse ad esempio 2 (cosa ammessa dallo dallo standard, in quanto si 
parla di zero e non-zero come possibili risultati), sarebbe true ad 
essere promosso ad 1 (e non il 2 a true) e il test risulterebbe falso in 
quanto 2 != 1.

 tutto funziona bene!
Esatto.


Scusa volevo dire overflow!


 E secondo te non è considerato un carattere esteso?!?
No, perche' non e' un carattere ma un valore di ritorno che appunto non 
rientra nel range rappresentabile con un (unsigned) char, essendo un 
valore int negativo.
O almeno, questa e' la mia interpretazione dello standard. Naturalmente 
posso sbagliarmi. In ogni caso gli unici caratteri estesi di cui parla 
lo standard sono quelli di tipo wchar_t, sui quali non sono applicabili 
le funzioni dichiarate in <ctype.h>

 Scusa volevo dire overflow!
Una riflessione: perche' dovresti correre il rischio di avere un 
overflow? Se isdigit() ritorna int, usa una variabile int per contenere 
il risultato, no?
Inoltre non sono sicuro su un fatto. Faccio un esempio.
int a = 12345;
char b = a;
Questo codice puo' generare overflow? So che si puo' generare in questo 
caso:
int a = INT_MAX;
a++;
...ovvero come risultato di un'operazione aritmetica. Questo vale anche 
in caso di un assegnamento?


No l'esempio era rivolto al fatto che puoi utilizzare anche il char oltre
che l'int.
se il char unsigned ha un range da 0 a 255, inserendo un valore come 300, ti
viene convertito in 3; è come l'esempio che hai fatto sull'int assegnato al
massimo valore e poi incrementato.



il wchar_t è per rappresentare i caratteri a più byte per il supporto di più
lingue...
l'EOF non è solo un valore di ritorno, è rappresentabile con la combinazione
CTRL+D che appunto è EOF ed è un carattere esteso!


 massimo valore e poi incrementato.
Non capisco a quale char ti riferisci. Intendo, in che contesto usi 
questa variabile di tipo char con la funzione isdigit()?

 CTRL+D che appunto č EOF ed č un carattere esteso!
Potresti dirmi da che fonte ricavi questa affermazione? Io non riesco a 
trovarla (ad esempio nell'ultima bozza dello standard C99)...
Il mio discorso e': ok, ottengo EOF premendo determinati tasti (CTRL-D 
sotto Unix ad esempio) se leggo lo stdin. Pero' ottengo EOF anche 
leggendo da un file diverso da stdin. Questo a mio parere implica che 
EOF non e' un carattere, poiche' in un file binario ci possono essere 
tutte e 256 le combinazioni (ipotizzando un char di 8 bit) e nessuna di 
esse puo' rappresentare EOF (altrimenti il file sembrerebbe finire prima 
del dovuto). Quindi non ottengo EOF leggendo un certo valore, ma 
raggiungendo la fine del file. Questa e' segnalata ad esempio da CTRL-D 
per lo stdin, e in un altro modo dipendente dal sistema per quanto 
riguarda ad esempio i file su disco.


GIUSTO: CTRL+D è un carattere esteso che non entra in un char unsigned...è
standard per lo stdin, per i file ecc...
Almeno io l'ho usato sia sotto win che linux allo stesso modo...


L'assegnamento di una variabile tipo:
a = 345;
viene eseguita sia se tu scrivi esplicitamente l'istruzione, sia se
rappresenta la restituzione di una funzione, sia se lo passi come parametro:
Per intenderci:
unsigned char prova(unsigned char par);
1) se richiami la funzione prova(456), automaticamente il 465 viene
convertito in uchar (a parte che il compilatore dovrebbe darti un warning
per un cast di perdita).
2) Stesso per il ritorno: se nel corpo della funzione prova effettui un
return(500), si verifica la situazione del primo caso.
3) a = 345; uguale al 1 e al 2


 test con un valore piu` che lecito.
isdigit  restituisce un  int,  non  un bool. Mischiare  i  due tipi,  lo
ripeto, e` sbagliato.
Kronos
-- 
Home: 
http://kronoz.cjb.net
Ci sono due cose che l'uomo non puo` nascondere:
essere ubriaco ed essere innamorato.

 Kronos
Secondo lo Standard C++ ISO del 1998, un bool viene convertito in un intero
se necessario.Qui è necessario, certo non lo si deve fare con true, ma con
false si...
if (isdigit(c) != false) // perfettamente funzionante


 se necessario.
E' piu' appropriato citare lo standard C99, che dice la stessa cosa.

 ha
scritto:

;-)


 Questo codice puo' generare overflow?
Ho avuto una risposta molto esauriente su comp.lang.c. Riporto un 
frammento dall'ultima bozza pubblica dello standard C99:
     6.3.1.3 Signed and unsigned integers
     1 When a value with integer type is converted to another integer
       type other than _Bool, if the value can be represented by the new
       type, it is unchanged.
     2 Otherwise, if the new type is unsigned, the value is converted by
       repeatedly adding or subtracting one more than the maximum value
       that can be represented in the new type until the value is in the
       range of the new type.
     3 Otherwise, the new type is signed and the value cannot be
       represented in it; the result is implementation-defined.
Quindi, nel mio esempio, a b viene assegnato un valore definito 
dall'implementazione, quindi il programma sarebbe portabile. Inoltre, 
non si tratta di overflow.

 dall'implementazione, quindi il programma sarebbe portabile.
Ovviamente intendevo dire che *non* sarebbe portabile.

 ha
scritto:

Non solo, ma anche sballato.
Overflow è inteso come superamento della capacità; essendo un signed char da
-128 a 127, un valore come 128 causa un rientro del tipo.


 essendo un signed char da -128 a 127, un valore come 128
 > causa un rientro del tipo.
No, lo standard garantisce solo da -127 (non -128) a 127.

 ha scritto nel messaggio
news:3F4552E3...@lombardiacom.it...

scusa e la base 2 dove sene va ???
non sarebbe uno in piu' negativo della parte positiva ???
ciao


Probabilmente questo e' stato deciso per supportare anche le vecchie 
macchine che usano aritmetica binaria in complemento a 1, invece che in 
complemento a 2 come le architetture piu' moderne.
In complemento a 1, con 8 bit si possono rappresentare solo i valori tra 
-127 e 127, con un piccolo spreco in quanto due combinazioni di bit 
distinte rappresentano entrambe lo zero.
In complemento a 2, con 8 bit si va da -128 a 127. Questa e' la regola, 
al giorno d'oggi.
Ma per compatibilita', lo standard dice: si va da -127 a 127 come range 
minimo.

Non sò di questo che dici tu...
cmq in passato ho letto e continuo a leggere sui libri di C/C++ che i range
vanno da -128 a 127 ecc... altro non sò!
Se apri l'header limits.h, avrai la conferma di quanto detto!
Se fosse come dici tu, limits.h avrebbe il range -127 a 127 e non è così!


 Se fosse come dici tu, limits.h avrebbe il range -127 a 127 e non č cosě!
Non sono io a dirlo, e' lo standard.
Questo stabilisce il range *minimo*, che e' [-127,127], poi le 
implementazioni possono ampliarlo. L'header <limits.h> fornisce i limiti 
definiti dall'implementazione, non dallo standard.
Se il tuo libro dice [-128,127], allora e' sbagliato. Sia il K&R che il 
Deitel&Deitel che io possiedo riportano (correttamente) [-127,127].

Mi sa che sono i tuoi libri a sbagliarsi o a far riferimento a C
pre-standard...
Ho controllato su Addison-Wesley "Didattica e programmazione C" dove viene
trattato solo l'ANSI C del 1990, e fa chiaramente riferimento a signed char
come da -128 a 127.
E' giusto perche' altrimenti tutte le implementazioni dei compilatori, dai
vecchi ai nuovi, non sarebbero standard, visto che in limits.h viene
definito -128,127 contro il presunto standard -127,127!!


 definito -128,127 contro il presunto standard -127,127!!
Lo standard richiede un range *minimo* ai valori del signed char. 
L'implementazione e' libera di estenderlo a piacimento, basta che lo 
documentino appunto in <limits.h>. Ripeto, in questo header ci stanno i 
limiti *dell'implementazione*, non quelli dello standard. [-128,127] e' 
perfettamente accettabile. Su una macchina diciamo 'moderna', con 
aritmetica in complemento a 2, questa e' l'ovvia scelta.
Questo pero' non significa che lo standard garantisca questo range in 
*qualsiasi* implementazione. Di garantito, c'e' solo [-127,127].
Questo range minimo e' adottato anche dal nuovo C99. Cito una bozza 
pubblica dello standard (che puoi trovare presso 
http://anubis.dkuug.dk/JTC1/SC22/WG14/www/docs/n869/
):
     5.2.4.2.1 Sizes of integer types <limits.h>
   1 The values given below shall be replaced by constant expressions
     suitable for use in #if preprocessing directives. Moreover, except
     for CHAR_BIT and MB_LEN_MAX, the following shall be replaced by
     expressions that have the same type as would an expression that is
     an object of the corresponding type converted according to the
     integer promotions. Their implementation-defined values shall be
     equal or greater in magnitude (absolute value) to those shown, with
     the same sign.
     — number of bits for smallest object that is not a bit-field (byte)
       CHAR_BIT        8
     — minimum value for an object of type signed char
       SCHAR_MIN    -127
     — maximum value for an object of type signed char
       SCHAR_MAX    +127
La bozza e' affidabile da questo punto di vista, in quanto successiva 
allo standard ANSI C definitivo.

 se necessario.
Lo Standard  dice che un bool  puo` diventare 1 oppure  0. Ti ripeto che
bool non va mischiato con gli altri tipi scalari nei confronti.
if ((bool)isdigit(car) == true)
Funziona perfettamente  ed e` corretto. Il  tuo esempio funziona,  ma e`
sbagliato dal  punto di  vista concettuale, come  un confronto  tra tipi
signed e unsigned.
Kronos
-- 
Home: 
http://kronoz.cjb.net
"Chi parla in tono cortese, ma continua a prepararsi, potra` andare avanti;
 chi parla in tono bellicoso e avanza rapidamente dovra` ritirarsi" 
Sun Tzu -- L'arte della guerra

 definito -128,127 contro il presunto standard -127,127!!
Ma  leggi  quello che  ti  viene  scritto?  limits.h contiene  i  valore
dell'implementazione, non  i valori (minimi) forniti  dallo Standard. Lo
Standard *dice* che i signed  char hanno come range *minimo* [-127,127],
la  tua  implementazione  potrebbe fornire  [-100000,100000]  e  sarebbe
perfettamente accettabile.
Kronos
-- 
Home: 
http://kronoz.cjb.net
"In linea di principio sarei indifferente al natale, se solo il natale
 ricambiasse la cortesia e mi lasciasse in pace." -- Marco d'Itri

Ok per me non ci sono problemi...
dimmi solo na cosa:
se i valori dello standard sono -127,127 e tutte le implementazioni
riportano -128,127...che standard è?
Dalle mie parti lo standard serve per migliorare la portabilità del codice
su diverse piattaforme, allora tuti i compilatori non sono standard?!
Mi sembra una grande cazzata e comunque moderati con i termini perchè non
sei mio fratello.


 signed e unsigned.
Funziona ed è corretto, ma concettualmente è sbagliato?!?
Hai un'pò di confusione...
Secondo te è sbagliato concettualmente che gli enumerativi vengono trattati
come interi?!?
Eppure lo si fà!


 su diverse piattaforme
Anche dalle mie di parti. Se infatti rispetti il range [-127,127] il tuo 
codice funzionera' ovunque ci sia un compilatore ANSI C, persino su una 
macchina con char di 8 bit e aritmetica in complemento a uno.
 > allora tuti i compilatori non sono standard?!
No, perche' come gia' ho detto due volte, e come puoi leggere nello 
standard, in <limits.h> ci stanno i limiti dell'implementazione.

 Hai un'p? di confusione...
Tra le due  frasi c'e` un punto. La  prima e` riferita al  codice che ho
scritto. La seconda ha come soggetto "il tuo esempio". L'italiano non e`
un opinione.
E adesso fila nel killfile.
Kronos
-- 
Home: 
http://kronoz.cjb.net
Dicono che  il cane sia  il miglior  amico dell'uomo. Secondo me  non e`
vero. Quanti dei vostri amici avete fatto castrare, recentemente?

 su diverse piattaforme, allora tuti i compilatori non sono standard?!
???? Se bastasse lo standard per rendere portabile il codice...
Hai mai sentito parlare di endianess? Puoi scrivere codice
perfettamente standard (secondo la _*tua*_ visone del termine) che
funziona su un processore Intel e non ne vuole sapere su un processore
Motorola (o viceversa).... E non ci vuole nemmeno troppa fantasia.
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Allora stai affermando che i bool non vanno mischiati con gli int, ad
esempio, nei test di condizione...
Lasciati dire una cosa:
Se fai questa affermazione, non hai capito nulla della programmazione!
Se scrivi
--> if (!isdigit(car))
secondo te il compilatore cosa fa?!?
Te lo spiego io...
Supponendo che car è un numero, isdigit restituisce un non zero, ad esempio
2048, a questo punto avremo:
--> if (!2048)
il 2048 essendo diverso da zero, diventerà true ed avremo:
--> if (!true)
a questo punto la negazione unaria trasforma il valore in false.
Se scrivo if(isdigit(car) == false)
E' LO STESSO, ma in quest ultimo caso è ESPLICITO.
è questo vale per tutti i test di condizione, restituiscono sempre un valore
bool!
Adesso vai tu nel killfile.


 ha
scritto:

Okkey non ti arrabbiare!
Allora dovrò inviare email a tutti gli editori che hanno scritto, parlando
di ANSI C, che un char ha un range di -128,127!!
Detto, fatto.
P.S. Stai parlando comunque di architettura completamente diverse ed è
normale che cambiano molte cose nell'implementazione dei compilatori, visto
che cambiano i componenti e il modo di fnzionamento!


Lascia che ti spieghi quando è concettualmente sbagliato o corretto
mischiare bool con int:
1) USO SPECIFICO DEL VALORE INTERO:
E' corretto quando i test avvengono con variabili int che hanno un peso nel
programma, cioè il cui valore ha importanza nel codice:
int indiceArray = 4;
QUI è corretto non mischiare i valori:
if (indiceArray == 0) // è molto più naturale di == false!
   printf("Il primo indice è riservato!");
// ok: altre operazioni con indiceArray
Non e' corretto quando il valore intero non ha peso nel codice, cioè quando
serve solo a testare un valore di sucesso o insuccesso:
if (isdigit(car) == false) ' da l'idea dell'errore più di == 0
Qualsiasi funzione restituisce un valore che indica se è andata a buon fine
o altrimenti. Affinità naturale e logica con bool!
2) LEGGIBILITA':
Moltissime funzioni vecchie del linguaggio C (socket per esempio)
restituiscono 0 per indicare successo, quale sarebbe più chiaro da leggere:
if (isdigit(car) == 0) ' indica se vi e' un ERRORE....
if (connect(sock, ...) == 0) ' indica se c'e' SUCCESSO...
oppure
if (isdigit(car) == false) ' il false chiarisce il test di err
if (connect(sock, ...) == 0) ' indica se vi è succeso...
Indubbiamente il secondo caso...
è giusto lasciare che il test della connect sia con zero, ma solo perchè è
cosi' stata definita la funzione!
Nota: guarda caso lo zero come valore di successo non viene piu'
implementato in nessuna funzione proprio per la confusione che si può creare
con i vari standard (C99, C++ ISO 1998).
Fine della discussione e del post
