Jump to content


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

Posted Image Posted Image

Guest Message by DevFuse
 

Funkcja zmiennej liczby parametrów


  • You cannot start a new topic
  • You cannot reply to this topic
2 replies to this topic

#1 R3X

    Godlike

  • Przyjaciel

  • Reputacja: 2,987
    Godlike

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

Posted 21.07.2010 20:33

*
POPULAR

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

Posted 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

Posted 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




  


1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users

Coinsy CSGOPolygon Za SMS, PSC , Przelew - CoinSell.pro
Skiny do CS:GO za SMS, PSC, Przelew - CSGOPaka.com
Automatyczny Bot Levelowania Steam - LVLUPSteam.com
CSGO Gambling Sites and Free Betting Codes - DreamCodes.gg

Sign In