C/Visual C - Funciones con argumentos variables.

 
Vista:

Funciones con argumentos variables.

Publicado por Gilbrán (1 intervención) el 01/08/2005 17:29:23
Saludos.

Tengo el siguiente código en C:

#include <conio.h>
#include <stdio.h>
#include <stdarg.h>

/* Calcula la sumatoria de un n£mero indefinido de argumentos enteros. */
int sum(int v, ...)
{
int arg=0, total=v;
va_list argptr;

va_start(argptr, v);
while ((arg=va_arg(argptr, int))!=0)
total+=arg;
va_end(argptr);

return total;
}

/* PROGRAMA PRINCIPAL*/
void main()
{
clrscr();
printf("\nSumatoria: [%ld]", sum(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15));
}

Hasta aquí podrán ver lo que estoy haciendo para leer una lista de argumentos variables de una función determinada, no obstante, mi problema radica en una manera confiable de leer toda la lista de argumentos hasta el final, es decir, encontrar un tope confiable del final de la lista de argumentos, para incluir aquellos argumentos que se envíen a la función como cero o valores aparentemente no válidos; pero lo más que he logrado es leer el apuntador argptr hasta que sea NULL y mientras leo la lista recupera cantidades extrañas de la memoria.

O bien, si conocen otra manera de recuperar de manera confiable una lista argumentos variables de una función dada aunque los argumentos que se envíen sean cero o cantidades que parecieran extrañas. Por ejemplo, sum(-34590, -27620, 0, 0, -12500, 75000);

Por su atención, muchas gracias compañeros.

Gilbran Romero Caballero.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Funciones con argumentos variables.

Publicado por El Mogur (202 intervenciones) el 03/08/2005 00:15:17
Buenas,

No he utilizado nunca funciones con argumentos variables desde C (quiero decir, con lo del va_list, y todo eso; hace mucho lo hice, y luego accedía a los parámetros en ensamblador ;) )... Bueno, que me voy del tema ;)

Decía, que no he usado nunca el va_list, etc., y no sé si se puede saber cuántos argumentos hay, pero a mí me da que no se puede, vamos. Lo digo pensando en cómo implementa el compilador las llamadas a las funciones en C.
Por eso, en las funciones como printf o scanf se necesita la cadena inicial del formato; no sólo es para saber qué cosas escribir entre los %d o %s, sino también le sirve para saber cuántos parámetros hay.

Como soluciones, yo veo dos:

1. El primer parámetro indica el número de sumandos que vas a pasar a la función.
2. Se marca el final de los sumandos con un 0. Así, cuando se van leyendo argumentos, se acaba cuando se lee un cero (vamos, como lo estás haciendo ahora). En ese caso, tendrás que:

sum (1,0) == sum(1, 0, 1234, 1234, 1243, 1243, 1243, 1243)

Saludos.

P.D.: Si alguien cree que se puede saber el número de argumentos pasados a una función variable, que me saque de mi error! ;)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Funciones con argumentos variables.

Publicado por fernando.gomez (1603 intervenciones) el 03/08/2005 00:31:38
Yo también pienso que no se puede por lo que comenta El Mogur. De hecho printf no valida argumentos, y si te equivocas (p.e. que falte algún argumento), ¡zaz! Caes al lado oscuro de la fuerza: el comportamiento indefinido. Pero pa no quedarme con las dudas, checo en draft de C99 y aviso. Salutes.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Funciones con argumentos variables.

Publicado por fernando.gomez (1603 intervenciones) el 03/08/2005 00:44:55
Bueno, pues el libro de Kernighan y Ritchie no es muy ilustrativo al respecto, pero por lo visto sí le tendrías que pasar de alguna forma el número de argumentos, o bien asumir un número de argumentos fijo. En mi opinión, esto te puede causar muchos problemas, relacionados con el comportamiento indefinido. ¿Por qué mejor no empleas una lista o un array para pasar argumentos variables? Algo así como el "params" de C#...

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Funciones con argumentos variables.

Publicado por fernando.gomez (1603 intervenciones) el 03/08/2005 01:17:36
Estaba revisando --ahora sí-- el draft de C99 (http://dev.unicals.com/c99-draft.html) y encontré en la sección 6.7.5.3#6 el siguiente texto:

"If the list terminates with an ellipsis (, ...), no information about the number or types of the parameters after the comma is supplied".

Más adelante, en la sección 7.15.1#2:

"The parameter type shall be a type name specified such that the type of a pointer to an object that has the specified type can be obtained simply by postfixing a * to type. If there is no actual next argument, or if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined".

En la sección 7.15.1.4#6 proponen el siguiente ejemplo:

#include <stdarg.h>
#define MAXARGS 31

void f1(int n_ptrs, ...)
{
va_list ap;
char *array[MAXARGS];
int ptr_no = 0;

if (n_ptrs > MAXARGS)
n_ptrs = MAXARGS;
va_start(ap, n_ptrs);
while (ptr_no < n_ptrs)
array[ptr_no++] = va_arg(ap, char *);
va_end(ap);
f2(n_ptrs, array);
}

Como ves en el ejemplo propuesto definen un máximo de argumentos. Además, su primer parámetro indica el número de parámetros variables. De esto, así como de los extractos que saqué del draft líneas arriba, se infiere que no hay forma de hacer exactamente lo que quieres, más que empleando una variable que indique el número de parámetros variables, bien en forma directa (como en el ejemplo previo), bien de forma indirecta (como en el printf).

Saludos.


Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Funciones con argumentos variables.

Publicado por El Mogur (202 intervenciones) el 03/08/2005 11:02:48
Gracias por el análisis, Fernando! ;)

Saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Funciones con argumentos variables.

Publicado por Franco Cedillo (36 intervenciones) el 09/08/2005 01:47:57
Hola,

Sí, los argumentos variables fue un tema que vi a grandes rasgos. Pero aporto con un código.

Se trata de la impresión de cadenas en pantalla. Lo que sí está presente siempre es el número de parámetros. y hay que tener cuidado con los diferentes casos incluso en el que no envíes ningún parámetro pero de todas maneras tendrías que indicarle que son 0 parámetros. (O tal vez poniendo 0 en valor por defecto, voy a probar eso :D).

#include <cstdarg>
using namespace std;

void funcion(int a, ...);

int main()
{
funcion(1, "cadena 1", 0);
funcion(1, "cadena 1", "cadena 2", "cadena 3", 0);
funcion(1, 0);
cin.get();
return 0;
}

void funcion(int a, ...)
{
va_list p;
va_start(p, a);
char *arg;
while ((arg = va_arg(p, char*)))
{
cout << arg << " ";
}
va_end(p);
cout << endl;
}

verán, el código es muy similar al de los drafts de c99 que menciona fernando, yo voy a revisar esa referencia :D... así como en C# se usa un param# que te ayudaría a validaciones yo usé el paramcount en el lenguaje pascal (antiguo pero introductorio para la programación, me gustó mucho).

esto sirve hasta para llamar a un programa completo, cuando hice la simulación del copy del dos hay que validar archivo original y el de destino, son dos parámetros y tal vez los parámetros adicionales ( podría haber uno de usar el mismo nombre, o de crear una copia con atributo de sólo lectura, etc )

saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Funciones con argumentos variables.

Publicado por fernando.gomez (1603 intervenciones) el 09/08/2005 04:21:26
Hola, bueno pues el código que muestras es muy ingenioso. En efecto, el 0 al final sería un NULL, así que la variable arg obtendría un NULL en todo caso, lo que es --a primera vista-- un valor válido en una cadena. Tentativamente no tendría que haber espacio para el comportamiento indefinido...

Quizás con un poquito más de investigación --sólo para estar seguro--, pero creo que podrías publicar un buen artículo en code project al respecto.

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar