|
Программирование >> Поддержка объектно-ориентированного программирования
Есть немногие ситуации и в обычных программах, когда применение goto оправдано. Одна из них -выход из вложенного цикла или переключателя. Дело в том, что оператор break во вложенных циклах или переключателях позволяет перейти только на один уровень выше. Приведем пример: void f() int i; int j; for ( i = 0; i < n; i++) for (j = 0; j<m; j++) if (nm[i][j] == a) goto found; здесь a не найдено ... found: nm[i][j] == a Есть еще оператор continue, который позволяет перейти на конец цикла. Что это значит, объяснено в $$3.1.5. 3.4 Комментарии и расположение текста Программу гораздо легче читать, и она становится намного понятнее, если разумно использовать комментарии и систематически выделять текст программы пробелами. Есть несколько способов расположения текста программы, но нет причин считать, что один из них - наилучший. Хотя у каждого свой вкус. То же можно сказать и о комментариях. Однако можно заполнить программу такими комментариями, что читать и понимать ее будет только труднее. Транслятор не в силах понять комментарий, поэтому он не может убедиться в том, что комментарий: [1 ] осмысленный, [2] действительно описывает программу, [3] не устарел. Во многих программах попадаются непостижимые, двусмысленные и просто неверные комментарии. Лучше вообще обходиться без них, чем давать такие комментарии. Если некий факт можно прямо выразить в языке, то так и следует делать, и не надо считать, что достаточно упомянуть его в комментарии. Последнее замечание относится к комментариям, подобным приведенным ниже: переменную v необходимо инициализировать. переменная v может использоваться только в функции f() . до вызова любой функции из этого файла необходимо вызвать функцию init() . в конце своей программы вызовите функцию cleanup() . не используйте функцию weird() . функция f() имеет два параметра. При правильном программировании на С++ такие комментарии обычно оказываются излишними. Чтобы именно эти комментарии стали ненужными, можно воспользоваться правилами связывания ($$4.2) и областей видимости, а также правилами инициализации и уничтожения объектов класса ($$5.5). Если некоторое утверждение выражается самой программой, не нужно повторять его в комментарии. Например: a = b + c; a принимает значение b+c count++; увеличим счетчик count Такие комментарии хуже, чем избыточные. Они раздувают объем текста, затуманивают программу и могут быть даже ложными. В то же время комментарии именно такого рода используют для примеров в учебниках по языкам программирования, подобных этой книге. Это одна из многих причин, по которой учебная программа отличается от настоящей. Можно рекомендовать такой стиль введения комментариев в программу: [1 ] начинать с комментария каждый файл программы: указать в общих чертах, что в ней определяется, дать ссылки на справочные руководства, общие идеи по сопровождению программы и т.д.; [2] снабжать комментарием каждое определение класса или шаблона типа; [3] комментировать каждую нетривиальную функцию, указав: ее назначение, используемый алгоритм (если только он неочевиден) и, возможно, предположения об окружении, в котором работает функция; [4] комментировать определение каждой глобальной переменной; [5] давать некоторое число комментариев в тех местах, где алгоритм неочевиден или непереносим; [6] больше практически ничего. Приведем пример: tbl.c: Реализация таблицы имен. Использован метод Гаусса см. Ральстон Начальный курс по ... стр. 411. в swap() предполагается, что стек AT&T начинается с 3B20. /************************************ Авторские права (c) 1991 AT&T, Inc Все права сохранены **************************************/ Правильно подобранные и хорошо составленные комментарии играют в программе важную роль. Написать хорошие комментарии не менее трудно, чем саму программу, и это - искусство, в котором стоит совершенствоваться. Заметим, что если в функции используются только комментарии вида , то любую ее часть можно сделать комментарием с помощью /* */, и наоборот. 3.5 Упражнения 1 . (*1 ) Следующий цикл for перепишите с помощью оператора while: for (i=0; i<max length; if (input line[i] == ?) quest count++; Запишите цикл, используя в качестве его управляющей переменной указатель так, чтобы условие имело вид *p==?. 2. Укажите порядок вычисления следующих выражений, задав полную скобочную структуру: a = b + c * d << 2 & 8 a & 077 != 3 a == b a == c && c < 5 c = x != 0 0 <= i < 7 f(1,2) + 3 a = - 1 + + b -- - 5 a = b == c ++ a = b = c = 0 a[4][2] *= * b ? c : * d * 2 a-b, c=d Каков может быть смысл этой функции? 11 . (*2) Напишите функцию atoi(), которая имеет параметр - строку цифр и возвращает соответствующее ей целое. Например, atoi( 1 23 ) равно 1 23. Измените функцию atoi() так, чтобы она могла переводить в число последовательность цифр не только в десятичной, но и в восьмеричной и шестнадцатеричной записи, принятой в С++. Добавьте возможность перевода символьных констант С++. Напишите функцию itoa() для перевода целого значения в строковое представление. 12. (*2) Перепишите функцию get token() ($$3.12) так, чтобы она читала целую строку в буфер, а затем 3. (*2) Укажите 5 различных конструкций на С++, значение которых неопределено. 4. (*2) Приведите 1 0 разных примеров непереносимых конструкций на С++. 5. (*1 ) Что произойдет при делении на нуль в вашей программе на С++? Что будет в случае переполнения или потери значимости? 6. Укажите порядок вычисления следующих выражений, задав их полную скобочную структуру: *p++ *-- p ++a-- (int*)p->m *p.m *a[i] 7. (*2) Напишите такие функции: strlen() - подсчет длины строки, strcpy() - копирование строк и strcmp() - сравнение строк. Какими должны быть типы параметров и результатов функций? Сравните их со стандартными версиями, имеющимися в <string.h> и в вашем руководстве. 8. Выясните, как ваш транслятор отреагирует на такие ошибки: void f(int a, int b) if (a = 3) ... if (a&077 == 0) ... a := b+1; Посмотрите, какова будет реакция на более простые ошибки. 9. (*2) Напишите функцию cat(), которая получает два параметра-строки и возвращает строку, являющуюся их конкатенацией. Для результирующей строки используйте память, отведенную с помощью new. Напишите функцию rev() для перевертывания строки, переданной ей в качестве параметра. Это означает, что после вызова rev(p) последний символ p станет первым и т.д. 1 0. (*2) Что делает следующая функция? void send(register* to, register* from, register count) Псевдоустройство. Все комментарии сознательно удалены register n=(count+7)/8; switch (count%8) { case 0: do { *to++ = *from++; case 7: *to++ = *from++; case 6: *to++ = *from++; case 5: *to++ = *from++; case 4: *to++ = *from++; case 3: *to++ = *from++; case 2: *to++ = *from++; case 1: *to++ = *from++; } while (--n>0);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |