Искусство программирования на Си (984073), страница 31
Текст из файла (страница 31)
Даже если вы объявляете, что в ф>нкцию ОВрЕВ ).([л[Е (прслполагается, что этот размер сообпоэтому было бы лсгколпясленно нс использовать их Однако фактом осзастся и то, что многие профсссио- передастся массив, компилятор внутренне преобразует щастся см> каждый раз с помощью какого-нибуль полтам, ~лс это возможно. (Если нс >твери дастся иное, нальные С-программисты плохо разбиракзтся в масси- синтаксис массива в синтаксис указателя. Тем не менее, холяшсго определения 1урег)еГ) и поскольку он знает слово обьект в данной главе означает, как зто опрсдс- вах и, слеловательно, нс могут в полной леере исполь- обшепринято говорить о "псрслаче массива в фл'нлцию .
базовый адрес массива, он может вычислить адрес лю 41лс1обе <вьб1гЬ Ь> l* ... I гесигп О ) ( Ьоабгля[АОа)[вевбег) = Са1съоаб)пв(лче, ' Селбег); ) ) ) Мы нс можем этого лапать, так как только по информации, прсдоставлсннои функции роев[а(еЕоаб)пплггауО, компилятор нс люжст установить, как лы всадить адрсса элсмснтов массива. Можно сделать это самостоятсль- но, используя запись с указателями чоьб Рорп1вгеьоабглдлггау(бопвзе **Ьоаб1ле, а)ге с махача, в1га Г Ивмсепбегв) ( вггв Г Ачв, Свпбег; (ог(АЧе = О) Аяе < НахАОа; Ача+с) ( (ог(свлбег = О; Сепбвг < ИвмСепбегв Сепбег++) ) Авллт 1ит 4 б) гас ВпмЛггау(ЛВААТ 1вт 4 б *); звс ва)п(чо1б) Айхат 1ИТ 4 б Аггау ( ( 1, 2, 3, 4, 5, б ), ) )' гвс Тоса1. тога1 = Бшалггау(алггау); рг1лс1( Тоса1 гв абхп , Тоса1) копирчго и вставляю лнсшний цикл во внутренний и прн этолс забываю обновить асс элсмснзы опсратора управлсния циклом. Сох(х = О; 1 < ОЦТЕйс 1++) = О; З < 1ИИЕВ) 14+) ( Гога1 += аггау[1.)[)); ) ) Такая нроблсма будст возникать рсжс, соли использовать имсюшис сл<ьюл имсна счстчиков циклов, так как в этом случас возможная ошибка будст, очсвидно, болсс заметной.
р(-мерные массивы фиксированного размера Двух измсрсний лостаточно для >довлстсюрсния почти всех потрсбностсй. Даже в трсхмсрных (3[у) трафичсских программах мы ножам записать координаты вершин Прастыс абстрантаас с.трунтурт даниил Глава 11 случае возможности прсдосзавляются нс только для создания гибких, удобных и полезных программ, но, увы, такжс и для совсршсния ошибок. Здссь булут рассмотрсны методы, позволяюшис рсазизовывать массивы псрсмснного размсра бсзонасно и надсжно. Одномерные массивы переменного размера Олномсрныс массивы переменного размсра созлаются на самом дслс просто. Если вам зрсбустся массив из )4 объскзов типа Т, то вот как это дсластся: т р) р = аа11ос(И " взгео( *р)) 11(р )= ИСЬЬ) сн теперь у вас есть массив, и мм моием записмвать в ваго ив(сормапив *с' Г!ратин ибгтрактнна стррктзри данник Глава 11 ргхпег( упеа1 ла Лд(п', гоеа11 Ггее(аггау); 1 Ор~анияаиияданник Часть и Изменение размеров массива — это очень полезная каждого элемента массива (если, конечно, ляы нс зала- 1ог(х = О; х < голо л++1 возможность, которая может припать нашим програм- дим той *), поэтоляу нам не придется задавать его.
Наш Гог(1 = О; ] < со1! 1++1 мам гораздо большую гибкость. последний (см. выше) эксперимент с программой аггау[11[11 1 + ]; !'я ОбраяваВЕ К Каееаау Я/ Однако не следует забывать, что после окончания Рорц[агеЕоа![[пйАггауО достаточно хорошо иллюстрируработы с массивом необходимо в соответствующий мо- ет этот метод адресации, так что не будем повторно мсяп освободить выделенную для него память. приводить здесь этот код.
Гоеа1 += аггау[х1[]11 Изменение размеров такого массива — пело ловольДвумерные массивы пеоеменного размера но хитрое, так как приход!пел осуществлять сложныс Вот где работа с массивами сзановится действительно манипуляшяи с данными. если мы нс хотим потерять увлекагсльной! Я могу без предварительной подготов- информацию. которая уже хранится в массиве.
кн создать массив М * [я[ объектов типа Т тремя различ- Во втором методе, так же как и в первом, для масгегпгп О; ными способами. В примере кода программы использо- сина выделяется слиный блок памяти. Олнако на этот вазся тип [пг, но можно заменить сто любым другим раз блок булет больше — мы запрашиваем лополнительтя!пом данных.
ную память для М указателей на объекты Т, и общий Как вилим на гнила фхнкцни Айоса!еО оказ»ва ва Можно довольно легко изменизь размлры блока но Первый из этих трех методов трсбус! меньше всего объем требуемой памяти оказывается равныл! ется довольно внушительной. Кроме того, как для мас- при этом прилстся весьма сложным образом пересылать памяти, но обеспечивает относительно медленный до- мгео[ (Т) * М * [х[ + МгеоГ (Т и) * М. Первые сива персляенного размера, нс так-то просто изменить в памяти данные массива. В листинге !1.3 показан код ступ к элементал! массива. Идея метода заключается в ыгеоГ(Т *) * М байтов мы резервируем лля совокупно- его размер! Его я!ажно изменить. но лля этого нсобхо- программы, или!сияющей размеры блока. Обратите вниилгитации массива фиксированного размера Выделяем сти указателей на тело основного массива, что позволяет дим обслуживавший код, сохраняющий данные масси- мание на то, ято следует сообщить фунлцни как старый зьзеоГ(Т) * М ' [л[ байтов и к отдельному элементу мас- использовать запись А [х] [у].
Это менее очевидно, поразмгр массива так и новыи Организи ион сдан ног Прис т и с и >страстно< сни>ун тури донни Часть й Глава 11 Можно попробовать модифицировать эту функцию Листинг 11.4. Двувгерный массив переменного для иллюстрации вышсс а ' ии вышесказанного напшпсм про- так, чтобы она сохраняла л>аксимачьное количество лан- размера. /* Заполаеаве яассвва '/ грамму, которая будет делать имс лать именно это — считывать ных исходного массива. Но я нс булу этого делать.
Еог(л = Оз в память текстовый файл. Прелположим, > жим, что тскстовыи о л ать О>вс1вде <яг>(зо ь> О, ' < со1; 1++) ела ст ок текста, отлслсн- В третьем методе используется такой же объем па- $1вс1иее <яед11ь.ь> Еог(1 = ; 1 ' 1 фаил состоит из Разумного чн >а с р мяти, как и во втором. однако не требуется, чтобы пааггау(з)(З) — > + 1> оламн новои ст оки (Хп ) Это /н Обраяевяе к массиву "/ >вол пс снопа строки (ска- мяТь была выделена однил> целыл> блоком.
кроме того, гуредее Еог(г = О. 1 < гов; з++) может соответствовать символу перевода с р ( этот метод облегчает изменение размеров массива. жом, в системс ())Ч(Х), символУ воз Р Р символ во>в ага каосткн (на Сначала мы выделяем блок памяти для размещения иозд йе1ееяе(У "а, язге Г в! ) гога) л= ау(1)(1)> компьк>тирах Мас(пгоьб), комбинации эти д у б а> ии этих дв х симво- М указателей на дачшые типа Т. Затем в цикле прохолим илге е йое> лов (00Б/%>пс(влил) или >ему нибуль совершенно ино этот массив и на каждом этапе цикла выделяем блок пав>.ге Е йое, ( ° ° , 1 ггвг( ( тгоеа1 ля Лдув, еога1) ) л>у. Нет никакой необходимости писать д, пи ть зя этого код, йе1еаяе(аггау, гов); файл в геке~оном рсжимс, мяти, лостаточный для размещения )л) объектов типа Т. Еог(йоя = О; йоя < в; вове+) ) так как, котла мы открь>наем файл в т кс Это означает, что мы больше не можем освобожлать станлартная библиотека выполни ыполнит всю нсобхолимую память за один вызов.
Необходимо в цикле проходить ЕЕ(а(йоо) (= йОЬМ гееьгв О; трансляцию. Единственным уело> м слоеном является то, что массив указателей, освобо>кдая память, занимаемую ( Егее(а(йов))> с)Л>рмат тексзового файла дслжен б Р олжен быть олным лля той каждым элементом, а затем освобождать память, зани- опсрацноннои системы в которо > ул кото ой б лет выполняться маемую самим массивом указателей. (Можно написать Такая гибкость исключи эта программа .зючителы>о попс>на — особенно прог>ую Функцию, которая будет выподнять эз-у з Егее; возможность иметь стРоки Разной,элины. Например* Начнс с ф нк й я ма ва ок.
(Полный код чу.) С друтой стороны, если используются очень боль- бы мы писали программу текстового Редактор~, ™ лн га ().б находится на >усЬ-санте излательства шие массивы, можно особенно не волноватьс отн можно бьшо бы считывать в п ' Ф диаСофт и солержит операторы в Р амять всеь файл леликом клк>чсния и леото я ос>н е **А11осаее(в1ге е в, ягге е в) //рек тне абстрактные структуры ааннык Глава 11 РгееаггАггау(Аггау, Ишздовв) Аггау = ИОЬЬ; > Часть И (*Аггаурсг)[дов) = ва11ос(1п1СИ>ПЬА); ( е р , 11 наста Рсгссаом) с= ИОЬЬ) заве Г Вов; /* Бслв любая аз опералвв внутренаего ввделенвя памятв заверватся аварааво, следует н1зе т Ьел; вмполавть очвстку.
'10'; 1аг Илвраг1огез = 0' (*Аггаурсг)[доы)[0) >У(1 >а Бпссевз) (И = 0; Вов < И вдова> Пан++) ( е1зе ( ( /' Болл эта баблнотека попользовалась Блссезя = 0; праввльао, то аа одна указатель аа строку > не долвен вметь заачеаве ИОЬЬ, поэтому нмевво так вам в следует полагать. ) */ е1не аввегг(аггаургг[аом) [а ИОЬЬ); геенно Актау; ( 0; Ьеа = 1 + вгг1ел(Аггаургг[дон))> > Бпссевз 0; 1((О == Иезгзеплеагг1пч(аггаургг, Аов, > ьеп>) гегогп Бпссевз; Если вся память полностью нс может быть вытслс- гесогл Бпссеян; ) +уипвгаг1аген> на, то программа выполняет сс очистку (вызывая фун> и ко с имеется два интересных момента.
поэтом коде имс кцию Егеео(ГАгтауо) и возврашаст значение Х()[.Е. Обрагтсс внимание, как аккуратновызуявастсяфунпервых, если мы удаляем строки, то нет нсобходилюс- > Здесь заранее предполагается, что сушсствуст функция кция ген[)ос(). Используя дополнительный указатель, ти заходить в в цикл, который выделяет памнть лля ногегогп Ипата>1лгея > ) ЕгееЯГАггау(К и вот она к вашим услугам. Как и мож- мы гарантируем, что первоначальный указатель нс бувых строк. ок Это прсдотврац(астся условием цикла шсг ...ст ..., ..