Skocz do zawartości

Witamy w Nieoficjalnym polskim support'cie AMX Mod X

Witamy w Nieoficjalnym polskim support'cie AMX Mod X, jak w większości społeczności internetowych musisz się zarejestrować aby móc odpowiadać lub zakładać nowe tematy, ale nie bój się to jest prosty proces w którym wymagamy minimalnych informacji.
  • Rozpoczynaj nowe tematy i odpowiedaj na inne
  • Zapisz się do tematów i for, aby otrzymywać automatyczne uaktualnienia
  • Dodawaj wydarzenia do kalendarza społecznościowego
  • Stwórz swój własny profil i zdobywaj nowych znajomych
  • Zdobywaj nowe doświadczenia

Dołączona grafika Dołączona grafika

Guest Message by DevFuse
 

Zdjęcie

Funkcja zmiennej liczby parametrów


  • Nie możesz napisać tematu
  • Zaloguj się, aby dodać odpowiedź
2 odpowiedzi w tym temacie

#1 R3X

    Godlike

  • Przyjaciel

Reputacja: 2 987
Godlike

  • Postów:4 248
  • Lokalizacja:Nie
Offline

Napisano 21.07.2010 20:33

*
Popularny

Funkcja zmiennej liczby parametrów

Czasem przydać się może możliwość elastycznego podawania parametrów funkcji. Dobrym przykładem są fakemetowe pev i set_pev, gdzie ilość parametrów określa typ zwracanych danych.

1. Umożliwienie podania dowolnej liczby parametrów
w nagłówku należy użyć ... jako ostatni argument
public funkcja(...){
}
public funkcja(id, data, Float:data2, ...){
}

W tym wypadku dodatkowymi parametrami mogą być tylko liczby całkowite. Dozwolone typy możemy uwzględnić dodając Tag:
public funkcja(Float:...){
}
lub kilka typów
public funkcja({Float, _, Array, CsTeams}:...){
}
albo dowolny typ
public funkcja(any:...){
}

2. Określenie ilości nadesłanych argumentów

Ilość zwraca funkcja
numargs()
Przykład
public plugin_init(){
	test(1);
	test(1, 2);
	test(1, 2, 3);
}
public test(...){
	new iNum = numargs();
	log_amx("%d", iNum);
}

3. Pobieranie danych
No i w tym miejscu wychodzą ograniczenia. Nie ma możliwości sprawdzenia jaki typ danych ma konkretny parametr ani nawet czy jest to komórka pamięci czy tablica. Musimy wiedzieć jakich się należy spodziewać. Opieramy się na pewnej umowie, np.: funkcja przyjmować może trójwymiarową tablicę Floatów lub 3 inty. Jeśli programista złamie taką umowę, działanie funkcji może zostać zatrzymane z błędem w errorlogu. Wszystkie dane pobieramy jedną funkcją:

getarg(arg, index=0)
gdzie arg to numer parametru (licząc od 0) a index pozwala na pobranie tablicy.

/**
 * Wszystkie parametry funkcji traktuje jak inty
 */
test1(...){
	log_amx("Test1");
	log_amx("%d", numargs());
	for(new i=0;i<numargs();i++){
		log_amx(">> %d", getarg(i));
	}
}

Inne niż _ typy trzeba opatrzyć ich tagiem. Co prawda w poniższym przykładzie nie jest on konieczny, ale w wielu wypadkach musi wystąpić.
/**
 * Wszystkie parametry funkcji traktuje naprzemian jak inty i jak floaty
 */
test2({_, Float}:...){
	log_amx("Test2");
	log_amx("%d", numargs());
	
	new bool:isInt = true;
	for(new i=0;i<numargs(); i++){
		if(isInt)
			log_amx(">> %d", getarg(i));
		else
			log_amx(">> %f", Float:getarg(i));

		isInt = !isInt
	}
}

To wszystko dotyczy pojedynczych komórek pamięci. Co z tablicami?

Do pobrania tablicy potrzebujemy jej rozmiaru. Tu obowiązuje ta nasza umowa i pobieramy tyle indeksów ile zapowiedzieliśmy, że chcemy :)
Jeśli tablica jest tekstem, wykorzystujemy budowę takiego łańcucha znaków i pobieramy kolejne komórki aż napotkamy bajt zerowy '^0'.
test3(...){
	log_amx("Test3");
	new iNum = numargs();
	if(iNum == 1){
		//Pobierz pierwszy argument jako stringa
		new szBuffer[32];
		for(new i=0;i<sizeof szBuffer; i++){
			szBuffer[i] = getarg(0, i);
			if(szBuffer[i] == '^0') break;
		}
		szBuffer[charsmax(szBuffer)] = '^0';
		log_amx("%s", szBuffer);
	}else if(iNum > 1){
		log_amx("%d %d", getarg(0), get_arg(1));
	}
}

4. Zwracanie wyniku
return oczywiście nie przestał tu działać, chodzi o referencję.

służy do tego funkcja
setarg(arg, index=0, data)

ustawia ona parametr na daną wartość, jeśli jest typu innego niż liczba całkowita usuwamy tag _:
w przypadku tablic każdy jej indeks osobno. Jeśli chodzi o stringi to ciągle interesuje nas bajt zero.

/**
 * data - dane
 * Ilość dodatkowych parametrów
 * 0 - zwraca data jako inta
 * 1 - zwraca data jak floata przez referencję
 * 2 - zwraca data jako stringa przez referencję (string[], len)
 */
test4(data, {_, Float}:...){
	log_amx("Test4");
	
	switch(numargs()){
		case 1: return data;
		case 2: setarg(1, 0, _:float(data));
		case 3:{
			new szBuffer[32];
			formatex(szBuffer, 31, "%d", data);
				
			new iLen = getarg(2);
			for(new i=0;i<iLen;i++){
				setarg(1, i, szBuffer[i]);
				if(szBuffer[i] == '^0')
					break;
			}
			
			//Upewnij sie ze string zakonczony bajtem NULL
			setarg(1, iLen, '^0');
		}
	}
	return 1;
}

  • +
  • -
  • 9

#2 Miczu

    Godlike

  • Przyjaciel

Reputacja: 657
Wszechmogący

  • Postów:2 862
Offline

Napisano 21.07.2010 20:51

Patrzyłem na te get/set -arg i numargs, ale nie mogłem znaleźć przykładu, a nie maiłem sił by robić coś samemu... GJ
  • +
  • -
  • 0

#3 grankee

    Godlike

  • Support Team

Reputacja: 517
Wszechwiedzący

  • Postów:1 500
  • Lokalizacja:Radom
Offline

Napisano 11.09.2010 18:35

Bardzo ciekawe i pewnie niejeden programista zaczynający przygodę szukał czegoś takiego do rozwiązania swoich celów. GJ
  • +
  • -
  • 0




Użytkownicy przeglądający ten temat: 0

0 użytkowników, 0 gości, 0 anonimowych