Duda con ejemplo del libro k&r

Iniciado por fruz, 21 Abril 2019, 01:00 AM

0 Miembros y 1 Visitante están viendo este tema.

fruz

Hola! Tengo una duda con este ejemplo del libro de k&r.
Según entiendo en el while de main se le pasa valores a la función getline al momento de llamarla. ¿En qué momento se  le pasa el arreglo s (que está dentro de getline) al arreglo line?
También quisiera saber: ¿El arreglo s que está dentro de getline tiene una extensión de 1000 caracteres al igual que line?

#include <stdio.h>
#define MAXLINE 1000    // maximum input line size

int getline(char line[], int maxline);
void copy(char to[], char from[]);

/* print longest input line */

int main()
{
   int len;            //current line lenght
   int max;            //maximum length seen so far
   char line[MAXLINE]; //current input line
   char longest[MAXLINE];//longest line saved here

   max = 0;
   while ((len = getline(line, MAXLINE)) > 0)
       if (len > max) {
           max = len;
           copy(longest, line);
       }
       if (max > 0)   //there was a line
           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 = c;
   if (c == '\n') {
       s = c;
       ++i;
   }
       s = '\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 = from) != '\0') {
       ++i;
   }
}

Serapis

#1
Citar¿En qué momento se  le pasa el arreglo s?
's' es el nombre interno del array en la función 'getline', como 'getline' es invocada desde la función 'main', resulta que el array 's' es en realidad el array 'line', así el punto exacto donde se le pasa dicho array es en:
       while ((len = getline(line, MAXLINE)) > 0)

Citar¿El arreglo s que está dentro de getline tiene una extensión de 1000 caracteres al igual que line?
Como acabo de señalarte, es el mismo array, luego es lo mismo...
Que una función 'x' tenga parámetros llamados así 'a', 'b', 'c':
   Funcion x(a, b, c)
y luego tu lo invoques así:
   llamada a x("hola", s, (k+23) )
no altera nada, cada parámetro si sigue siendo del mismo tipo, en otra parte tendrá otro nombre, al final o se pasa una dirección de memoria que contiene el valor o un valor inmediato... es decir en otra parte puede llamarse de otra manera...

Un ejemplo llano: Hay 3 estudiantes, Luis, Carlos y Antonio, y tienen 20, 25 y 30 años respectivamente, Luis estudia, Carlos trabaja y Antonio se toca los "0,0"... entonces en otra parte podrían llamarlos de la siguiente forma:
--- Carlos venga usted para acá"... como se llama Carlos, se sabe quien es.
--- El que trabaja, que venga para acá... como 'trabaja' es un atributo de Carlos (digamos que s elocaliza en memoria, por una dirección alternativa...
--- El que tiene 25 años, que venga para acá....
incluso aún s ele podría decir:
--- El segundo de la fila, que venga para acá (símil que reflejaría estar dentro de un array).

en todos casos se está llamando a 'Carlos' pero con diferentes 'nombres', no importa en unos se le llama por su nombre, en otros por su valor o una referencia, incluso una referencia a una referencia, etc...

Entonces en la funcion 'main', 'line' es el nombre de un array (pongamos que es Carlos), pero cuando se invoca getline(carlos), luego la función 'getiline' lo llama 's' que podríamos decir que ahora en vez de llamarlo 'Carlos' lo llama 'el que trabaja'...
    int getline(char elquetrabaja[], int lim)
    int getline(char elquetiene25años[], int lim)
    int getline(char elsegundodelafila[], int lim)
como tu le pasaste 'Carlos' pués ese es el que recibe, luego 's' y 'getline' son la misma cosa, el mismo contenido.
Es decir, no estás obligado a darle el nombre a una variable que tu has creado y vas a usar con el nombre que tiene el parámetro en una función... imagina que ese array se tuviera que pasar a 3 funciones diferentes, podrían tener diferentes nombre... luego si fuera una exigencia tener el mismo nombre impediría que pudiera ser usado en más de una función.
El nombre de un parámetro solo tiene sentido fuera para saber que se espera, para diferenciar con claridad que se pretende recibir, una ayuda al que usa la función, internamente poco importa el nombre, de hecho en funciones simples sin complejidad alguna y que quedan ocultas (nunca son llamadas desde fuera), suele ponerse nombres sin importancia como 's'...

Un ejemplo que clarifica que se pide en cada parámetro y que una vez dentro poco importa, los nombres usados internamente... al caos reg, se supone una clase que no es accesible desde fuera, y tiene nombres que no precisan aclarar mucho o nada, o si se prefiere podría ser una estructura y luego se invocaría un método 'save' usando como parámetro la estructura 'reg'...

funcion GuardarRegistro( char nombre[], char apellido1[], char apellido2[] )
   // reg se supone una clase o si prefieres una estructura y luego un método: save(reg)
    reg.x=nombre;
    reg.y=apellido1;
    reg.z=apelido2;
    reg.save;   //save(reg);
fin funcion


OJO... al decir que dos parámetros son el mismo, no es estrictamente cierto, solo mientras se pase por referencia, a veces no se quiere que se modifiique el original, entonces se pasa una 'copia' así cualquier modificación que se haga al que se pasa, deja intacto al original, la copia suple el mismo efecto (para lo que se necesite que se deba hacer con los datos recibidos) que usando el original, pero dejando el original intacto.

Espero que este pequeño sermón aclare tus dudas.

Si tienes además algún IDE instalado, es bueno que ejecutes el programa "paso a paso", porque así y ahí es donde se descubre todo el potencial que ofrece un IDE, al saltar de una línea a la siguiente, e ir viendo la ejecución de adónde salta, consutar que valor contiene una variable etc... es decir ejecutando en modo DEBUG, se aprende mucho más y más rápido que solo leyendo y por ejemplo escibiendo en un 'procesador de texto' como algunos ingenuos creen que es mejor viendo pelis (nunca es mejor y menos para el que empieza, para el que todo son tinieblas... hasta que se despejen las nubes).


fruz

¿Esto es así solo en el caso de los arrays? Si entiendo bien, cuando se trata de variables comunes no son las mismas, sinó copias.

Serapis

Si se pasa por referencia, se pasa la dirección de la variable, luego en ambos casos es la misma variable, es decir distintos nombres apuntan a la misma dirección de memoria, (haya lo que haya alli, da igual  si es un string, una variable simple, un array...), si se pasa por valor, quiere decir que se hace una copia y por tanto no se recibe la dirección original, si no la de una variable temporal (normalmente localizada en la pila)...

...sigue leyendo el libro, seguramente te lo aclarará más adelante, no me creo que un libro no aclare cosas tan simples, más bien lo hará cuando se considere el momento oportuno. Tu ahora no te compliques con eso, de momento te baste saberlo...