Domanda Dubbi su semplice programma C

Stato
Discussione chiusa ad ulteriori risposte.

Soul_code

Utente Silver
11 Marzo 2016
200
15
4
77
Studio da poco il linguaggio C seguendo il libro di Kernighan & Ritchie
Vi posto un programma e vi espongo i miei dubbi :)

C:
#include <stdio.h>

main(){
    double num_car = 0;
    int c = 0;

    while(c != EOF){
        c = getchar();
        ++num_car;
    }

    printf("%1.0f", num_car);
}
Il programma conta il numero di caratteri che l utente inserisce da tastiera.
Avvio il programma, digito
"casa" (senza gli apicali)
premo invio
e il programma stampa il numero 6
Prima domanda:
Perchè 6? 4 per le lettere di c-a-s-a, 1 per il ritorno a capo dell invio ,quindi, non dovrebbe stampare 5?
o forse il ritorno a capo conta come 2 caratteri e quindi 4+2 =6?
Seconda domanda:
Se digito "casa" e termino il programma (stavolta senza premere invio) il programma stampa 1.
Se stampa 1 significa che num_car è 1, e quindi significa che entra nel ciclo while esattamente una volta.
Perchè (se non premo invio) entra nel ciclo while una volta sola?
 
Studio da poco il linguaggio C seguendo il libro di Kernighan & Ritchie
Vi posto un programma e vi espongo i miei dubbi :)

C:
#include <stdio.h>

main(){
    double num_car = 0;
    int c = 0;

    while(c != EOF){
        c = getchar();
        ++num_car;
    }

    printf("%1.0f", num_car);
}
Il programma conta il numero di caratteri che l utente inserisce da tastiera.
Avvio il programma, digito
"casa" (senza gli apicali)
premo invio
e il programma stampa il numero 6
Prima domanda:
Perchè 6? 4 per le lettere di c-a-s-a, 1 per il ritorno a capo dell invio ,quindi, non dovrebbe stampare 5?
o forse il ritorno a capo conta come 2 caratteri e quindi 4+2 =6?
Seconda domanda:
Se digito "casa" e termino il programma (stavolta senza premere invio) il programma stampa 1.
Se stampa 1 significa che num_car è 1, e quindi significa che entra nel ciclo while esattamente una volta.
Perchè (se non premo invio) entra nel ciclo while una volta sola?
Prima di tutto non dovresti dichiarare double il numero di caratteri in quanto saranno interi sicuramente, seconda cosa l'incremento del num_car va fatto posticipatamente quindi num_car++. Il fatto che incrementi nel modo ++num_car ti determina l'errore di contarne uno in più. Ricorda di cambiare anche la printf per prendere un intero.
 
Prima di tutto non dovresti dichiarare double il numero di caratteri in quanto saranno interi sicuramente, seconda cosa l'incremento del num_car va fatto posticipatamente quindi num_car++. Il fatto che incrementi nel modo ++num_car ti determina l'errore di contarne uno in più. Ricorda di cambiare anche la printf per prendere un intero.

L ho dichiarato double per avere un range maggiori di numeri disponibili :)
e non fa differenza se uso il post-increment xD non centra in quello spezzone di codice, se l istruzione è singola non vi sono differenze :)
quindi restano ancora entrambe le domande xD ma grazie cmq per la risposta!
 
Con double hai solo la virgola in più e 4 bytes di memoria sprecati comunque l'input come lo dai? Esempio : "c" invio "a" invio "s" invio "a" invio oppure scrivi direttamente "casa" e premi invio?
 
Con double hai solo la virgola in più e 4 bytes di memoria sprecati comunque l'input come lo dai? Esempio : "c" invio "a" invio "s" invio "a" invio oppure scrivi direttamente "casa" e premi invio?
mi risulta che con double è possibile memorizzare numeri più grandi, al di là della virgola :)
Allora:
se digito: casa e poi invio e poi termino il programma, mi conta 6 caratteri (cioè uno in piu di quanti me ne aspetto)
se digito casa e termino il programma (senza premere invio) mi conta 1 carattere, come se entra una volta sola nel ciclo.
 
Ultima modifica:
mi risulta che con double è possibile memorizzare numeri più grandi, al di là della virgola :)
Allora:
se digito: casa e poi invio e poi termino il programma, mi conta 6 caratteri (cioè uno in piu di quanti me ne aspetto)
se digito casa e termino il programma (senza premere invio) mi conta 1 carattere, come se entra una volta sola nel ciclo.
Hai ragione che un double contiene di pù ma dubito che ne hai bisogno in quanto un int arriva fino a 32767 e penso che ti basti. Ti posto il codice commentato:
C:
#include <stdio.h>
//Per terminare e vedere l'output dopo aver digitato "casa" sulla stessa riga premi Ctrl-D
int main(){
  int n = 0;
  while(getchar() != EOF){ //Fai controllare direttamente alla guardia del while se ha finito o meno.Risparmi una                                              //variabile e tante operazioni costanti.
       n++;  //Ti consiglio di incrementare sempre con il metodo post per evitare problemi in futuri codici.
  }
  printf("%d",n-1); //n-1 perché conta anche l'ultimo carattere che sarebbe nullo se premi "invio" e poi Ctrl-D
                                  // altrimenti basta n.
return 0;
}
Spero di esserti stato abbastanza d'aiuto!
 
  • Mi piace
Reazioni: Soul_code
Ultima modifica:
Tralasciando il discorso post/pre-increment che in questo caso non fa alcuna differenza.
Semplicemente devi prima verificare che il carattere letto non sia un '\n' o un EOF prima di incrementare. Quindi :
C:
while((c = getchar()) != '\n')
    ++n;
Il buffer stdin una volta che hai inserito "casa" diventa
c a s a '\n' EOF
è chiaro quindi che incrementi il numero delle lettere anche quando getchar ritorna il '\n' o EOF.
PS. Un int ha come range +-2 miliardi circa. Ti consiglio un unsigned int dato che non avrai mai numeri negativi.
 
  • Mi piace
Reazioni: Soul_code
Grazie a tutti , molto gentili :)

p.s. Anche io preferisco il post increment, ho iniziato adesso col C ma sono un "esperto" di Java..
sto usando il pre increment in quanto sto seguendo un libro e lì in quest esempio usa il pre increment :) cmq grazie raga!
 
Se num_car lo usi come un contatore come in questo caso allora devi dichiaralo come "insignened int" per sua definizione. La variabile "c" nel ciclo while è una variabile string quindi devi dichiararla come "char". Sostituisci EOF con "\n" e sostituisci "++num_car" con "num_car++". Se dichiari come ho fatto io allora nel printf devi mettere " %u "


Inviato dal mio iPhone utilizzando Tapatalk
 
Se num_car lo usi come un contatore come in questo caso allora devi dichiaralo come "insignened int" per sua definizione. La variabile "c" nel ciclo while è una variabile string quindi devi dichiararla come "char". Sostituisci EOF con "\n" e sostituisci "++num_car" con "num_car++". Se dichiari come ho fatto io allora nel printf devi mettere " %u "

Grazie :) più avanti nel libro mi parlare del unisgned int, questo programma è solo uno dei primi esempi :)
Pero grazie :)
 
Stato
Discussione chiusa ad ulteriori risposte.