Учись программированию на C++ Builder бесплатно!
  • Главная
  • Передача в функции нескольких параметров и управление макросами
Передача в функции нескольких параметров и управление макросами

Иногда в функции требуется передавать некоторое число фиксированных параметров плюс неопределенное число дополнительных параметров. В этом случае заголовок функции имеет вид:

тип имя_функции(список аргументов,...)

В данном случае список аргументов включает в себя конечное число обязательных аргументов (этот список не может быть пустым), после которого ставится многоточие на месте неопределенного числа параметров. Для работы с этими параметрами в файле stdarg.h определен тип списка va_list и три макроса: va_start, va_arg и va_end.

Синтаксис макроса va_start

void va_start(va_list ap, lastfix)

Этот макрос начинает работу со списком, устанавливая его указатель ар на первый передаваемый в функцию аргумент из списка с неопределенным числом аргументов. Параметр lastfix – это имя последнего из обязательных аргументов функции.

Синтаксис макроса va_arg

void typeva_arg(va_listар, type)

Макрос возвращает значение очередного аргумента из списка. Параметр type указывает тип аргумента. Перед вызовом va_arg значение ар должно быть установлено вызовом va_start или va_arg. Каждый вызов va_arg переводит указатель ар на следующий аргумент.

Синтаксис макроса va_end

void va_end(va_list ap)

Макрос завершает работу со списком, освобождая память. Он должен вызываться после того, как с помощью va_arg прочитан весь список аргументов. В противном случае могут быть непредсказуемые последствия.

Пример

Пусть требуется создать функцию average, которая рассчитывает и отображает в метке Label1 среднее значение передаваемых в нее целых положительных чисел. Функция принимает в качестве первого аргумента некоторое сообщение, которое должно отображаться перед результатами расчета. Список обрабатываемых чисел может быть любой длины и заканчиваться нулем. Такая функция может быть реализована следующим образом:

#include<stdarg.h>
void average(AnsiString mess, ...) {
	double A = 0;
	int i = 0, arg;
	va_list ap;
	va_start(ap, mess);
	while ((arg = va_arg(ap, int)) != 0) {
		i++;
		A += arg;
	}
	Form1->Label1->Caption = mess + "N= " + IntToStr(i) + ", среднее= " + FloatToStr(A / i);
	va_end(ap);
}

Вызов функции может быть, например, таким:

average("Результаты экзамена: ", 4, 2, 3, 5, 4, 0);

В результате функция выдаст в метку Label1 сообщение:

Результаты экзамена: N = 5, среднее = 3,6

Функцию average можно было бы организовать иначе, не вводя специальную конечную метку в список (в приведенном примере - 0), а предваряя список аргументов параметром N, указывающим размер списка:

void average(AnsiString mess, int N, ...)
{
	double A = 0;
	va_list ар;
	va_start(ар, N);
	for (int i = 0; i < N; i++)
		A += va_arg(ap, int);
	Form1->Label1->Caption = mess + "N = " + IntToStr(N) + ", среднее= " + FloatToStr(A / N);
	va_end(ap);
}

Вызов функции может быть, например, таким:

average("Результаты экзамена: ", 5, 4, 2, 3, 5, 4);

Поиск по сайту