|
Программирование >> Формирование пользовательского контейнера
178 ; Главам Цикл foreach транслируется в приведенный далее код на языке С++. int ia = 0; for(double V = nums[0]; ia < {{sizeof nums)/(sizeof nums[0])); ia++, V = nums[ ia]) sum += v; Прежде всего, обратите внимание на то, что цикл for нуждается в управляющей переменной цикла, в нашем случае названной ia, но такой переменной нет в цикле foreach. Напоминаю, что переменная, объявленная в цикле foreach, в данном случае v, получает значения элементов массива. Она не является счетчиком цикла. Следовательно, управляющую переменную цикла надо создать. Она не может быть объявлена внутри цикла, так как ее нужно сохранить для объявления v - переменной цикла foreach, локальной в цикле for. Это требует формирования уникального имени переменной типа int, которое не будет конфликтовать с другими переменными, используемыми в их области видимости. Кроме того, в цикле for должны обрабатываться все элементы массива (в данном случае nums), но размер массива не задан в цикле foreach. Это значит, что количество элементов массива нужно вычислить. К счастью, это можно сделать с помощью операции sizeof, которая вскоре будет описана. Теперь давайте рассмотрим каждый шаг процесса трансляции. Преобразование цикла foreach начинается с создания уникальной (будем надеяться) переменной, которая будет использоваться как управляющая переменная цикла for. Имя ее начинается с символьной комбинации i, к которой добавляется буква из диапазона от а до z. Первая создаваемая в файле управляющая переменная называется ia, вторая - ib и т. д. Можно создать до 26 подобных переменных. Это не лучший способ формирования бесконфликтных имен переменных, но достаточно простой и удовлетворяющий потребности эксперимента с циклом foreach. Управляющая переменная получает тип int и ее объявление записывается в выходной файл. Затем с записи forC в выходной файл начинается цикл for. Далее конструируется инициализирующая часть цикла. Сначала тип и имя переменной цикла foreach считываются и копируются в выходной файл. Затем ключевое слово in читается и отбрасывается. Потом имя массива читается и используется для инициализации, в результате которой переменной цикла foreach присваивается значение первого элемента массива. Далее формируется часть цикла, содержащая условное выражение. В этой секции управляющая переменная цикла сравнивается со значением, равным количеству элементов массива. Последнее вычисляется с помощью деления размера массива на размер отдельного его элемента. Это действие необходим- потому что операция sizeof возвращает размер занимаемой массивом области ттамяти в байтах, а не количество его элементов. В конце создается секция итерации или тело цикла for. В ней значение переменной цикла увеличивается на единицу с помощью операции инкремента и переменной цикла foreach присваивается значение следующего элемента массива. Перед заверщением функции foreach о проводится проверка того, что цикл foreach заканчивается символом ) . Последнее замечание: в языке С* цикл foreach может применяться к массивам и коллекциям (которые больше похожи на контейнеры библиотеки STL). Для простоты предлагаемая версия цикла будет обрабатывать только массивы, но вы можете адаптировать ее для обработки в цикле STL-контейнеров. Трансляция оператора cases Как уже объяснялось ранее, оператор cases представляет собой односекци-онную альтернативу описанию серии стопочных case-операторов. Он транслируется функцией cases (), приведенной далее. Транслирует оператор cases, void cases О { string token; int start, end; skipspaces(); Получает начальное значение, gettoken(token); if(isdigit(token[0])) { получена константа int start = atoi(token.c str()); else if {token[0] == Л ) { получена константа char gettoken(token); start = (int) token[0]; Отбрасывает закрывающий (апостроф) gettoken(token); if (token [0] != -X ) throw SyntaxExcC expected in cases. ); else throw SyntaxExc( Constant expected in cases. ); skipspaces(); Читает и отбрасьшет to , gettoken(token); if(token != to ) throw SyntaxExc( to expected in cases. ); skipspaces(); Получает конечное значение. gettoken(token); if (isdigit(token [0])) { Получена константа int end = atoi(token.c str()); else if (token[0] == *V) { Получена константа char gettoken(token); end = (int) token[0]; Отбрасывает закрывающий gettoken(token); if(token[0] != X- ) throw SyntaxExc( eзфected in cases . ) ; else throw SyntaxExc( Constant expected in cases. ) . skipspaces{); Читает и отбрасывает : gettoken(token);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |