je_clenem()?

David Zabensky zabensky na ica.cz
Pátek Únor 25 09:03:59 CET 2000


Dobry den,

omlouvam se za OT ale vim, ze konferenci cte par C GURU :-) a mam zajimavy problem,
se kterym bych chtel poradi. Chtel bych si napsat funkci s promennym poctem argumentu, jenz pro
hodnotu typu VARARGS zjisti ze seznamu argumentu fce, zda je argument clenem. Volani teda muze
vypadat treba takhle:

if(je_clenem(vaINT, 3, 1,2,4,5,3,NULL)) puts("3 je clenem [1,2,4,5,3]");

if(je_clenem(vaSTRING, "ahoj", "a", "Linux :-), aby to nebylo zas az tak OT", "ahoj")) puts("ahoj je clenem");

atd...

Proste seznam paramentru je ukoncen NULL a porovnava se 1. za "typ" s ostatnimi.
Problem je vsak v tom, ze makro va_start zrejme potrebuje argument funkce. Pokud tedy
dosadim do neho treba iVal, na Linuxu se mi to prekompiluje s warning hlaskami, ale na unixu
(Digital) uz treba ne (koncim s error). Pokud tam dam "typ", je to sice OK, ale tim vypocet pomoci 
sizeof vraci velikost enum VARARGS a ne treba int. A nasledne cteni zasobniku vraci blbosti.

Vim, ze to neni prenositelne, ale chtel bych mit nejakou pomocnou fci, ktera by mi mohla kontrolovat,
zda polozka je clenem mnoziny. Jde mi o to, jak to udelat (jestli vubec to lze) a vyhnout se tomu,
 ze budu muset mit za "typ" povinny argument typu int, char *.... a pri kazdem pridelani noveho
paramentru to cele prekopat :((

Ma nekdo nejaky napad?
D.
kod:
-- 
#include <stdarg.h>
typedef enum {
  vaINT,
  vaCHAR,
  vaSTRING
} VARARGS;

const int je_clenem(VARARGS typ, ...) {
  int found = 0;
  int iVal, iArg;
  char cVal, cArg;
  char *sVal, *sArg;
  va_list arg;

  switch(typ) {
    /* zpracovavam argumenty typu int */
    case vaINT: {
      /* inicializuji arg */
      va_start(arg, iVal);
      /* nactu hledanou hodnotu */
      iVal = va_arg(arg, int);
      /* porovnavam dalsi hodnoty */
      while(iVal && found == 0 && (iArg = va_arg(arg, int)) != (int) NULL)
        if(iArg == iVal) found = 1;
      va_end(arg);
      break;
    }
    /* zpracovavam argumenty typu char * */
    case vaSTRING: {
      va_start(arg, sVal);
      sVal = va_arg(arg, char *);
      while(sVal && found == 0 && (sArg = va_arg(arg, char *)) != (char *) NULL)
        if(strcmp(sVal, sArg) == 0) found = 1;
      va_end(arg);
      break;
    }
  }

  return found;
}


Další informace o konferenci Linux