2015-10-23 14 views
6

Sto studiando il libro K & R. Attualmente sto leggendo la funzione getop() a p.78. Capisco il codice ma ho bisogno di chiarimenti su 2 cose.getop(), funzione K & R book p 78

Il codice di getop() è il seguente:

int getch(void); 
void ungetch(int); 

/* getop: get next character or numeric operand */ 
int getop(char s[]) 
{ 
    int i, c; 
    while ((s[0] = c = getch()) == ' ' || c == '\t') 
     ; 
    s[1] = '\0'; 

    if (!isdigit(c) && c != '.') 
     return c; /* not a number */ 

    i = 0; 
    if (isdigit(c)) /* collect integer part */ 
     while (isdigit(s[++i] = c = getch())) 
      ; 
    if (c == '.') /* collect fraction part */ 
     while (isdigit(s[++i] = c = getch())) 
      ; 
    s[i] = '\0'; 

    if (c != EOF) 
     ungetch(c); 

    return NUMBER; 
} 

mia domanda riguarda: s[0] in:

while ((s[0] = c = getch()) == ' ' || c == '\t') 

L'idea alla base del ciclo while è saltare spazi e tab orizzontale, quindi perché stiamo salvando 'c' in s [0]? Perché gli autori non hanno semplicemente scrivere:

while (c= getch() == ' ' || c == '\t') 

Non abbiamo intenzione di utilizzare gli spazi e le schede più tardi, perché abbiamo bisogno di salvare c in s[0] per? Qual è la necessità di s[0] qui?

La mia seconda domanda riguarda:

s[1] = '\0'; 

perché stiamo assegnando lo '\ 0' (fine della stringa) per s[1] qui?

Ho letto alcune delle risposte precedenti pubblicate su stackoverflow.com a riguardo ma non ne sono totalmente convinto!

La risposta accettata sulla domanda precedente è: "Perché la funzione potrebbe tornare prima che l'input rimanente venga letto, e quindi s deve essere una stringa completa (e terminata)."

Ok. Ma cosa succede se l'input ha uno spazio bianco all'inizio e seguito da un operando o operatore? In questo caso, s[1] = '\0' chiuderà la stringa troppo presto? non è vero?

risposta

5

In risposta alla tua prima domanda, l'assegnazione a s[0] in questo caso è una comoda scorciatoia di codifica. Il valore di c viene copiato in s[0] per ogni carattere letto da getch(), indipendentemente dal fatto che verrà utilizzato o scartato. Se deve essere scartato, nessun grosso problema; verrà sovrascritto alla successiva iterazione del ciclo while(). Se deve essere utilizzato, è già stato copiato nella posizione necessaria nell'array di destinazione s[].

In risposta alla tua seconda domanda,

Ma cosa succede se l'ingresso ha uno spazio bianco all'inizio e seguito da un operando o un operatore?

Si noti che il precedente ciclo while() impedisce caratteri di spazio bianco (spazi e tabulazioni) di apparire nella s[0] dopo l'uscita dal ciclo. Pertanto, dopo l'esecuzione di

s[1] = '\0'; 

stringa s[] consiste in un singolo carattere che non è né uno spazio né una scheda, seguito da un terminatore di stringa.

Nella prossima dichiarazione

if (!isdigit(c) && c != '.') 
    return c; /* not a number */ 

la funzione restituisce se il carattere è tutt'altro che una cifra o un punto decimale. Questo è il motivo per cui è stato necessario terminare la stringa.

+0

Una buona spiegazione, anche se rimuoverei aggettivi positivi come "conveniente", poiché ciò suggerisce che questo codice K & R disordinato segue una sorta di buona pratica di codifica in C, mentre in realtà è piena fino all'orlo dell'opposto. – Lundin

+0

@Lundin: Sono completamente d'accordo sul fatto che il codice K & R in questione sia terribile da un punto di vista di "buona pratica di codifica", ma il codice illustra alcune novità del linguaggio C che sono importanti per i principianti. Dal punto di vista del design dell'algoritmo, e credo dalla prospettiva dell'autore originale del codice (molto prima che venissero concepite le "buone pratiche di codifica" di oggi), l'assegnazione a s [0] a questo punto del codice è un convenienza, dal momento che non dovrà essere eseguita in seguito. – sifferman

2

Ma cosa succede se l'input ha uno spazio bianco all'inizio e seguito da un operando o operatore? In questo caso, s [1] = '\ 0' chiuderà la stringa troppo presto? non è vero?

No,

i = 0; 
if (isdigit(c)) /* collect integer part */ 
    while (isdigit(s[++i] = c = getch())) 

Questo fa in modo che, se c'è qualcosa da leggere, otterrà sovrascritto il \0, come i=0 e s[++i] significherebbe, memorizzazione in s[1], che contiene il \0

+0

thx per aver risposto alla mia seconda domanda! Qualche commento sulla mia prima domanda? –

0

per la vostra prima domanda su: s [0] in:

while ((s[0] = c = getch()) == ' ' || c == '\t') 

perché il risparmio 'c' in s [0] aiutare a memorizzare primo numero in anticipo in modo che possiamo iniziare il nostro codice successivo da semplicemente i uguale a 1.

i = 0; 
if (isdigit(c)) /* collect integer part */ 
    while (isdigit(s[++i] = c = getch())) 

il codice precedente viene utilizzato per la memorizzazione di prossima stringa di caratteri che è cominciare dall'indice i = 1

Circa la seconda domanda:

0.123.

non possiamo fare

s[0] = '\0'; 

perché in quel momento abbiamo già memorizzato primo numero nella stringa in s [0]

see

(s[0] = c = getch()) 
Problemi correlati