Función con error de tiempo de ejecución de argumentos variables
Frecuentes
Visto 330 veces
0
He escrito esta función para calcular el promedio de algunos flotadores. Pero tiene un error de tiempo de ejecución en la última línea de la función "promedio". ¿Cuál es el problema?
#include <stdarg.h>
#include <stdio.h>
float average(float first , ...)
{
int count = 0;
float sum = 0 , i = first;
va_list marker;
va_start(marker , first);
while(i != -1)
{
sum += i;
count++;
i = va_arg(marker , float);
}
va_end(marker);
return(sum ? (sum / count) : 0);
}
int main(int argc , char* argv[])
{
float avg = average(12.0f , 34.0f);
printf("The average is : %f\n" , avg);
scanf("a\n");
}
4 Respuestas
4
La función se repite hasta que ve un -1
, y la persona que llama no está proporcionando el -1
.
La página del manual en mi caja promete "errores aleatorios":
va_arg() ... If there is no next argument, or if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), random errors will occur.
Tratar:
float avg = average(12.0f, 34.0f, -1f);
contestado el 03 de mayo de 12 a las 17:05
2
Olvidó finalizar la llamada con un -1
, entonces tus while
loop provoca un comportamiento indefinido porque intenta seguir recibiendo más argumentos de los que pasó. Debería ser:
float avg = average(12.0f, 34.0f, -1f);
También, trabaja para float
Se promueven argumentos para double
cuando se pasa a funciones variádicas, por lo que no puede usar float
con va_arg
. Deberías estar usando double
para todo esto:
double average(double first, ...)
{
int count = 0;
double sum = 0, i = first;
va_list marker;
va_start(marker, first);
while(i != -1)
{
sum += i;
count++;
i = va_arg(marker, double);
}
va_end(marker);
return sum ? sum / count : 0;
}
double avg = average(12.0, 34.0, -1.0);
contestado el 03 de mayo de 12 a las 17:05
Funcionó. Pero, ¿hay alguna forma de no usar -1 en los argumentos pasados? - arman_aegit
@ Arman-aegit, la función necesita saber de alguna manera cuándo dejar de extraer argumentos (es decir, cuándo detener el while
lazo). Entonces, debe dar un valor al final como lo está haciendo ahora, o hacer algo como agregar un primer argumento que proporcione la cantidad de argumentos que desea sumar. Entonces sería como double average(int count, ...)
y podrías hacer double avg = average(3, 1.0, 2.0, 3.0);
. Lamentablemente, no existe una forma automática de saber cuántos argumentos se aprobaron. - Seth Carnegie
2
¿No quieres pasar -1 como el último argumento para detener el bucle while?
Además, creo que los flotantes se convierten en dobles cuando se usan VA, por lo que cambiar el flotante a doble sería bueno...
contestado el 03 de mayo de 12 a las 17:05
2
El problema es que no tiene una terminación para su bucle while. usted está buscando -1
pero nunca pases -1
. Tienes que llamar a tu average
función como
float avg = average(12.0f ,34.0f, -1);
Hay un ejemplo de tiempo de ejecución de este ejemplo en va_arg, va_fin, va_inicio que muestra casi exactamente su código, pero usando int
en lugar de float
por los valores.
contestado el 03 de mayo de 12 a las 17:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ c or haz tu propia pregunta.
Por experiencia personal, descubrí que las funciones que tienen un número variable de argumentos causan más problemas de los que valen, especialmente si se usa C++, ya que hay mejores (en mi humilde opinión) formas de evitar esto. - Ed Heal
En particular usando
-1
como un centinela tiene un diseño realmente malo, este podría ser un valor válido. Dado que se supone que todos sus parámetros tienen el mismo tipo, tanto C++ como C le ofrecen mejores alternativas para esto. - Jens Gustedt