Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 55, средняя оценка - 4.62
nikkka
Мат в 32 хода
235 / 170 / 8
Регистрация: 10.09.2009
Сообщений: 1,096
#1

Функции с переменным числом аргументов - C++

10.08.2010, 11:19. Просмотров 8042. Ответов 24
Метки нет (Все метки)

на пример sum(2,56,515,-23.65,548)?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.08.2010, 11:19
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Функции с переменным числом аргументов (C++):

GCC и функции с переменным числом аргументов - C++
Писал мини приложение в студии для работы с векторами, один из методов просто получает сколько угодно аргументов и заполняет координаты...

Шаблон с переменным числом аргументов, и возвращаемое значение функции - C++
Здравствуйте! Использую С++11. Хочу возвращать элементы кортежа пытаюсь так, auto Deserialize(unsigned long long i) ->...

Шаблоны с переменным числом аргументов - C++
Написал шаблон функции с переменным числом аргументов которая считает сумму своих аргументов. Практики по этому вопросу не имею, поэтому...

Шаблонная функция с переменным числом аргументов - C++
Сабж. Каким образом можно запретить использование шаблонной функции, если тип одного из аргументов не соответствует требуемому? Есть...

Инициализация std::tuple переменным числом аргументов - C++
Добрый вечер. Мне нужно инициализировать объект std::tuple, который является членом некоторого другого шаблонного класса с переменным...

Функция с переменным числом аргументов (через шаблоны) - C++
Доброго времени суток! Встал вопрос с реализацией такой функции. template<typename... Args> returntype functionname(const Args&......

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
ForEveR
В астрале
Эксперт С++
7972 / 4734 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
11.08.2010, 20:37 #16
Evg, Букв много. Но вроде то что надо
0
Evg
Эксперт CАвтор FAQ
17801 / 6007 / 387
Регистрация: 30.03.2009
Сообщений: 16,511
Записей в блоге: 26
11.08.2010, 21:17 #17
Цитата Сообщение от Lavroff Посмотреть сообщение
Могу ответственно заявить, что автор статьи - дятел. В том плане, что эллиптические аргументы должны доставаться совсем не так, как он написал, а через интерфейсы va_arg (из stdarg.h)

Новичкам показывать эту статью строго запрещается. Понятно, что если человек всю жизнь будет работать только на intel'овской архитектуре, может быть так и можно делать, но ведь заранее никому неизвестно, как будут меняться программные соглашения по передаче параметров в будущих intel'овских процессорах. Да и незачем приучать людей к неправильным вещам
0
Mencey
147 / 94 / 7
Регистрация: 22.07.2010
Сообщений: 424
11.08.2010, 21:28 #18
Вот рабочий пример функции sum(int,...):

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
 
/* Будет складывать k аргументов после k */
int sum1(int k,...)
{
  va_list ap;
  int s = 0;
  va_start( ap, k );
  while( k-- > 0 )
    s += va_arg( ap, int );
  va_end(ap);
  return s;
}
 
/* Будет складывать аргументы пока невстретится 0(ноль) */
int sum2(int onearg,...)
{
  va_list ap;
  int s = onearg;
  int n;
  va_start( ap, onearg );
  while( n = va_arg( ap, int ) )
    s += n;
  va_end(ap);
  return s;
}
 
int main(int argc, char *argv[])
{
  int s1 = sum1( 10/*Г*ðãóìåГ*òîâ*/, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 );
  int s2 = sum2( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0/*ГЄГ®Г*ГҐГ¶*/ );
  printf( "s1 = %d; s2 = %d;\n", s1, s2 );
  system("PAUSE");
  return 0;
}
1
ForEveR
В астрале
Эксперт С++
7972 / 4734 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
11.08.2010, 21:30 #19
Evg, Суть в том, что использовать такую функцию

int foo(...) - нереально. Ибо нету конечного значения никакого. Следовательно не возможно сие сделать. Несмотря на то, что компилятор на это не ругается.

И да. Как уже писали здесь в С++0x для этого будет предназначены шаблоны с переменным числом параметров
0
Evg
Эксперт CАвтор FAQ
17801 / 6007 / 387
Регистрация: 30.03.2009
Сообщений: 16,511
Записей в блоге: 26
11.08.2010, 21:33 #20
Цитата Сообщение от Lavroff Посмотреть сообщение
Evg, Суть в том, что использовать такую функцию
int foo(...) - нереально
Именно поэтому мне хочется высказать "Фи" в адрес разработчиков Си++. Либо всё-таки какая-то потаённая возможность есть. Либо закладывались на такие архитектурно-зависимые случаи.
0
ForEveR
В астрале
Эксперт С++
7972 / 4734 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
11.08.2010, 21:54 #21
И только... Описана возможность, но ничего не сказано

Страуструп. Абстракция данных в языке С++.

Тем не менее имеется возможность вводить функции с неопределенным
и возможно переменным числом аргументов неопределенных типов,
однако такое отступление от типового контроля должно быть явно указано.
Например :


int wild ( ... );
int fprintf (FILE*, char* ...);


Многоточие определяет, что любые (или никакие) аргументы будут
приняты без контроля или преобразования точно так как в старом С.
Например :


wild (); wild ("asdf" , 10); wild (1.3, "ghjk", wild);
fprintf (stdout, "x=%d" , 10);
fprintf (stderr, "file %s line %d\n", f_name, l_no);


Заметьте, что первые два аргумента f p r i n t f должны
присутствовать и будут проконтролированы. Следует обратить
внимание однако, что функции с частично определенными типами
аргументов значительно реже используются в С++, чем в старом С
Такие функции преимущественно используются для описания интерфейсов
со старыми С-библиотеками. Вместо этого используются :
- аргументы функции по умолчанию (секция 9),
- перегрузка имен функций (секция 7),
- перегрузка знаков операций (секция 8).
0
Mencey
147 / 94 / 7
Регистрация: 22.07.2010
Сообщений: 424
11.08.2010, 22:01 #22
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
 
/* Будет складывать k аргументов после k */
int sum1(int k,...)
{
  va_list ap;
  int s = 0;
  va_start( ap, k );
  while( k-- > 0 )
    s += va_arg( ap, int );
  va_end(ap);
  return s;
}
 
/* Будет складывать аргументы пока невстретится 0(ноль) */
int sum2(int onearg,...)
{
  va_list ap;
  int s = onearg;
  int n;
  va_start( ap, onearg );
  while( n = va_arg( ap, int ) )
    s += n;
  va_end(ap);
  return s;
}
 
int main(int argc, char *argv[])
{
  int s1 = sum1( 10/*Г*ðãóìåГ*òîâ*/, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 );
  int s2 = sum2( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0/*ГЄГ®Г*ГҐГ¶*/ );
  printf( "s1 = %d; s2 = %d;\n", s1, s2 );
  system("PAUSE");
  return 0;
}
Описание:

C
1
typedef ... va_list;
va_list - Этот тип применяется для объявления локальной переменной состояния с общепринятым именем ap, используемой для передачи параметров.

C
1
#define va_start( a_list ap, type LastFixedParm)...
va_start - Этот макрос инициализирует переменную состояние ap. Его необходимо вызвать до первого вызова va_arg и va_end. В традиционном C va_start устанавливает в ap внутрений указатель на первый из передаваемых функции аргументов; в Standart C va_start содержит дополнительный параметр - имя последнего фиксированого параметра, - и устанавливает внутрений указатель в ap на первый аргумент списка переменной длины.

C
1
#define va_arg( va_list ap, type) ...
va_arg - Этот макрос возращает значение следующего параметра в списке и переводит внутрений указатель (в ap) на следующий параметр (при наличии). Должен быть указан тип этого (следующего) параметра (после обычного преобразования аргументов), чтобы va_arg мог вычислить объём, занимаемый им в стеке. При первом вызове, после вызова va_start, va_arg возращает значение первого параметра в списке переменной длины.

C
1
void va_end(va_list ap);
va_end - Эту функцию (или макрос) необходимо вызвать после считывания макросом va_arg всех аргументов. Он выполняет все необходимые обнуления переменных ap и va_alist.

C
1
void va_copy(va_list dest, va_list src);
va_copy - (C99) Этот макрос копирует текущее состояние из src в dest, создавая, тем самым, второй указатель на список аргументов. После этого va_arg можно применить, независимо, к src и dest. Макрос va_end необходимо вызвать как с src так и с dest.
0
ForEveR
В астрале
Эксперт С++
7972 / 4734 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
11.08.2010, 22:33 #23
Итак.
Никакой информации от разработчика языка по поводу использования func(...) без параметров
Страуструп. Язык программирования С++
Существуют функции, в описании которых невозможно указать число
и типы всех допустимых параметров. Тогда список формальных
параметров завершается эллипсисом (...), что означает:
"и, возможно, еще несколько аргументов". Например:

int printf(const char* ...);

При вызове printf обязательно должен быть указан параметр
типа char*, однако могут быть (а могут и не быть) еще другие
параметры. Например:

printf("Hello, world\n");
printf("My name is %s %s\n", first_name, second_name);
printf("%d + %d = %d\n", 2,3,5);

Такие функции пользуются для распознавания своих фактических
параметров недоступной транслятору информацией. В случае функции
printf первый параметр является строкой, специфицирующей формат вывода.
Она может содержать специальные символы, которые позволяют правильно
воспринять последующие параметры. Например, %s означает -"будет
фактический параметр типа char*", %d означает -"будет фактический
параметр типа int" (см. $$10.6). Но транслятор этого не знает, и
поэтому он не может убедиться, что объявленные параметры действительно
присутствуют в вызове и имеют соответствующие типы. Например,
следующий вызов

printf("My name is %s %s\n",2);

нормально транслируется, но приведет (в лучшем случае) к неожиданной
выдаче. Можете проверить сами.
Очевидно, что раз параметр неописан, то транслятор не имеет сведений
для контроля и стандартных преобразований типа этого параметра.
Поэтому char или short передаются как int, а float как double, хотя
пользователь, возможно, имел в виду другое.
В хорошо продуманной программе может потребоваться, в виде
исключения, лишь несколько функций, в которых указаны не все типы
параметров. Чтобы обойти контроль типов параметров, лучше использовать
перегрузку функций или стандартные значения параметров, чем
параметры, типы которых не были описаны. Эллипсис становится
необходимым только тогда, когда могут меняться не только типы, но
и число параметров. Чаще всего эллипсис используется
для определения интерфейса с библиотекой стандартных функций на С,
если этим функциям нет замены:

extern "C" int fprintf(FILE*, const char* ...);
extern "C" int execl(const char* ...);

Есть стандартный набор макроопределений, находящийся в <stdarg.h>,
для выбора незаданных параметров этих функций. Рассмотрим функцию
реакции на ошибку, первый параметр которой показывает степень тяжести
ошибки. За ним может следовать произвольное число строк. Нужно
составить сообщение об ошибке с учетом, что каждое слово из него
передается как отдельная строка:

extern void error(int ...)
extern char* itoa(int);

main(int argc, char* argv[])
{
switch (argc) {
case 1:
error(0,argv[0],(char*)0);
break;
case 2:
error(0,argv[0],argv[1],(char*)0);
break;
default:
error(1,argv[0],
"With",itoa(argc-1),"arguments",(char*)0);
}
// ...
}

Функция itoa возвращает строку символов, представляющую ее целый
параметр. Функцию реакции на ошибку можно определить так:

#include <stdarg.h>

void error(int severity ...)
/*
за "severity" (степень тяжести ошибки) следует
список строк, завершающийся нулем
*/
{
va_list ap;
va_start(ap,severity); // начало параметров

for (; {
char* p = va_arg(ap,char*);
if (p == 0) break;
cerr << p << ' ';
}

va_end(ap); // очистка параметров

cerr << '\n';
if (severity) exit(severity);
}

Вначале при вызове va_start() определяется и инициализируется
va_list. Параметрами макроопределения va_start являются имя типа
va_list и последний формальный параметр. Для выборки по порядку
неописанных параметров используется макроопределение va_arg().
В каждом обращении к va_arg нужно задавать тип ожидаемого фактического
параметра. В va_arg() предполагается, что параметр такого типа
присутствует в вызове, но обычно нет возможности проверить это.
Перед выходом из функции, в которой было обращение к va_start,
необходимо вызвать va_end. Причина в том, что в va_start()
могут быть такие операции со стеком, из-за которых корректный возврат
из функции становится невозможным. В va_end() устраняются все
нежелательные изменения стека.
Приведение 0 к (char*)0 необходимо потому, что sizeof(int)
не обязано совпадать с sizeof(char*). Этот пример демонстрирует
все те сложности, с которыми приходится сталкиваться
программисту, если он решил обойти контроль типов, используя
эллипсис.
Добавлено через 17 минут
Собственно вот. Линк: Тут

Функции без аргументов и с неизвестными аргументами
При описании функции, отсутствие аргументов в скобках означает, что их нет, а не что они неизвестны (как в Си). В Си++ записи f() и f(void) строго равносильны.

Если количество или типы некоторых аргументов неизвестны, надо заменить их многоточием. При этом:

хотя бы один аргумент должен быть известен (иначе откуда функция узнает количество и типы аргументов?)
Известные аргументы должны быть в начале списка
void f(); // функция без аргументов
void g(void); // тоже функция без аргументов
int printf(const char* fmt, ...); // функция с неизвестными аргументами
int sprintf(char* s, const char* fmt, ...); // ещё одна
// int bad1(...); // Неправильно! Нужен хотя бы один известный аргумент. (Стандарт позволяет, проверьте!)
// int bad2(..., char* fmt); // Неправильно! Известные аргументы должны быть в начале списка
Доступ к дополнительным аргументам такой функции в ее теле требует средств из stdarg.h

При совместном использовании нескольких функций та, что имеет многоточие в параметрах, считается хуже всех других при выборе, какую именно функцию звать (т.е. используется только тогда, когда ни одна без многоточия не подошла).
0
Evg
Эксперт CАвтор FAQ
17801 / 6007 / 387
Регистрация: 30.03.2009
Сообщений: 16,511
Записей в блоге: 26
11.08.2010, 22:35 #24
Цитата Сообщение от Lavroff Посмотреть сообщение
При совместном использовании нескольких функций та, что имеет многоточие в параметрах, считается хуже всех других при выбор
Я так понимаю, что тут речь идёт о перегрузке функций? А то с трёх прочтений не мог понять
0
ForEveR
В астрале
Эксперт С++
7972 / 4734 / 321
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
11.08.2010, 22:48 #25
Evg, Ага.
То есть как я понял:

C++
1
2
void foo(int);
void foo(int, ...);
Предпочтительнее первая

Добавлено через 10 минут
Пункт 8.3.5 под циферкой 2
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.08.2010, 22:48
Привет! Вот еще темы с ответами:

Как изменить значение переменной, переданной в списке с переменным числом аргументов - C++
Помогите!!! Начал изучать С++ Возникла такая проблема. Когда мне нужно получить доступ к переменному числу аргументов я делаю что-то...

Шаблон функции с переменным количеством аргументов - C++
Добрый вечер, мне необходимо при помощи шаблона функции реализовать поиск минимального числа(тип данных не известен, количество чисел...

Функции с переменным числом параметров - C++
#include &lt;iostream.h&gt; #include &lt;conio.h&gt; int max(int k,...) { int *p=&amp;k; int maxi; for(;k!=0;k--)

Функции с переменным числом параметров - C++
Написать функцию prost с переменным числом параметров, которая находит все простые числа из нескольких интервалов. Интервалы задаются...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
11.08.2010, 22:48
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru