Главная » Просмотр файлов » Б. Страуструп - Язык программирования С++

Б. Страуструп - Язык программирования С++ (1119446), страница 35

Файл №1119446 Б. Страуструп - Язык программирования С++ (Б. Страуструп - Язык программирования С++) 35 страницаБ. Страуструп - Язык программирования С++ (1119446) страница 352019-05-09СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 35)

Она может содержать специальные символы, которые позволяют правильно воспринятьпоследующие параметры. Например, %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:114Бьерн Страуструп.Язык программирования С++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*). Этотпример демонстрирует все те сложности, с которыми приходится сталкиваться программисту, если онрешил обойти контроль типов, используя эллипсис.4.6.9 Указатель на функциюВозможны только две операции с функциями: вызов и взятие адреса. Указатель, полученный спомощью последней операции, можно впоследствии использовать для вызова функции.

Например:void error(char* p) { /* ... */ }void (*efct)(char*);// указатель на функциюvoid f(){efct = &error;// efct настроен на функцию error(*efct)("error");// вызов error через указатель efct}Для вызова функции с помощью указателя (efct в нашем примере) надо вначале применить операциюкосвенности к указателю - *efct. Поскольку приоритет операции вызова () выше, чем приоритеткосвенности *, нельзя писать просто *efct("error"). Это будет означать *(efct("error")), что являетсяошибкой. По той же причине скобки нужны и при описании указателя на функцию. Однако, писатьпросто efct("error") можно, т.к. транслятор понимает, что efct является указателем на функцию, исоздает команды, делающие вызов нужной функции.Отметим, что формальные параметры в указателях на функцию описываются так же, как и в обычных115Бьерн Страуструп.Язык программирования С++функциях.

При присваивании указателю на функцию требуется точное соответствие типа функции итипа присваиваемого значения. Например:void (*pf)(char*);void f1(char*);int f2(char*);void f3(int*);void f(){pf = &f1;pf = &f2;pf = &f3;(*pf)("asdf");(*pf)(1);int i = (*pf)("qwer");////////указатель на void(char*)void(char*);int(char*);void(int*);//////////////нормальноошибка: не тот тип возвращаемогозначенияошибка: не тот тип параметранормальноошибка: не тот тип параметраошибка: void присваивается int}Правила передачи параметров одинаковы и для обычного вызова, и для вызова с помощью указателя.Часто бывает удобнее обозначить тип указателя на функцию именем, чем все время использоватьдостаточно сложную запись. Например:typedef int (*SIG_TYP)(int);// из <signal.h>typedef void (SIG_ARG_TYP)(int);SIG_TYP signal(int, SIG_ARG_TYP);Также часто бывает полезен массив указателей на функции. Например, можно реализовать системуменю для редактора с вводом, управляемым мышью, используя массив указателей на функции,реализующие команды.

Здесь нет возможности подробно описать такой редактор, но дадим самыйобщий его набросок:typedef void (*PF)();PF edit_ops[] = { // команды редактора&cut, &paste, &snarf, &search};PF file_ops[] = { // управление файлом&open, &reshape, &close, &write};Далее надо определить и инициализировать указатели, с помощью которых будут запускаться функции,реализующие выбранные из меню команды. Выбор происходит нажатием клавиши мыши:PF* button2 = edit_ops;PF* button3 = file_ops;Для настоящей программы редактора надо определить большее число объектов, чтобы описать каждуюпозицию в меню. Например, необходимо где-то хранить строку, задающую текст, который будетвыдаваться для каждой позиции. При работе с системой меню назначение клавиш мыши будет постоянноменяться.

Частично эти изменения можно представить как изменения значений указателя, связанного сданной клавишей. Если пользователь выбрал позицию меню, которая определяется, например, как позиция 3для клавиши 2, то соответствующая команда реализуется вызовом:(*button2[3])();Чтобы полностью оценить мощность конструкции указатель на функцию, стоит попытаться написатьпрограмму без нее. Меню можно изменять в динамике, если добавлять новые функции в таблицукоманд.Довольно просто создавать в динамике и новые меню.Указатели на функции помогают реализовать полиморфические подпрограммы, т.е.

такие подпрограммы,которые можно применять к объектам различных типов:typedef int (*CFT)(void*,void*);void sort(void* base, unsigned n, unsigned int sz, CFT cmp)116Бьерн Страуструп.Язык программирования С++/*Сортировка вектора "base" из n элементовв возрастающем порядке;используется функция сравнения, на которую указывает cmp.Размер элементов равен "sz".Алгоритм очень неэффективный: сортировка пузырьковым методом*/{for (int i=0; i<n-1; i++)for (int j=n-1; i<j; j--) {char* pj = (char*)base+j*sz;char* pj1 = pj - sz;if ((*cmp)(pj,pj1) < 0) {// поменять местами b[j] иfor (int k = 0; k<sz; k++)char temp = pj[k];pj[k] = pj1[k];pj1[k] = temp;}}}// b[j]// b[j-1]b[j-1]{}В подпрограмме sort неизвестен тип сортируемых объектов; известно только их число (размермассива), размер каждого элемента и функция, которая может сравнивать объекты.

Мы выбрали дляфункции sort() такой же заголовок, как у qsort() - стандартной функции сортировки из библиотеки С. Этуфункцию используют настоящие программы. Покажем, как с помощью sort() можно отсортироватьтаблицу с такой структурой:struct user {char* name;// имяchar* id;// парольint dept;// отдел};typedef user* Puser;user heads[] = {"Ritchie D.M.","dmr","Sethi R.","ravi","SZYmanski T.G.","tgs","Schryer N.L.","nls","Schryer N.L.","nls","Kernighan B.W.","bwk",};void print_id(Puser v, int n){for (int i=0; i<n; i++)cout << v[i].name << '\t'<< v[i].id << '\t'<< v[i].dept << '\n';}11271,11272,11273,11274,1127511276Чтобы иметь возможность сортировать, нужно вначале определить подходящие функции сравнения.Функция сравнения должна возвращать отрицательное число, если ее первый параметр меньшевторого, нуль, если они равны, и положительное число в противном случае:int cmp1(const void* p, const void* q)// сравнение строк, содержащих имена{return strcmp(Puser(p)->name, Puser(q)->name);}int cmp2(const void* p, const void* q)117Бьерн Страуструп.Язык программирования С++// сравнение номеров разделов{return Puser(p)->dept - Puser(q)->dept;}Следующая программа сортирует и печатает результат:int main(){sort(heads,6,sizeof(user), cmp1);print_id(heads,6);// в алфавитном порядкеcout << "\n";sort(heads,6,sizeof(user),cmp2);print_id(heads,6);// по номерам отделов}Допустима операция взятия адреса и для функции-подстановки, и для перегруженной функции($$R.13.3).Отметим, что неявное преобразование указателя на что-то в указатель типа void* не выполняется дляпараметра функции, вызываемой через указатель на нее.

Поэтому функциюint cmp3(const mytype*, const mytype*);нельзя использовать в качестве параметра для sort(). Поступив иначе, мы нарушаем заданное вописании условие, что cmp3() должна вызываться с параметрами типа mytype*. Если вы специальнохотите нарушить это условие, то должны использовать явное преобразование типа.4.7 МакросредстваМакросредства языка определяются в $$R.16. В С++ они играют гораздо меньшую роль, чем в С.Можно даже дать такой совет: используйте макроопределения только тогда, когда не можете без нихобойтись. Вообще говоря, считается, что практически каждое появление макроимени являетсясвидетельством некоторых недостатков языка, программы или программиста.

Характеристики

Список файлов книги

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6361
Авторов
на СтудИзбе
310
Средний доход
с одного платного файла
Обучение Подробнее