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 |
#include <stdlib.h> #include <iostream.h> #include <stdarg.h> void OK(char *format, ...) //Функция OK с произвольным числом параметров { va_list ap; //Указатель на список параметров va_start(ap,format); //Настроились на список параметров for (char *p=format;*p;p++) // { if (*p=='%') //Если встретится символ % { switch (*++p) //То анализируем следующий за этим симолом символ { case 'd': int ival=va_arg(ap,int); //Если это символ d, то значит параметр int cout << ival << " "; //Выводим параметр типа int на экран break; case 'f': double dval = va_arg(ap,double); //Если это символ f значит параметр double cout << dval << " "; //Выводим параметр типа double на экран break; } } else cout << *p << " "; } va_end(ap); //Завершаем работу с макрокомандами } int main() { system("CLS"); OK("%d%f", 8, 9.555); //Вывод двух чисел с разными типами cin.get(); } |
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 |
//Visual Studio Express 2012 #include <iostream> #include <stdarg.h> using namespace std; void OK(char *format, ...) //Функция OK с произвольным числом параметров { int ival; double dval; va_list ap; //Указатель на список параметров va_start(ap,format); //Настроились на список параметров for (char *p=format;*p;p++) // { if (*p=='%') //Если встретится символ % { switch (*++p) //То анализируем следующий за этим симолом символ { case 'd': ival=va_arg(ap,int); //Если это символ d, то значит параметр int cout<<ival<<" ";break; //Выводим параметр типа int на экран case 'f': dval=va_arg(ap,double); //Если это символ f значит параметр double cout<<dval<<" ";break; //Выводим параметр типа double на экран } } else cout<<*p<<" "; } va_end(ap); //Завершаем работу с макрокомандами } int main() { system("CLS"); OK("%d%f",8,9.555); //Вывод двух чисел с разными типами system("PAUSE"); |
===================================
Код С++. НЕ РЕКОМЕНДУЕТСЯ. Может работать и правильно, и неправильно: зависит от компилятора и от компьютера, на котором выполняется программа.
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 |
#include <iostream.h> #include <stdlib.h> void MyFunc(int a,...) //Так объявляется функция с заранее неизвестным числом параметров { //Borland C++ 3.1 #include <iostream.h> #include <stdlib.h> void MyFunc(int a,...) //Так объявляется функция с заранее неизвестным числом параметров { int *P=&a; //Взятие адреса у первого параметра while (*P) //Пока встречаются параметры и параметр не равен 0 { cout << *P << " "; //Вытаскиваем значение с адреса по которому живет параметр P++; //Адресная арифметика. Смена текущего адреса на следующий } } int main() { system("CLS"); MyFunc(100,200,300,400,0); //В функцию передается 4 параметра и пятый как идентификатор того, что параметры кончились system("PAUSE"); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//НИКОГДА, НИКОГДА ТАК НЕ ДЕЛАЙТЕ!!! #include <iostream.h> #include <stdlib.h> void MyFunc(int a,...) //Так объявляется функция с заранее неизвестным числом параметров { int *P = &a; //Взятие адреса у первого параметра long sum = 0; //Инициализация значения суммы в ноль while (*P) //Пока встречаются параметры и параметр не равен 0 { sum = sum + (*P); //Прибавляем к сумме то что взяли по адресу P P++; //Адресная арифметика. Смена текущего адреса на следующий } cout << sum << endl; //Вывод результата на экран } int main() { system("CLS"); MyFunc(100.0,200.0,300.0,400.0,0.0); //В функцию передается 4 параметра и пятый как идентификатор того, что параметры кончились system("PAUSE"); } |
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 |
//НИКОГДА, НИКОГДА ТАК НЕ ДЕЛАЙТЕ!!! //Если сработал предыдущий код, не факт, что этот сработает правильно #include <iostream.h> #include <stdlib.h> void MyFunc(double a,...) //Так объявляется функция с заранее неизвестным числом параметров { double *P = &a; //Взятие адреса у первого параметра double sum = 0; //Инициализация значения суммы в ноль while (*P) //Пока встречаются параметры и параметр не равен 0 { sum = sum + (*P); //Прибавляем к сумме то что взяли по адресу P P++; //Адресная арифметика. Смена текущего адреса на следующий } cout << sum << endl; //Вывод результата на экран } int main() { system("CLS"); MyFunc(10.0,15.0); //В функцию передается 4 параметра и пятый как идентификатор того, что параметры кончились system("PAUSE"); } |
Чётко, чётко
😆
😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆 😆
target pattern contains no «%» stop
выскакивает эта ошибка и не работает задача, подскажите плиз как этого миновать, плиз 😥
А к какому из листингов?
и если у вас не Windows , я не смогу ничем помочь. Даже если Windows и компиляторы как у меня, то я не знаю в чем может быть проблема. Возможно переписывали и где-то что-то не дописали.
Перед публикацией я проверял работу в Win7
вот это может быть сможет помочь
http://technorecipes.blogspot.ru/2011/10/cmakemake-windows-target-pattern.html
как мне подставить формулу
S = a1 * a2 + a2 * a3 + a3 * a4 + . . .;
допусутим для 5 переменных
s + = (*p)*(*p) — не катит((
Это обязательно через такую функцию делать?
Если я знаю ответ, то завтра отвечу. Если не знаю ответа, то завтра скажу, что не знаю.
Могу только предположить, что в месте вызова функции, прописывать можно что-то типа
ну и смотреть пример с суммой.
но не могу сказать, что это вообще работать будет, проверить не могу.
Не в описании функции, а там, откуда ее вызываем.
или же
как-то так (проверить не могу)
проверил
но работает это в Borland C++ 3.1, в Linux же, например, весь этот алгоритм сам по себе ошибка. Правильнее было бы использовать код подобно коду из последнего примера.
У меня вопрос — и он на праздный вот такой — 😈 👿 — сам я знаток языка, использую эти вот штуки. но вот теперь на си++ обнаружил что обязательного параметра может и не быть — а это тот самый случай который мне нужен. у меня конструктор, и сразу можно подцепить к обьекту связанные с ним штуки(ну это обьект со штуками такой, вы меня понимаете) т.е. передаются указатели, замыкает ноль — конец списка.и синтаксичестки правильно и компилятор разделяет мою точку зрения, да вот незадача то 🙁 🙁 👿 😡 😥 😥 😥 😥 раз нет первого параметра — ЧЕМ мне бедолаге горемычному инициализировать указатель тот волшебный??? Липман молчит ка рыба об лёд, а у Интернета я только начал интересоваться и забрёл на ваш сайт.
Сам я совсем не знаток языка и не использую такие штуки, поэтому мне немного забавна ситуация с обращением ко мне за советом от знатока.
Если вы знаток, то должны знать, что на компилятор надеяться глупо. Он многое допускает, но не все, что он допускает будет впоследствии работать и не все допустимые конструкции получится использовать.
Если бы я встретил способ, о котором вы спрашиваете, то я бы описал его еще до вашего вопроса.
Но способа такого, насколько я знаю, нет.
Должна быть точка отсчета. Точка отсчета узнается по первому параметру.
Грубо говоря, когда компилятор работает, чтобы запустить программу, для каждой найденной функции он выделяет какую-то область памяти, а также для каждой переменной по функции тоже выделяется память. Первый такой адрес по переменной для функции как раз и будет точкой отсчета.
Зачем компилятор допускает что-то типа void myfunc(…) я понятия не имею.
в си++ можно переопределять функции для разных списков типов входных данных(включая пустой), т.е. можно описать функцию с одним именем, но принимающую разные типы параметры и в зависимости от того от чего она будет вызываться в коде будет вызвана нужная.
если это имеет отношение к функциям вида myfunc(…), я бы очень хотел увидеть пример. это сложно найти.
===================
по поводу претензий и сегменташин фолт — я всего лишь заимствовал коды из других источников и собрал их сюда. Так как они написаны в разных книгах и на разных форумах, авторов я указывать не стал. (я не знаю истинного автора) но исправлю
этот прототип(как и любой другой) говорит транслятору только то, что для функции (будь она от void или с переменным списком параметров) к моменту раскрытия ссылок на тело, это тело будет где-то существовать и он может смело продолжать формировать объектник.
а поконкретнее? я ж не компилятор
прототип прототипом, я спрашивал не про прототип, а про функцию с телом.
вопрос, который мне задали, куда вы далее вписали и свой комментарий с пояснением — это вопрос о таких функциях. Зачем допускается возможность?
не допускается, компилятор выдаст ошибку.
прототип возможно в некоторых компиляторах и пройдёт.
CodeBlock MinGW пропускает без предупреждений и ошибок.
Именно функцию с телом.
а во большинстве листингах ошибки, функция контролирует конец списка параметров по нулю в конце, а вызывая функцию этот самый ноль в конец не добавляете, в итоге привет сегменташин фолт.
также, шагая по списку параметров нельзя просто прибавлять размер параметра, так как некоторые типы при засовывании в стек расширяются, например на 32битных системах обычно при засовывании short и char расширяются до int т.е. записываются в стек 4 байта. так что для чтения параметров нужно пользоваться макросом va_arg(list,type), а не прибавлять размер предыдущего считанного параметра.
Админ вот решение которое в большинстве компиляторах работает:
А вот еще вопрос: Если мы пройдемся по указателю то почему будет не 5 3 9 1 7 0,а 5 0 3 0 9 0 1 0 7 0 0 почему так?
почему при перенаправке адреса следуещее значение 0,а не числа в аргументе функции?
Потому что в Вашем компиляторе это не работает и выводится мусор.
Такое решение не нужно использовать.
Тем не менее его можно встречать, но нужно понимать, что оно непереносимое и как решение на С++ — плохое.
Хорошо буду использовать va_list