Duda stdarg.h en C

Iniciado por jhonsc, 31 Enero 2012, 16:32 PM

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

jhonsc

Buenas (de nuevo). Estoy intentando que un programa me coja unos argumentos fijos y luego, me pueda recoger un número indefinido de argumentos. He oído que sería:

#include <stdarg.h>
int printf(char *text, char *color, ...) //Esto es lo que he oído.
{
/*
Aquí iría lo que no tengo ni idea. Si no pongo la de color consigo que me  coja la variable
texto, pero las "no obligatorias" me las deforma. Son unos int. Por ejemplo, pongo 32 y
me sale 1034..., en fín, que se equivoca. Si pongo la de color... ni se ejecuta.
*/
return 0;
}

Siento no ponerles el código completo, pero no tengo acceso a él en este momento.
"Vive rápido, muere joven y deja un bonito cadáver"
"Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas."
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad."

rir3760

En C estándar no puedes definir la función principal de esa forma, debe ser "int main(int argc, char **argv) ...", "int main(void) ..." o equivalentes.

Mejor explica de una forma clara lo que debes hacer. Supongo es procesar los argumentos pasados a tu programa mediante la linea de comandos o bien crear un programa con una función (similar a printf/scanf) que reciba un numero variable de argumentos.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

jhonsc

#2
Hola, lo que quiero hacer es un mini kernel. Me funciona y todo (al nivel que escribe algo y punto). En la función printf necesito que me recoja, el texto, el color, y las variables. Por ejemplo, la llamaría así: int c=32; printf("Intento patético de kernel.\nLa variable c es %d\n","red",c);
Ya tengo el printf pero o solo consigo elegir color, o solo coger variables. Cuando intento los dos a la vez, ERROR.
Si sirve de algo, este es mi stdarg.h :

#ifndef _STDARG_H
#define _STDARG_H

typedef char *va_list;
#define __va_rounded_size(TYPE)  \
 (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

#ifndef __sparc__
#define va_start(AP, LASTARG) \
(AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), \
 AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif

void va_end (va_list);
#define va_end(AP)

#define va_arg(AP, TYPE) \
(AP += __va_rounded_size (TYPE), \
 *((TYPE *) (AP - __va_rounded_size (TYPE))))

#endif /* _STDARG_H */

Y el printf tendría esta forma (solo es parte):

int printf(char *text, char *color, ...)

Ah y me equivoqué antes y puse "main" en vez de "printf", lo siento, pero ya dije que no tenía el código y me lié escribiendolo.
"Vive rápido, muere joven y deja un bonito cadáver"
"Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas."
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad."

rir3760

No es necesario publicar el contenido del encabezado, en su lugar es mejor revisar un buen libro.

Un programa sencillo de ejemplo:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

void fn(char const *texto, int num_args, ...);

int main(void)
{
   fn("Un argumento sin nombre", 1, 1);
   fn("Dos argumentos sin nombre", 2, 1, 2);
   fn("Tres argumentos sin nombre", 3, 1, 2, 3);
   
   return EXIT_SUCCESS;
}

void fn(char const *texto, int num_args, ...)
{
   int i;
   va_list lista; /* 1 */
   
   va_start(lista, num_args); /* 2 */
   
   printf("%s:", texto);
   
   for (i = 0; i < num_args; i++)
      printf(" %d", va_arg(lista, int) /* 3 */);
   putchar('\n');
   
   va_end(lista); /* 4 */
}


Los pasos son:

1) Declaras un objeto de tipo "va_list".

2) Ejecutas la macro "va_start" indicando el objeto declarado en el paso 1 y el ultimo parámetro con nombre (en este caso "num_args").

3) Cada vez que debas procesar uno los argumentos utilizas la macro "va_arg" indicando el objeto declarado en el paso 1 y el tipo del objeto esperado (en nuestro caso siempre es de tipo "signed int").

4) Una vez que termines de procesarlos ejecutas la macro "va_end".

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

jhonsc

#4
Muchas gracias. Pero como puedo pasar caracteres en vez de números, por ejemplo:
fn('a','b','c');
?¿?¿
"Vive rápido, muere joven y deja un bonito cadáver"
"Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas."
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad."

rir3760

Un consejo: si todavía no manejas con soltura el lenguaje C deberías dejar eso para después.

Un problema con el ejemplo que pones es: ¿Como sabrá la función cuantos argumentos se pasaran en la llamada? La función printf se basa en la cadena de formato y el ejemplo que presente en mi mensaje anterior utiliza el ultimo argumento con nombre pero en tu ejemplo falta ese mecanismo.

Por ultimo los caracteres literales no deben darte problemas ya que son enteros de tipo "signed int", mi ejemplo anterior con algunas modificaciones te puede servir de base.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

jhonsc

Ok! ya lo consegui! Gracias!!! Y eso.... soy demasiado impaciente, quiero aprender mucho, pero tengo poco tiempo xD. Gracias de nuevo.
"Vive rápido, muere joven y deja un bonito cadáver"
"Todos somos muy ignorantes. Lo que ocurre es que no todos ignoramos las mismas cosas."
"Hay una fuerza motriz más poderosa que el vapor, la electricidad y la energía atómica: la voluntad."