видове низове в Делфи - Списание
В тази статия, следните въпроси ще бъдат разгледани:
- Които съществуват видове низове в Делфи, постави и как те се различават един от друг
- String преобразуване от един вид в друг
- Някои методи се използват видове AnsiString на линии:
- Функции за работа с низове, които много често забравят или не знаят
- Електропроводи като параметри
- Използването на записите на линии
- Писане във файл и четене на файл
- Използването на низове като параметри и резултати функции поставени в DLL.
Е, аз се чудя? Тогава да вървим.
Кои видове низ съществува в Делфи, постави и как те се различават един от друг?
В Delphi 1.0 има само един-единствен тип низ String, напълно равностойни на вида на едно и също име в Turbo Pascal и Borland Pascal. Въпреки това, този вид има значителни ограничения, които ще обсъдят по-късно. За да се заобиколят тези ограничения, Delphi 2, разработчиците на Borland разположени малка революция. Сега, тъй като Delphi 2, има три основни типа низ: ShortString, AnsiString и WideString. В допълнение, низов тип се превърна логично. Т.е. в зависимост от настройките на съответния режим компилатор (големи струни режим), е равен на или по тип ShortString (за съвместимост с по-стари програми), или да въведете AnsiString (по подразбиране). режим на шофиране, можете да използвате директивата за компилация (кратка форма), или от прозореца за настройки на проекта - в раздела "Compiler" -> "отбележете Огромни струни". Ако е активирана, а след това се равнява на една AnsiString String, String се равнява на друг ShortString. Това правило има изключение: ако в дефиницията на типа String Определете максималния размер на низа, например String [25], а след това, независимо от начина на компилатора, видът ще се приравни към подходящия размер ShortString.
Защото, както ще научите в бъдеще, и AnsiString видове ShortString има съществена разлика в изпълнението, аз не препоръчвам да използвате логически тип String, без да уточнява размера, ако, разбира се, не се пишат програми под Delphi 1. Ако все още използвате тип низ, а след това аз силно препоръчвам директно в кода на вашата модул, за да уточни директива компилация, който определя вашия компилатор имплицитно режим. Особено, ако използвате функциите на изпълнението на съответния вид низ. Ако не го направите, един ден, когато вашият код попадат в ръцете на друг програмист, няма да има гаранция, че ще се създаде на компилатора, както и ваши.
Тъй като по подразбиране, след инсталирането на Делфи, големи струни е включен, по-голямата част от младите програмисти дори не знаят, че низът може да бъде нещо различно от AnsiString. Поради това, до края на тази статия, всяко позоваване на String, без да уточнява размера, означава, че тя е равна на тип AnsiString, освен ако изрично е посочено друго. Т.е. счита се, че настройката на компилатор съответства на настройката по подразбиране.
Веднага спомена от разликата между видовете AnsiString и WideString. Тези видове имат по същество същата изпълнението, и се различават само по това, WideString използва за представяне низове в UNICODE кодиране с помощта на 16-битово представяне на всеки знак (WideChar). Това кодиране се използва в случаите, когато имате нужда от едновременното присъствие в една и съща линия на герои от два или повече езика (различни от английски език). Например, линиите, съдържащи двете героите на английски, български и европейски езици. За тази възможност да плащат - размера на паметта, заета от такъв низ е два пъти размера на заети конвенционални линии. Използването WideString не се среща често, така че основно ще се говори за линии тип AnsiString. Но тъй като те имат една и съща реализация, почти всичко, което е казано за AnsiString ще бъде валиден за WideString, естествено като се отчитат различията в размера на всеки един от героите.
Същото важи и за разликата между pChar и pWideChar.
String AnsiString, обикновено се използва за представяне низове, кодирани в ANSI, или други (например ПОО), които използват един байт (8 бита), кодираща един символ. Подобен метод на кодиране се нарича еднобайтовата набор от символи, или SBCS. Но много хора не са наясно за съществуването на друг метод за кодиране на многоезични струни (различни от Unicode), използвани в Windows и Linux операционни системи. Този метод се нарича многобайтовите знакови набори, или МВСи. При този метод, някои от героите са представени от един байт, а някои две или повече. За разлика от UNICODE, низ кодиран по начин, изискващ по-малко памет за съхранението им, но изискват по-сложна обработка. Така че, AnsiString тип низ може да се използва за съхраняване на такива редове. Няма да се спирам на този метод за кодиране, тъй като тя се използва рядко. Лично аз никога не се срещна програмите по метода на кодиране.
експерти Delphi вероятно ще ми напомнят още веднъж, и за видовете pChar (pWideChar) и масив [. ] Овъгляване. Въпреки това, аз вярвам, че това не е съвсем видове низове, но аз ще ви разкажа за тях, тъй като те често се използва във връзка с видове низове.
Така че, тук са основните характеристики на типа низ:
Максималният размер на низа
Количеството памет, необходима за съхранение на низа
String [п], където 0 е 0, така че Delphi и не освобождава паметта, заета от низ.
И все пак, този брояч се използва за решаване на проблемите, свързани със следната ситуация:
Когато се работи с определени струни като константи, алгоритъмът е малко по-различна. Ето един пример:
Тя ще изглежда, че в края на процедурата, например на низа "Боб" трябва да бъде унищожен. Но в този случай не е така. В крайна сметка, следващия път, когато процедурата за възлагане ще трябва отново да се вземат някъде линия "Вася". За да направите това, дори когато се компилира, Delphi поставя копие на низа "Боб" в константи на програмата, дори и когато не е възможно да се промени, най-малко с прости методи. Но какво да кажем, когато в края на процедурата, за да се определи, че низа "Боб" - постоянна низ, и е невъзможно да се унищожи? Това е много проста. За постоянни струни, справка брояч е настроен на -1. Тази стойност е "изключено" нормална работа на алгоритъма с "референтния брой". Той не се увеличава със задача, и не е намален с унищожаването на променливата. Въпреки това, когато се опитва да се промени променливата (Не забравяйте s2 [1]: = "X"), стойността на брояча -1 винаги ще се счита за индикация, че се отнася до серия от повече от една променлива (в действителност това не е равно на 1). Ето защо, в такава ситуация, винаги ще се създаде уникален екземпляр на низ, разбира се, без снижаване на референтния брой на старите. Това ви предпазва от промени в низови константи например.
За съжаление, този алгоритъм не винаги работи. Но повече за това, ние ще говорим по-късно, когато се разглежда превръщането на видове низове.
Къде е Delphi магазините на "референтен брой"? Освен това, за всяка линия на собствения си! Естествено, заедно с низ. Това е, което тази област от паметта, която съхранява копие от линия "абв":
Референтен брой на -1
С сферата на офсетов -8, ние вече трябва да е ясно. Тази стойност се запаметява в двойна дума (4 байта), същата брояч, което позволява оптимизиране на съхранението на еднакви линии. Този брояч е от тип цяло число, т.е. може да бъде отрицателен. В действителност, като се използва само един отрицателни - "-1", и положителни стойности. 0 не се използва.
Сега гледам за областта, която се намира в компенсира -4. Това четири байта дължина на стойността на низ (почти като в ShortString). Мисля, че вие ще забележите, че сумата, заделена памет за низа не съкращения. Т.е. компилаторът разпределя низ минимално необходимия брой байта памет. Това със сигурност е добра, но когато се опитате да "засили" ред: s1: = S1 + "D", съставител, а по време на изпълнение библиотека (RTL) трябва да се преразпределят памет. Защото сега линия се нуждае от повече памет, колкото един байт. За да се преразпределят на паметта трябва да знаете текущия размер на низа. Вероятно, това е за това, което не е необходимо всеки път, когато линията сканиране, определяне на нейния размер, Delphi разработчици и включени полеви дължина линии в тази структура. Дължината на низ се съхранява като стойност цяло число, следователно ограничи максималният размер на реда - 2 GB. Надявам се ние няма скоро да upremsya в това ограничение. Между другото, именно защото паметта за низа е динамично разпределени, и те имам още един на името си: динамичната линия.
Остава да кажете нещо повече за някои функции на продукта променливи AnsiString. Най-важната характеристика на този тип ценности, е възможността за привеждането им с типа на курсора. По този начин, разбира се, защото в "душата", те са указатели, като че ли те не се скрие. Например, ако са описани променливите: S: AnsiString и р: показалеца. Изпълнението на стр оператор: = показалеца (и) ще доведе до това, че индексът р ще посочим инстанция низ. Въпреки това, много е важно да се знае: противопоставяне на това ред с връзки няма да се увеличи. Но повече за това, ние ще говорим за по-късно.
Тъй като променливите от този тип са всъщност Указатели, за тях и наистина е важно, тъй като Нил - ". Нищото" указател към Стойността в променлива тип AnsiString по смисъла на равен празен низ. Освен това, за да предотврати загубата на памет и време за провеждане на референтния брой и размер на полето на низа винаги е 0, когато зададете празен низ променлива от този тип, всъщност, е настроен на нула. Не е ясно, тъй като тя обикновено не се забелязва, но както ще видим по-късно, една много важна функция.
Сега, изглежда, сте наясно с всички линии. Време е да преминем към по-интересна част на статията - как да живеят с всичко това?
String преобразуване от един вид в друг
Тук, както обикновено, и прости и сложни.
Преобразуване между "истински" видове низове String [н], ShortString и AnsiString извършва лесно и прозрачно. ние трябва да не прави изрично действие, Delphi ще направи всичко за вас. Нужно е само да се разбере, че в малко по-дълго на почивките. Например:
В резултат на този код, променливата S3 воля низ "ABC", а не "ABCDEF". С преобразуването на pChar в String [н], ShortString и AnsiString, също не всичко е лошо. Просто да възлага, и всичко ще бъде наред.
Трудностите започват, когато започнем да се трансформират "истински" видове струнни в pChar. Директен задача променлива тип стойности pChar ред не е разрешено от компилатора. На стр оператор: = S, където р е тип pChar, и е: AnsiString, компилаторът ще издаде съобщение: "Несъвместими типа:" String "и" PChar "- несъвместими видове" String "и" PChar ". За да се избегне този проблем, ще трябва да използвате изрично посочен тип гласове: р: = pChar (а). Така че препоръчвам Delphi разработчици. Като цяло, те са прави. Но, ако си спомняте, като динамични низове се съхраняват - нулев-прекратен, тъй като pChar. И все пак, и какво да AnsiString приложим вид реализация на курсора. Това става очевидно, че всички, може би най-много три начина да се преобразуват низ да pChar:
Всички те са синтактично правилни. И изглежда, че и трите показалка (P1, P2 и P3) ще има в резултат на една и съща стойност. Но това не е така. Всичко зависи от това, което е в с. За да бъдем по-точни, дали празен ред стойността е или не:
Че сте разбрали причината за това явление, аз ще опиша как Delphi изпълнява всеки един от тези трансформации. В началото Напомням ви, че AnsiString променливи, представляващи празни редове наистина трябва Nil стойност. Така че:
За да направите pChar (а) конверсия, компилаторът генерира вътрешен разговор специална функция @LstrToPChar. Тази функция проверява - ако променливата на низ е на стойност Nil, а след това вместо това, тя се връща указател към действителното местоположение в памет на празен низ. Т.е. pChar (а) никога не връща указател равен на нула.
Той причинява грешка достъп с памет, когато реда, обозначен 1. Така че трябва да използвате тази функция.
Тук, тъй като параметър премина по стойност, обаждането ще бъде създаден локално копие на променливата (показалец) MSG. Това е, което ще кажа по-късно. Тази променлива, при приключване на процедурите, ще бъдат унищожени, което води до освобождаването на "персонализирани" копия от копия на предава и преобразува низ.
Функциите на тази група, се използват за сравнение струни. Резултатът ще бъде една от стойностите:
> 0, ако S1> S2
255 символа трябва да плащат.
Ако достатъчно и 255 символа, след това се използва ShortString или String [п].
Използването на записите на линии
Проблемът възниква, когато едно поле (или полета) са от тип динамична линия. В този случай, често има проблем, подобен на проблема с динамични линии записани във файла - не всички данни се в записа, динамични линии са представени в него само указатели. За решаване на проблема, както и запис на редовете във файла. Единственото жалко е, че след това ще бъде невъзможно да се работи (четене / запис) цялата дневника. Line ще трябва да се справят самостоятелно. Можете да го направите по следния начин:
Използването на низове като параметри и резултати функции поставени в DLL.
Общият смисъл на Epic, че ако вашият Dll износ поне една процедура или параметър функция, съответстваща на типа на всеки динамичен бар (AnsiString например), или функция, която връща резултат от този тип. Трябва да сте сигурни, и Dll, както и използването му програма, първия модул в списъка с внос (употреби) посочи ShareMem модул. И в резултат на това да достави със своята програма и Dll друга стандартна библиотека BORLNDMM.DLL.
Не мислех, че на въпросите: "Защо всички неприятности?"; "Какво ще се случи, ако не направя?" и "Може ли това да бъде избегнато?"; "Ако е така, как?" Ако не сте се замисляли, че е време да го направя.
Опитайте се да разберете какво ще се случи със случаи на динамични редове в този пример:
Всичко изглежда да бъдат добри. Но докато и двете процедури са разположени в един изпълним модул (EXE-файл). Ако такава процедура, която Y Dll и процес X оставете да EXE, няма да има проблеми.
Фактът, че разпределянето и deallocation за отделни случаи на динамични линии, ангажирани в дейността на вътрешния мениджър памет Delphi-приложения. Използвайте стандартна програма за управление на Windows е много скъпо. Той също е универсална и затова бавно и линии често изискват преразпределение. Разработчиците на Delphi и създават свои собствени. Той води списък за разпространение и наличната памет на вашето приложение. Е, проблемът е, че Dll се използва за управление на паметта, и си EXE. За един от друг, те не знаят нищо. Поради това, освобождаването на блок памет, заделена Не се опитвайте мениджърът му ще доведе до сериозно нарушаване на нейната работа. Нещо повече, това заболяване може да се прояви не наведнъж, и доста необичаен начин.
В този случай, паметта за низа '100' ще бъде осветен мениджър EXE файл, и той ще бъде освободен DLL мениджър. Същото ще се случи с паметта в рамките на низ "100 $, само на заден ход.
За да се преодолее този проблем, Delphi разработчиците са създали BORLNDMM.DLL библиотека. Тя включва друг мениджър памет :). Използвайки същия ShareMem модул води до факта, че да замени вградения в EXE (DLL) Управителят памет за мениджър намира в BORLNDMM.DLL. Т.е. Сега и EXE файлове и DLL, ще използва една обща програма за управление на паметта.
Важно е да се отбележи, че ако някой не би било от програмните модули (EXE или DLL) имат ShareMem модул внася в списъка, цялата работа ще дойде до нищо. Отново ще се проведе няколко мениджъри на паметта. Отново ще има бъркотия.
Е, най-накрая го. Сега, че знаете за струни почти толкова, колкото аз :).
Разбира се, тази тема не е изчерпана. Например, аз не съм казвал нищо за низове многобайтовите (МВСи), използвани за многоезична приложения. Може би нещо друго забравих да кажа. Но, не се притеснявайте. Получих своите знания чрез изучаване на книги, текстове на тяхната собствена, и други програми, кода, генериран от компилатора и т.н. Т.е. всички с отворен код. Така че всичко това е на ваше разположение. Основното нещо е, че сте любознателен и често си зададе въпроса "Как?", "Защо?" "Защо?". След около вас ще бъде в състояние да решат сами.