tag:blogger.com,1999:blog-1702873441071265539.post532092992078702044..comments2023-05-29T19:02:20.570+03:00Comments on Блог GunSmoker-а: Задачка №12GunSmokerhttp://www.blogger.com/profile/15611696588191431330noreply@blogger.comBlogger14125tag:blogger.com,1999:blog-1702873441071265539.post-36154534275471674502011-09-13T11:43:53.864+04:002011-09-13T11:43:53.864+04:00На первый взгляд, UniqueString() не нужен, т.к. Se...На первый взгляд, UniqueString() не нужен, т.к. SetLength() гарантирует уникальность строки. Однако функция, реализующая конкатенацию, в случае пустого первого аргумента вызывает функцию присваивания и получается, что Data указывает на то же, что и Buf. Т.е., по сути, вызов UniqueString() нужен ровно один раз после конкатенации. Причём, хоть UniqueString(Buf), хоть UniqueString(Data).Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-71048189276536035122011-09-12T22:32:40.138+04:002011-09-12T22:32:40.138+04:00Выглядит адекватно. Еще бы вначале
FS.Position :=...Выглядит адекватно. Еще бы вначале <br />FS.Position := 0;Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-33434502905180512642011-08-29T18:11:48.365+04:002011-08-29T18:11:48.365+04:00У меня попутный вопрос. Если такая "засада&qu...У меня попутный вопрос. Если такая "засада" со строками, то что будет при использовании динамическим массивов (type tarr = array of Integer)? Какие "подводные камни"?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-67111897676975437422011-08-21T08:52:42.260+04:002011-08-21T08:52:42.260+04:00Есть небольшой недостаток, но об этом - в ответе.....Есть небольшой недостаток, но об этом - в ответе... :)GunSmokerhttps://www.blogger.com/profile/15611696588191431330noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-70299006669534519602011-08-20T23:34:48.434+04:002011-08-20T23:34:48.434+04:00Конструкция вида Buf[1] хорошо работает и во многи...Конструкция вида Buf[1] хорошо работает и во многих других случаях. А вот интересно, есть ли у нее недостатки или ее можно слепо лепить всюду, где она применима?Torbinsnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-40426459282982549542011-08-17T13:53:51.468+04:002011-08-17T13:53:51.468+04:00>Действительно, UniqueString тут не хватает.. э...>Действительно, UniqueString тут не хватает.. это интересно<br /><br />При использовании в FS.Read Buf[1] вместо Pointer(Buf)^ вызов UniqueString генерируется компилятором.Igor Schevchenkohttps://www.blogger.com/profile/06503541755579898125noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-43891589051525200222011-08-17T13:05:23.478+04:002011-08-17T13:05:23.478+04:00Действительно, UniqueString тут не хватает.. это и...Действительно, UniqueString тут не хватает.. это интересно. Получается так, что первая порция данных потеряется (вместо неё будет дублироваться вторая порция данных).<br /><br />Как оно будет оптимальнее - здесь нельзя сказать однозначно, т.к. нам неизвестна сама задача. Можно вообще весь файл считал одним вызовом FS.Read(... FS.Size - FS.Position). Или переменную Buf объявить как указатель и вручную выделять/освобождать под него память, плюс под строку Data сначала выделить память вызовом SetLength(Data, FS.Size - FS.Position) перед циклом, а потом в цикле копировать порцию из Buf.Николай Зверевhttps://www.blogger.com/profile/08965247674233981930noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-6425888230999960772011-08-17T01:44:13.351+04:002011-08-17T01:44:13.351+04:00Chaa прав. В строке 14 нужно добавить
UniqueString...Chaa прав. В строке 14 нужно добавить<br />UniqueString(AnsiString(Data));<br />Ну или если оптимальнее:<br />if Data = Buf then<br /> UniqueString(AnsiString(Data));Andynoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-87966875538333824222011-08-16T23:17:39.148+04:002011-08-16T23:17:39.148+04:00Забавные комментарии.
Вот Вы подумайте, как в один...Забавные комментарии.<br />Вот Вы подумайте, как в один байт уместить число 10240 (длина строки в примере)? Никак.<br />Переменные типа string (AnsiString/RawByteString) указывают на начало строки, а не на байт, содержащий размер строки (как в старом-добром Pascal'е, или как в случае с типом ShortString). Поэтому в примере всё корректно в этом плане.<br /><br />Мне кажется, что проблема заключается в том, что FS.Read в случае ошибки чтения вернёт 0 (фактическое кол-во прочитанных байт), что приведёт к... бесконечному циклу.<br />Вероятность возникновения такой ошибки - не велика, и потому этот код работает. Но если есть вероятность выше ноля, то такое когда-нибудь да и произойдёт. По закону Мёрфи :)<br />Исправить код можно добавлением условия в while:<br /> while (FS.Position < FS.Size) and (Length(Buf) > 0) do<br /><br />Но лично я предпочитаю немного другой, более прозрачный стиль кодирования:<br /> while FS.Position < FS.Size do<br /> begin<br /> Count := FS.Read(Pointer(Buf)^, Length(Buf));<br /> if Count = 0 then<br /> //попытаться понять, в чём ошибка чтения, или просто передать ошибку вверх:<br /> RaiseLastOSError;<br /> if Count < Length(Buf) then<br /> SetLength(Buf, Count);<br /> Data := Data + Buf; // это тоже не очень хорошая строка - за кадром происходит перераспределение памяти<br /> end;Николай Зверевhttps://www.blogger.com/profile/08965247674233981930noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-43879193507963808032011-08-16T16:57:36.735+04:002011-08-16T16:57:36.735+04:00Однако код-то работает.Однако код-то работает.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-46178320653665301942011-08-16T15:01:36.132+04:002011-08-16T15:01:36.132+04:00такое тоже помогает:
Data := Data + Copy(Buf,...такое тоже помогает: <br /> Data := Data + Copy(Buf, 1, Length(Buf));<br /><br />но совет с Buf[1] правильнее и проще :)Igor Schevchenkohttps://www.blogger.com/profile/06503541755579898125noreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-75539629724738701242011-08-16T08:03:37.237+04:002011-08-16T08:03:37.237+04:00AnsiString = array[0.. ] of Char
байт с адресом 0 ...AnsiString = array[0.. ] of Char<br />байт с адресом 0 в этом массиве указывает длину строки. Загрузка текстовой строки Pointer(Buf)^ приведет к тому что в [0] будет записано что угодно, но только не длина. Соответственно операция Data := Data + Buf в итоге даст мусор.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-27797963154350084002011-08-15T20:59:23.573+04:002011-08-15T20:59:23.573+04:00Или же в FS.Read использовать Buf[1] вместо Pointe...Или же в FS.Read использовать Buf[1] вместо Pointer(Buf)^.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1702873441071265539.post-56723784265702227222011-08-15T19:18:53.266+04:002011-08-15T19:18:53.266+04:00Строки в Delphi используют Copy On Write, а из-за ...Строки в Delphi используют Copy On Write, а из-за прямого доступа на запись к данным строки этот механизм не работает. UniqueString поможет.Chaahttps://www.blogger.com/profile/14387721107858333063noreply@blogger.com