PDA

Visualizza la versione completa : [C/C++]: Chiarimenti su funzioni e prototipi


Rommel
25-07-2006, 13:11
Ciao a tutti,
sto imparando a programmare in C leggendo il libro "The C Programming Language 2nd edition" di K&R e mi sono bloccato in un punto.


#include <stdio.h>

#define MAXLINE 1000 /* maximum input line length */

int getline(char line[], int maxline);

void copy(char to[], char from[]);

/* print the longest input line */
int main() {
int len, max;
char line[MAXLINE], longest[MAXLINE];

max = 0;
while ((len = getline(line, MAXLINE)) > 0) {
if (len > max) {
max = len;
copy(longest, line); } }
if (max > 0) {
printf("%s", longest); }

return 0; }

/* getline: read a line into s, return length */
int getline(char s[], int lim) {
int c, i;

for (i=0; i < lim-1 && (c=getchar()) != EOF && c != '\n'; ++i) {
s[i] = c; }
if (c == '\n') {
s[i] = c;
++i; }
s[i] = '\0';

return i; }

/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[]) {
int i;
i = 0;
while ((to[i] = from[i]) != '\0') {
++i; } }

Precisamente non ho capito perché all'inizio (dopo il #define) c'è int getline(char line[], int maxline);, mentre dopo cambia in int getline(char s[], int lim).

Scusate la domanda niubba. Ho cercato di capire, ma non ce l'ho fatta :fagiano:

Habanero
25-07-2006, 15:11
int getline(char line[], int maxline);
viene chiamato prototipo. In genere non è neanche necessario specificare il nome delle variabili ma solo il loro tipo:

int getline(char [], int );

in questo modo il compilatore puo' conoscere la funzione e i suoi parametri prima di incontrare la funzione stessa all'interno del codice.

ad esempio:




int getline(char [], int ); // questo è il prototipo


int main(int argc, char **argv)
{
....
....
getline (stringa, intero)
....
...
}

int getline(char s[], int lim)
{

.....
.....

}


quando il compilatore arriva alla getline() all'interno del main, grazie al prototipo, puo' già verificare che la chiamata sia corretta ed utilizzi i tipi giusti... senza prototipo non sarebbe possibile perchè getline() è definita dopo il main.

I nomi delle variabili nel prototipo non sono influenti... l'importante è che siano indicati i tipi.

Rommel
25-07-2006, 20:26
Ecco, ora ho capito. Però è strano che K&R abbiano messo quella variabili a caso nel prototipo. Così confondono solo le idee ai niubbi.

Inoltre:
for (i=0; i < lim-1 && (c=getchar()) != EOF && c != '\n'; ++i) {
s[i] = c; }
if (c == '\n') {
s[i] = c;
++i; }
s[i] = '\0';

Non capisco in quali circostanze l'uguaglianza c == '\n' possa essere vera.
Il ciclo if non è incluso nel for :master:

nanu_90
25-07-2006, 21:25
Immagino che c=='/n' è come non scrivere niente e andare a capo. cmq se non ti funziona prova a scrivere c==''. :ciauz:

Rommel
25-07-2006, 22:05
Originariamente inviato da nanu_90
Immagino che c=='/n' è come non scrivere niente e andare a capo. cmq se non ti funziona prova a scrivere c==''. :ciauz:
\n non è il nulla. È semplicemente un carattere come r, b, \t o putchar(numero_a_piacere).
Almeno, questo so io :fagiano:

U-bahn
26-07-2006, 10:16
Originariamente inviato da Rommel
Ecco, ora ho capito. Però è strano che K&R abbiano messo quella variabili a caso nel prototipo. Così confondono solo le idee ai niubbi.

mmh, in realtà non confonde affatto, anzi: se, ad es., una funzione fa parte di una libreria, è normale che nel prototipo siano presenti i nomi(possibilmente descrittivi) delle variabili,
e non è raro che differiscano da quelle della dichiarazione della funzione (se sono diverse, solitamente queste ultime hanno nomi più brevi)

poi non preoccuparti...fidati di K&R: loro hanno ragione comunque. Sempre. :D




Non capisco in quali circostanze l'uguaglianza c == '\n' possa essere vera.

forse scritto così si legge meglio:



for (i=0; i < lim-1; ++i) {
c = getchar()
if (c == '\n' || c == EOF)
break;
s[i] = c;
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';



:ciauz:

Rommel
26-07-2006, 12:35
Originariamente inviato da U-bahn
forse scritto così si legge meglio:
È incredibilmente più chiaro :)

Grazie a tutti per le risposte :ciauz:

LeleFT
27-07-2006, 10:55
E' sicuramente più chiaro... ma è tutta un'altra cosa da quello che ha postato il nostro amico. :)
Questa è la stessa cosa, scritta meglio (nel senso dell'indentazione):


for (i=0; i < lim-1 && (c=getchar()) != EOF && c != '\n'; ++i) {
s[i] = c;
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
In quale caso l'if può diventare vero? Quando il for trova il carattere di newline! In questo caso, infatti, il ciclo termina. Subito dopo si controlla se si è verificata questa condizione. In caso affermativo alla stringa "s" viene aggiunto il carattere di newline (che non viene aggiunto dal cilo!!), si porta sul carattere successivo (alla fine della stringa, quindi) e aggiunge il terminatore di stringa.

Questa piccola parte di codice viene spesso inserita in quei programmi che devono leggere sequenze di caratteri (come nei file) dove i terminatori dei dati utili sono EOF e NewLine con la sola differenza che il primo carattere non ha importanza, ma il secondo sì.


Ciao. :ciauz:

U-bahn
27-07-2006, 14:07
ma è tutta un'altra cosa
ma, veramente il codice assembly prodotto è essenzialmente lo stesso...:bhò:
il mio for:



.L3:
call getchar
movb %al, -1(%ebp)
cmpb $10, -1(%ebp)
je .L4
cmpb $-1, -1(%ebp)
je .L4
s[i] = c; (inutile inserire l'assembly qui)
.L2:
movl 12(%ebp), %eax
decl %eax
cmpl -8(%ebp), %eax
jg .L3

il for del libro:



.L3:
s[i] = c; (inutile inserire l'assembly qui)
.L2:
movl 12(%ebp), %eax
decl %eax
cmpl -8(%ebp), %eax
jle .L4
call getchar
movb %al, -1(%ebp)
cmpb $-1, -1(%ebp)
je .L4
cmpb $10, -1(%ebp)
jne .L3


:ciauz:

LeleFT
27-07-2006, 14:20
Originariamente inviato da U-bahn
ma, veramente il codice assembly prodotto è essenzialmente lo stesso...:bhò:

Senza dubbio. La mia osservazione, infatti, riguardava solamente la forma del codice, ad indicare che una corretta indentazione, oltre a migliorare la leggibilità, a volte aiuta (di riflesso) la comprensione. :)


Ciao. :ciauz:

Loading