Problem z zmienną liczbą argumentów.

0

Witam, napisałem takie coś, żeby zobaczeć czy uda mi się napisać coś co wykorzystuje stdarg.h.

void errorMessage(char* text, ...){
    string error;
    va_list arg_list;
    int iterator =0;
    va_start(arg_list, text);
    //error = va_arg(arg_list,char*);
    for(int i =0;i<iterator;i++){
        error += va_arg(arg_list, char*);
    }
    va_end(arg_list);

    cout << error.data() << endl;

}

No i jest tak.
Jeżeli skompilować tak jak jest to nic nie wypisze.
Jeżeli odkomentować ten komentarz i zmienić i=0 na i=1 to wywala błąd.
Przykładowo - errorMessage("test","test "," test \n Test");
Nie widzę tutaj co może być źle, więc co jest źle i jak to naprawić?

0

eee "zmienić i=0 na i=1"?
a nie przypadkiem zmienić: "int iterator =0;" na "int iterator =1;"

0

Skąd ty w ogóle bierzesz liczbę argumentów? va_arg jest prymitywne jak komentarz na onecie - po prostu idzie w górę stosu.
Musisz albo stworzyć sobie swój własny terminator (np. NULL jako ostatni argument) albo podawać ilość argumentów jako pierwszy argument.

0
pompom napisał(a)

Skąd ty w ogóle bierzesz liczbę argumentów? va_arg jest prymitywne jak komentarz na onecie - po prostu idzie w górę stosu.
Musisz albo stworzyć sobie swój własny terminator (np. NULL jako ostatni argument) albo podawać ilość argumentów jako pierwszy argument.
Lub w jakikolwiek inny sposób muisz przekazać informację o ilości argumentów w samych argumentach.

0

Gdy lista argumentów zostanie wyczerpana va_arg zwraca 0x00000001, poprawiony kod powinien wyglądać tak:

void errorMessage(char* text, ...){
    std::string error;
    va_list arg_list;
    int iterator =0;
    char *temp = (char*)0x00000001;
    va_start(arg_list, text);
    //error = va_arg(arg_list,char*);
    do{
        temp = va_arg(arg_list, char*);
        if(temp != (char*)0x00000001){
            error += temp;
        }
    }while(temp != (char*) 0x00000001);
    MessageBox(NULL,error.c_str(),"Message",MB_OK);

    va_end(arg_list);   
    //std::cout << error.data() << std::endl;
}
0
gringoM napisał(a)

Gdy lista argumentów zostanie wyczerpana va_arg zwraca 0x00000001
G. prawda

0

adf88 napisał

G. prawda

Ciekawe że to działa (kompilowałem i sprawdzałem więc wiem), no i jeszcze dodam że w MSDN jest taki przykład tego typu funkcji:

int average( int first, ... )
{
   int count = 0, sum = 0, i = first;
   va_list marker;

   va_start( marker, first );     /* Initialize variable arguments. */
   while( i != -1 )
   {
      sum += i;
      count++;
      i = va_arg( marker, int);
   }
   va_end( marker );              /* Reset variable arguments.      */
   return( sum ? (sum / count) : 0 );
}

tu jest zastosowana ta sama zasada tylko że dla innego typu argumentów
</quote>

0

gringoM, że tak to ujmę: g**no prawda :]
twoja piękna funkcja z MSDN działa dobrze, jeśli się jako ostatni arg poda -1:

 // działa super
cout << average(7,1,1,-1) << endl;

 // w najlepszym wypadku wpisuje głupotę - w najgorszym mamy ostry syf
cout << average(7,1,1,10) << endl;

Cytując właśnie MSDN:

va_arg returns the current argument; va_start and va_end do not return values.

Dopisane, bo rozmowa idzie w głupią stronę:
Netaro, załóżmy sobie że funkcji np jako ostatni argument podajesz NULL, albo pusty tekst "", wtedy funkcja wygląda podobnie do twojej, ale trochę poprawiona:

#include <iostream>
#include <cstdarg>
#include <string>
using namespace std;

void errorMessage(char* text, ...){
    string error;
    va_list arg_list;
    va_start(arg_list, text);

    char* value = va_arg(arg_list, char*);
    while( value && *value ) {
        error += value;
        value = va_arg(arg_list, char*);
        }

    va_end(arg_list);
    cout << error.data() << endl;
    }

int main() {
    errorMessage("message", "first", "second", "third", "");
    errorMessage("error", "one", "two", "three", NULL);

    return 0;
    }

while(value) - dopóki wskaźnik nie jest NULLem
while(*value) - dopóki wskaźnik nie wskazuje na pusty string

0
MSDN napisał(a)
/* Call with 3 integers (-1 is used as terminator). */
printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );
0

Ranides, działa to co ty napisałeś u ciebie?
Wziąłem dokładnie kopiuj-wklej i niestety nie działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0