Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.07.08;
Скачать: [xml.tar.bz2];

Вниз

FillChar для строки   Найти похожие ветки 

 
Dmitry_177   (2007-05-26 02:25) [0]

Как правильно выполнить FillChar для строки?

Если выполнить так:

var
s: string;
...
FillChar(s, SizeOf(s), #0);

ИМХО очистится не сама строка, а указатель на нее..

Вот так правильно ли будет?

var
s: string;
...
FillChar(PChar(s)^, Length(s), #0);


 
Германн ©   (2007-05-26 02:39) [1]

А зачем нужен FillChar для строки?


 
Dmitry_177   (2007-05-26 02:41) [2]

чтоб очистить ее =)


 
Германн ©   (2007-05-26 02:51) [3]


> Dmitry_177   (26.05.07 02:41) [2]
>
> чтоб очистить ее =)
>

От чего очистить?


 
Dmitry_177   (2007-05-26 02:57) [4]

от всякого мусора..


 
Германн ©   (2007-05-26 02:59) [5]


> Dmitry_177   (26.05.07 02:57) [4]
>
> от всякого мусора..
>

Ну а смысл, то в чём?


 
Andy BitOff ©   (2007-05-26 03:14) [6]

Чтобы очистить s:=""; а чтобы заполнить StringOfChar


 
Kedge ©   (2007-05-26 03:43) [7]

> [6] Andy BitOff ©   (26.05.07 03:14)
> Чтобы очистить s:=""; а чтобы заполнить StringOfChar
Довольно "емкие" операции.
Допустим, я в строку, заранее определенной длины MAX_MY_VALUE_LEN, в цикле записываю значения:
for i := 0 to Count do
begin
 // здесь надо очистить строку, IMHO, лучше использовать FillChar
 SomeFunction(MyStr[1], MAX_MY_VALUE_LEN);
 if Pos("bla-bla", MyStr) > 0 then ....
end;


 
Andy BitOff ©   (2007-05-26 04:19) [8]

Да. К сожалению я забыл написать P.S.
Так вот.

Чтобы очистить s:=""; а чтобы заполнить StringOfChar

P.S. Я знаю, что земля не шар.


 
palva ©   (2007-05-26 07:57) [9]


> Вот так правильно ли будет?
>
> var
> s: string;
> ...
> FillChar(PChar(s)^, Length(s), #0);

Так будет правильно. Но нарушится механизм подсчета ссылок. Пример.
{$APPTYPE CONSOLE}
var
 s1, s2: String;
begin
 s1 := "qwerty";
 s2 := s1;
 writeln(s2); // "qwerty"
 FillChar(PChar(s1)^, Length(s1), #0);
 writeln(s2); // выдаст пустую строку
end.

Если вы хорошо понимаете, что произойдет, и ваш текст не будут сопровождать другие программисты, тогда делайте.


 
Loginov Dmitry ©   (2007-05-26 08:59) [10]

> Так будет правильно. Но нарушится механизм подсчета ссылок


Вот он-то как-раз сработает, как и должен. Насколько результат ожидаем - зависит от квалификации того, кто применит данный код.

P.S. А что, константы в консольной проге разве не хранятся в области кода? (Или данные в области кода разрешено модифицировать?)


 
palva ©   (2007-05-26 09:11) [11]

Loginov Dmitry ©   (26.05.07 08:59) [10]
Это я не в курсе. Я написал пример, который демонстрирует, как я предполагаю, неожиданные для автора последствия.


 
Однокамушкин   (2007-05-26 09:18) [12]


> FillChar(PChar(s)^, Length(s), #0);


В этой строке приведение к PChar неправильно... Правильнее приводить к Pointer, потому что PChar(string) на самом деле не приведение типов, а неявный вызов функции _LStrToPChar. Если s<>"", то Pointer(s)=PChar(s), а вот если s="", то Pointer(s)=nil, а PChar(s)<>nil, он указывает на символ #0, размещённый в сегменте кода... Тут конечно без разницы, какой будет указатель, если длина всё равно ноль, но зато немного сэкономим на вызове _LStrToPChar - пустячок, а приятно...


 
Однокамушкин   (2007-05-26 09:21) [13]


> palva ©   (26.05.07 09:11) [11]
> Loginov Dmitry ©   (26.05.07 08:59) [10]
> Это я не в курсе. Я написал пример, который демонстрирует,
>  как я предполагаю, неожиданные для автора последствия.


Неожиданным последствием в данном случае будет access violation, т.к. вы пытаетесь модифицировать сегмент кода...


 
Loginov Dmitry ©   (2007-05-26 09:23) [14]

> Неожиданным последствием в данном случае будет access violation,
> т.к. вы пытаетесь модифицировать сегмент кода...


[10] читать будем?


 
Однокамушкин   (2007-05-26 09:27) [15]


> Loginov Dmitry ©   (26.05.07 09:23) [14]
>
> [10] читать будем?

Читал, просто решил сказать то же самое немного другими словами, раз palva не согласился сразу и стал возражать... В чём проблема-то?


 
Loginov Dmitry ©   (2007-05-26 09:31) [16]

> Читал, просто решил сказать то же самое немного другими
> словами


Дак я ж про то говорю, что в консольном приложеним "в данном случае" AV-то как раз и не будет.


 
Однокамушкин   (2007-05-26 09:42) [17]


> Loginov Dmitry ©   (26.05.07 09:31) [16]
>
> Дак я ж про то говорю, что в консольном приложеним "в данном
> случае" AV-то как раз и не будет.


Кажись, разобрался... Тут не в консольном приложении дело, а в том, что переменные глобальные... Например, такой код даёт av:

{$APPTYPE CONSOLE}
procedure Test;
var
s1, s2: String;
begin
s1 := "qwerty";
s2 := s1;
writeln(s2); // "qwerty"
FillChar(PChar(s1)^, Length(s1), #0);
writeln(s2);
readln
end;

begin
Test
end.


В неконосльном приложении такой код тоже не даёт ошибки

var s1, s2:string;

procedure TForm1.Button1Click(Sender: TObject);
begin
s1 := "qwerty";
s2 := s1;
FillChar(PChar(s1)^, Length(s1), #0);
Button1.Caption:=s2
end;


Но если сделать переменные локальными, av будет...

Смутно припоминаю, что когда-то видел статью, где об этом говорилось... сейчас попробую найти...


 
Однокамушкин   (2007-05-26 09:45) [18]

Вот, нашёл...
http://www.rsdn.ru/article/Delphi/dynarrays.xml#ENF


 
palva ©   (2007-05-26 09:58) [19]

Однокамушкин   (26.05.07 09:18) [12]
> но зато немного сэкономим на вызове _LStrToPChar - пустячок, а приятно...
Согласен.
Я в таких случаях вообще обхожусь без приведения
FillChar(s[0], Length(s), #0);
и Length(s) я бы не использовал, поскольку наверняка имеется переменная, где эта длина записана.


 
Loginov Dmitry ©   (2007-05-26 10:11) [20]

> Вот, нашёл...


thanks! Буду знать!


 
Однокамушкин   (2007-05-26 10:43) [21]


> palva ©   (26.05.07 09:58) [19]
> Я в таких случаях вообще обхожусь без приведения
> FillChar(s[0], Length(s), #0);


Видимо, имелся ввиду s[1]... Но это тоже корректно только если s<>"", а то будет то же av... а ещё обращение к отдельному символу в строке приводит к неявному вызову UniqueString, чтобы не повредились переменные, ссылающиеся на ту же строку, а это тоже дополнительная работа для процессора...


 
Riply ©   (2007-05-26 12:12) [22]

> [21] Однокамушкин   (26.05.07 10:43)
> а ещё обращение к отдельному символу в строке приводит к неявному вызову UniqueString
Вот тебе и раз :(
А как тогда можно "побыстрее" очистить строку ?
Я использовала FillChar(s[1], cbStrLen, #0) и была счастлива :)


 
Однокамушкин   (2007-05-26 12:53) [23]


> Riply ©   (26.05.07 12:12) [22]
> А как тогда можно "побыстрее" очистить строку ?

А так, как мы уже тут говорили...
FillChar(Pointer(s), cbStrLen, #0)

Быстрее, наверное, только на асемблере...


 
Loginov Dmitry ©   (2007-05-26 13:43) [24]

> А как тогда можно "побыстрее" очистить строку ?
> Я использовала FillChar(s[1], cbStrLen, #0) и была счастлива
> :)


Очищай так и далее, и будь счастлива. Тем более, что не вижу практического смысла применения операции FillChar к строкам (ну ни разу практически не вознакала такая потребность)


 
Dmitry_177   (2007-05-26 13:51) [25]

а если к примеру есть строка, и мы не знает есть ли в ней что-то или она пустая.. как тогда лучше делать? Ведь как тут уже говорилось Pointer(str) при пустой строке вернет nil. Вот так?

if str <> "" then
 FillChar(Pointer(str), Length(str), #0);


А еще если Length-ем не вариант пользоваться, то чем тогда лучше?

> и Length(s) я бы не использовал, поскольку наверняка имеется
> переменная, где эта длина записана.

У меня нету такой переменной..

А еще что лучше передавать третьим параметром? ведь если передавать "#0" и "0" строка в обоих случаях очищается..


 
Однокамушкин   (2007-05-26 14:01) [26]


> Ведь как тут уже говорилось Pointer(str) при пустой строке
> вернет nil.

Но ведь вот какая штука: Length(str) при ёэтом вернёт 0... А FillChar, он достаточно умный, чтобы при нулевой длине не обращаться к памяти, на которую указывает первый параметр... Так что ничего страшного, отдельно s<>"" можно не проверять...


> А еще что лучше передавать третьим параметром? ведь если
> передавать "#0" и "0" строка в обоих случаях очищается..


А без разницы... Для процессора что то - ноль, что это - ноль...


 
Dmitry_177   (2007-05-26 14:24) [27]

просто на сколько я знаю "#0"-это именно нулевой символ, а "0" - это символ 48.. Может какое-то да тратится время на перевод из 0 в #0? Вот я и спросил может сразу уж "#0" задавать..

Но если так у меня встречный вопрос, а если мы очищаем не строку а какую-то структуру? Где есть и строки и числа? тут уже что лучше "#0" или "0"?

Кстати как лучше структуры очищать? Что передавать первым и вторым параметром? Вот к примеру есть такая структура:

 Tabc = packet record
   a: integer;
   b: integer;
   c: string или pchar или array [0..MAX_PATH-1] of Char;
 end;


Что лучше передавать в Fillchar первым параметром? abc или Pointer(abc)?

P.S. насчет параметра c, незнаю как string и pchar, я использую array [0..MAX_PATH-1] of Char;


 
Loginov Dmitry ©   (2007-05-26 14:27) [28]

> просто на сколько я знаю "#0"-это именно нулевой символ,
> а "0" - это символ 48


Ноль - он и в африке ноль!


 
Anatoly Podgoretsky ©   (2007-05-26 14:45) [29]

> Loginov Dmitry  (26.05.2007 14:27:28)  [28]

Использовать FillChar самому себе вредить, а потом удивляемся откуда знаменитый buffer overflow
Насколько я помню в .NET компилятор грубо обругает за подобные вольности.


 
Dmitry_177   (2007-05-26 14:48) [30]

Anatoly Podgoretsky, ладно бог с ней с этой строкой.. а как тогда структуру очищать без FillChar-а?


 
Loginov Dmitry ©   (2007-05-26 15:05) [31]

ZeroMemory :)


 
palva ©   (2007-05-26 15:08) [32]


> Однокамушкин   (26.05.07 12:53) [23]
> А так, как мы уже тут говорили...
> FillChar(Pointer(s), cbStrLen, #0)

Теперь всегда так буду делать. Конечно, если мне когда нибудь взбредет в голову вспомнить детство и позаниматься извращениями.


 
Anatoly Podgoretsky ©   (2007-05-26 15:11) [33]

> Loginov Dmitry  (26.05.2007 15:05:31)  [31]

Шило на мыло


 
Dmitry_177   (2007-05-26 15:13) [34]

Loginov Dmitry,  в ZeroMemory ее коде FillChar, посмотри..


 
Однокамушкин   (2007-05-26 15:46) [35]


> просто на сколько я знаю "#0"-это именно нулевой символ,
>  а "0" - это символ 48..

0 и "0" - это разные вещи... 0 соответствует #0, а "0" - #48...


 
Dmitry_177   (2007-05-26 16:36) [36]

Кстати если так подумать то ведь я не только в FillChar передавал PChar(str), но и во все API функции.. Тогда лучше в них Pointer(str) передавать?


 
Dmitry_177   (2007-05-26 16:41) [37]

Да и еще, при: FillChar(Pointer(str), Length(str), #0); при последующей работе с str выскакивает AV, а так: FillChar(Pointer(str)^, Length(str), #0);


 
Dmitry_177   (2007-05-26 16:42) [38]

т.е. с "^" на конце..


 
Loginov Dmitry ©   (2007-05-26 16:55) [39]

> Кстати если так подумать то ведь я не только в FillChar
> передавал PChar(str), но и во все API функции.. Тогда лучше
> в них Pointer(str) передавать?


Вряд ли это че-то будет лучше, не говоря уж о том, что многие API-функции Windows работают в Unicode-формате, и тама расходы на преобразование в UNICODE и обратно куда больше, чем расходы при использовании PChar.


 
begin...end ©   (2007-05-26 17:19) [40]

> Однокамушкин   (26.05.07 10:43) [21]

> Видимо, имелся ввиду s[1]... Но это тоже корректно только
> если s<>"", а то будет то же av...

AV не будет. Может быть только Range Check Error -- если, конечно, включена опция Range Checking.



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.07.08;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.082 c
1-1178639823
Oleg_teacher
2007-05-08 19:57
2007.07.08
Размер мемо


2-1181200742
delphino
2007-06-07 11:19
2007.07.08
Как работать с полем Date?


15-1181225632
Interior
2007-06-07 18:13
2007.07.08
Пакет легализации пиратского ПО


11-1164605756
StormA
2006-11-27 08:35
2007.07.08
RE_Text (RichEdit)


1-1178351020
nali
2007-05-05 11:43
2007.07.08
Ошибка при запуске делфи





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский