Форум: "Основная";
Текущий архив: 2003.01.06;
Скачать: [xml.tar.bz2];
ВнизГлупый вопрос: Pchar ->string Найти похожие ветки
← →
pavel_ak (2002-12-14 21:04) [0]Была же простая функция для перевода PChar в string. Но я ее забыл. В helpe искал - не нашел. Может кто вспомнет навскидку?
← →
Anatoly Podgoretsky (2002-12-14 21:09) [1]Конечно, для этого функция не требуется.
← →
pavel_ak (2002-12-14 21:11) [2]-??? (а подробнее?)
← →
TTCustomDelphiMaster (2002-12-14 21:13) [3]string1 := pchar1;
← →
xyz (2002-12-14 22:09) [4]Этот вопрос стар как сам делфи )))
var ch : PChar;
str : string;
ch := PChar(str);
А стринг из ПЧара получать... смех...
← →
Набережных С. (2002-12-14 22:34) [5]>TTCustomDelphiMaster © (14.12.02 21:13)
Это только, если PChar указывает на строку, заканчивающуюся нулем, что не есть непреложный факт.
>pavel_ak © (14.12.02 21:11)
SetString, например.
← →
Anatoly Podgoretsky (2002-12-14 23:02) [6]Так PChar согласно справочной системы Дельфи
PChar is a pointer to a null-terminated string of 8-bit characters.
То есть в Дельфи другие варианты не рассматриваются и как PChar не считаются.
← →
TTCustomDelphiMaster (2002-12-14 23:21) [7]Набережных С.
Я исходил из того, что в 99,999% случаев PChar указывает на строку, заканчивающуюся нулем.
← →
Набережных С. (2002-12-14 23:21) [8]>Anatoly Podgoretsky © (14.12.02 23:02)
Ну это уже софистика:)
← →
Набережных С. (2002-12-14 23:27) [9]TTCustomDelphiMaster © (14.12.02 23:21)
Ну, насчет 99,999% ты явно погорячился:)
var
PC: PChar;
S:string;
Ch: array[0..2]of Char;
Ch1: array[0..2]of Char;
begin
Ch:="ABC";
Ch1:="DEF";
PC:=@Ch;
S:=PC;
ShowMessage(s);
end;
Не реально?
← →
TTCustomDelphiMaster (2002-12-14 23:32) [10]
> Не реально?
Нет. Какой смысл в этом. Где реально применяются указатели PChar как указатель на строку не завершающуюся #00. Как узнавать ее длину?
← →
Набережных С. (2002-12-14 23:37) [11]Ну не реально, так не реально. Смыслов много, но это для меня. Настаивать я не буду.
← →
Fantasist (2002-12-15 23:05) [12]
> Это только, если PChar указывает на строку, заканчивающуюся
> нулем, что не есть непреложный факт
Если это С-строка не заканчивающаяся нулем, то это уже не строка, а просто указатель на нечто. Чтобы она была строкой (С-строкой), она обязанна заканчиваться на 0.
← →
Anatoly Podgoretsky (2002-12-15 23:10) [13]TTCustomDelphiMaster © (14.12.02 23:32)
PChar можно использовать не только как указатель на ASCIIZ строку, а на что угодно, только работать надо не как со строкой
Иногда это удобно из за поддержки адресной математики, как использование string не для хранения строк, а двоичных данных, из за великолепного управления памятью.
← →
Snap (2002-12-15 23:20) [14]Насколько я знаю, strPass или StrPCopy делает как раз то что тебе надо!.
← →
Sha (2002-12-15 23:33) [15]Иногда, например, бывает надо обработать целочисленный массив побайтно - PChar незаменим.
← →
Snap (2002-12-15 23:34) [16]Лучше всего природу Pchara понять поможет его объявление - ^char.
← →
Jeer (2002-12-16 00:16) [17]Sha © (15.12.02 23:33)
Возможно, если забыть о предопределенных
IntegerArray = array[0..$effffff] of Integer;
PIntegerArray = ^IntegerArray;
PSmallInt = ^SmallInt;
PInteger = ^Integer;
PSingle = ^Single;
PDouble = ^Double;
PDate = ^Double;
PDispatch = ^IDispatch;
PPDispatch = ^PDispatch;
PError = ^LongWord;
PWordBool = ^WordBool;
PUnknown = ^IUnknown;
PPUnknown = ^PUnknown;
PByte = ^Byte;
PPWideChar = ^PWideChar;
← →
xyz (2002-12-16 00:41) [18]из-за String и PChar столько шуму...
← →
Sha (2002-12-16 09:16) [19]2 Jeer © (16.12.02 00:16)
У меня случается, что в строках String лежат целые числа.
Для их побайтной обработки, например, так:
(a+i)^:=(a+i+1)^ xor (a+i+2)^ xor (a+i+3)^;
логичнее использовать PChar, а не PByte.
Здесь все a - байты целого числа, являющегося элементом
массива с индексом, равным i div 4.
← →
Sha (2002-12-16 09:19) [20]2 xyz © (16.12.02 00:41) и других "продолжающих".
Обсуждая PChar, мы забыли про ребенка.
Сначала маленькая загадка.
Попробуйте угадать, что выведет на экран простейшая программа:
procedure TForm1.Button4Click(Sender: TObject);
var
s, t, r: string;
pc: PChar;
begin
s:="qwerty";
t:="qwerty";
r:="qwerty";
pc:=@s[1]; pc^:="-"; ShowMessage(r);
pc:=PChar(t); pc^:="-"; ShowMessage(r);
end;
Теперь пространный ответ для начинающих.
Разработчики Дельфи "улучшая" старый короткий строковый тип, почему-то думали,
что нам вечно будет не хватать памяти и вынудили программистов пользоваться
скрытым механизмом подсчета ссылок на строки. Может это и здорово, но в моих
программах почему-то раз в 100 чаще оказывается, что ссылки посчитывать
как раз не надо.
Хотя бы дали возможность выбора или ввели новый тип. В результате этого
идиотизма стало просто невозможно написать эффективную программу, работающую
с отдельными символами строк (типа String, разумеется).
Где выход,- спросите вы. Да, да, вы знали: надо использовать PChar.
При его использовании в подобных программах эффективность возрастает в десятки
раз: не надо подсчитывать ссылки, не надо получать уникальные строки.
Пример приводить не буду. Тут пару дней назад кто-то не сделал домашнего
задания (перебор всех слов из заданного множества букв).
Если надо, найдите его - там есть пример. Если сам найду, подниму.
А как же обещанный ответ?
После выполнения первых трех операторов все строки (s, t, r) будут не просто равны.
Они будут одной строкой, использованной 3 раза, т.е. будут располагаться по одному адресу.
Первый ShowMessage покажет "qwerty", т.к. в результате оператора pc:=@s[1]
произойдет обращение за уникальной строкой и s будет располагаться уже не там,
где r и t, хоть они и будут оставаться равными. И, значит, изменение первого
символа строки s никак не повлияет на строку r.
Второй ShowMessage покажет "-werty", т.к. pc:=PChar(t) не обращается за
уникальной строкой, и, изменяя t, мы меняем r.
Почувствуйте разницу, и пребудет с вами сила.
← →
Ihor Osov'yak (2002-12-16 10:38) [21]2 Sha © (16.12.02 09:19)
У Вас, во первых, присутствует как минимум, две ошибки.
Обо всем попорядку.
Во первых: строки-константы размещаются в учаске памяти, имеющей атрибут рид-онли и механизм подсчета ссылок для них блокирован (запустите на трассирование фрагмент
s:="qwerty";
t:="qwerty";
r:="qwerty";
в режиме "CPU" (там, где дисассемблер - Ctrl+Alt+C), одновреммено проссматривая участок памяти, где живет наша "qwerty" - понятное дело, прихопив восемь байт перед началом тела строки... Вы увидите, что счетчик юзаний не меняется, он вообще установлен в $FFFFFFFF...
Вторая - вылет в следуещем фрагменте:
pc:=PChar(t); pc^:="-"; ShowMessage(r);
Здесь оператор присваивания вызовет ошибку. Ибо pc будет указывать та "оригинальную строку", размещенную в "рид-онли" участке памяти...
Ps, в чем с Вами согласен, что борланд немного перемудрил со строками... Хотя вряд-ли можно было придумать что-либо лучшее.
А если вспомнить, что string=AnsiString=поинтер на структуру - то все встает на свои места... Жаль только, что практически все книги не уделяют должного внимания этому вопросу ... Отсюда и куча непоняток в тех начинающих, которые начинают выходить из уровня "ламерства"... А если чел еще не дружит Ctrl+Alt+C - проблема для него может быть очень серьезная ...
ЗЫ2 - а пимер Вы действительно хорошийц привели ... Если не брать во внимание нескольких тех неточностей, упрмянутых выше
← →
han_malign (2002-12-16 10:50) [22]2 Sha - ошибочка у вас закралась и вы ввели в заблуждение публику
procedure TForm1.Button4Click(Sender: TObject);
var
s, t, r: string;
pc: PChar;
begin
s:="qwerty";
t:="qwerty";
r:=t; //!!! r:="qwerty";
pc:=@s[1]; pc^:="-"; ShowMessage(r);
pc:=PChar(t); pc^:="-"; ShowMessage(r);
end;
- тогда будет так как вы сказали, но только для случая прямого приведения типов(что всегда делается исключительно на свой страх и риск), если сделать t[1]:="-" то для t автоматически будет выделен новый блок памяти и скопирована страрая информация.
!!!!ВНИМАНИЕ - ДЛЯ ОТКРЫТЫХ МАССИВОВ, ПРИ ИЗМЕНЕНИИ, АВТОМАТИЧЕСКОЕ РАЗДЕЛЕНИЕ ССЫЛОК ПРОИСХОДИТЬ НЕ БУДЕТ - это специально описано в хелпе, к открытым массивам надо изначально относиться как к указателям(причем Length(OpenArray)=0 можно проверять и таким способом - OpenArray=nil), только со своими функциями управления памятью и автоматическими приведением типа и адрессацией.
З.Ы. Честно говоря не понимаю возмущения, за вас сделали всю работу по управлению памяти, причем интеллектуальнальному управлению(программа активно работающая с string, IMHO надежней чем с PCHAR, поскольку когда вы отладите свою программу по поводу утечек памяти - не известно, а string-и отлажены уже давно и проверены на тысячах комерческих проектах). String - это тот-же PChar (s[Length[s]+1]=#0 - всегда), только добавлено неявное поле DWORD(pointer(DWORD(s)-4)^)=Length(s), плюс механизм ссылок. Для явного разделения ссылок достаточно сделать SetLength(t,Length(t)).
З.З.Ы. Причем механизм подсчета ссылок это не эксклюзив string-ов, этот механизм изначально зашит в Delphi-ийский менеджер кучи, только не везде используется(string, Interface). Так-что работая с PChar через GetMem/FreeMem/New/Dispose - вы все равно его используете, но в холостом режиме.
З.З.З.Ы. Причем работает и WideString:=String и String:=WideString, только что убедился что даже корректно(для интернацинальных - кодировку в старшем байте проставляет).
← →
KSergey (2002-12-16 11:11) [23]Спасибо всем! Для меня было очень познавательно.
PS: люди, откуда вы все знаете?? впрочем, это риторический вопрос.
← →
Sha (2002-12-16 11:24) [24]2 Ihor Osov"yak © (16.12.02 10:38)
2 han_malign © (16.12.02 10:50)
А вы попробуйте исполнить мой код, поставьте брекпойнт в начале процедуры, посмотрите память, а потом говорите про ошибки.
← →
Sha (2002-12-16 11:31) [25]2 han_malign © (16.12.02 10:50)
Я лишь описал некоторые тонкости применения строковых типов.
Никакого возмущения нет и в помине. Дельфи форэва !!!
Просто хотелось бы иметь длинные строки без подсчета ссылок, вот и все.
← →
Ihor Osov'yak (2002-12-16 11:35) [26]2 Sha © (16.12.02 11:24)
Мил человек, а я так и делал, перед тем как писать сюда...
Хотя что там не все чисто догадался и теоритически ... :-)
← →
vedmed (2002-12-16 12:21) [27]2 Sha ©
В WideString нет подсчета ссылок, для типа string есть процедура UniqueString
← →
Ihor Osov'yak (2002-12-16 12:23) [28]В дополнение :-)
> Просто хотелось бы иметь длинные строки без подсчета ссылок,
> вот и все.
А раскажите, пожалуйста, как себе Вы представляете реализацию
s:=s+"qwerty" где s - длинная строка без механизма подсчета ссылок и с кооректным освобождением памяти от "старого екзампляра" тела строки...
Зы и еще - перед тем как кому-то советовать прогнать Ваш код в отладчике, следовало бы это делать самому ...
← →
Ihor Osov'yak (2002-12-16 12:31) [29]сорри, в (16.12.02 12:23) подразумевается конечно не widestring :-)
← →
Danlicha (2002-12-16 12:42) [30]Да, чуваки, клёво! И, кстати, никто не отменял ShortString - я его использую везде, где только можно, т.к. глупо для строки в несколько символов выделять большой стринг, с восьми или двеннадцитибайтным заголовком. И не медленне работает, чем сишные. Но надёжно.
← →
Sha (2002-12-16 12:50) [31]2 Ihor Osov"yak ©
>pc:=PChar(t); pc^:="-"; ShowMessage(r);
>Здесь оператор присваивания вызовет ошибку. Ибо pc будет
>указывать та "оригинальную строку", размещенную в "рид-онли"
>участке памяти...
У меня не вызывает :)
>А раскажите, пожалуйста, как себе Вы представляете реализацию
>s:=s+"qwerty" где s - длинная строка без механизма подсчета
>ссылок и с кооректным освобождением памяти от "старого
>екзампляра" тела строки...
Я думал, все знают это.
Выделяем память для t, выполняем t:=s+"qwerty", освобождаем s,
далее t называем s.
← →
Sha (2002-12-16 13:08) [32]2 Ihor Osov"yak ©
Насчет счетчика юзанья.
Исправьте начало так:
---
s:="qwerty"; s[1]:="q";
t:=s;
r:=s;
---
Теперь счетчик меняется как положено?
Про счетчик я сказал просто так - для информации.
Я вовсе не утверждал, что такое поведение программы зависит от счетчика. Я даже не говорил, что он равен трем. Будьте внимательны, мил человек.
А утверждал я вот что: операторы pc:=@s[1] и pc:=PChar(t) работают по-разному - одному нужна уникальная строка, другому нет.
З.Ы. Я всегда все гоняю под отладчиком, иначе откуда мне это знать.
← →
Ihor Osov'yak (2002-12-16 15:35) [33]2 Sha © (16.12.02 12:50)
Ну и вы любитель разводить дисскусию на пустом месте + талант перекручивать слова собеседника ..
у меня было:
s:=s+"qwerty" - то есть тривиальное соединение строк без декларации промежуточной переменной и ручной работы по освобождению памяти.
Вы почемуто начали комментировать реализацию с промежуточной переменной t и с ручками по памяти. Юзайте себе на здоровье PChar и занимайтесь мазохизмом с ручным выделением/освобождением памяти везде где это только возможно... Одно из главных преимуществ борландовской реализации string - то что код с операциями соединения строк очень прозрачен и компактен, без рутинной работы по управлению выделениею и освобождению памяти, что невозможно реализовать без счетчика использований.. А если уже вас понесло на "силовое" приведение типов - так вы должны соображать,что делаете... Не говоря уже о том, что нужно очень подумать, перед тем как такое делать....
> У меня не вызывает :)
D5, sp1... вы, возможно юзаете версию компилятора, которая размещает строки-константы в памяти с r/o, что, если быть очень дотошным, не совсем корректно... Да, и если у вас это действительно работает - можете запомнить на всю последующую жизнь, как пример плохого кода, который может вызывать проблемы под разными версиями комполяторов..
> Исправьте начало так:
Оригинально-с... Я не спрашивал вас, как написать, чтобЫ счетчик заработал. Я обратил только внимание на то, что в коде, который привели вы, счетчик вообще не юзается, и это есть корректно, ибо не будем же удалять строку-константу, которая "живет" в образе PE, загруженном в память...
> pc:=@s[1] и pc:=PChar(t) работают по-разному
И правильно делает. В первом случае, вы запрашиваете указатель на элемент строки(пускай и первый), то есть заявляате, что собираетесь потенциально измееять его. И целиком естественно, что компилятор для вас строит копию начальной строки, которая еще юзается какими-то другими обьектами программы, чтобы застраховатся от изменения оригинальной строки, которая не есть в монопольном использовании. То есть реализация кода в этом случае есть абсолютно корректной...
Во втором случае - pc:=PChar(t) - присваивание указателя с "силовым" приведением типа. Последствия за использование - полностью на кодере...
Зы - если под отладчиком в контекте разговора вы понимаете отладку на уровне дизассемблера - то очень странно, что вы ожидаете, что pc:=@s[1] и pc:=PChar(t) сгенерят вам одинаковый код. Ибо это вещи совершенно разные. Если Вы работаете на уровне символьного отладчика - не поленитесь, углубтесь на уровень диссамилерного кода (предварительно несколько узучив ассемблер) -
и на многое у вас будет точка зрения гораздо ближе к истинной ...
← →
Ihor Osov'yak (2002-12-16 15:39) [34]Должно быть:
которая не размещает строки-константы в памяти с r/o
что, если быть очень дотошным, не совсем корректно...
← →
Anatoly Podgoretsky (2002-12-16 15:46) [35]Второй вариант еще сложнее, пусть S := "", тогда функция вместо передачи nil, как это было бы для неициализированной PChar переменной выдаст из кодового сегмента адрес нулевой строки, защитив тем самым некоторые WinApi функции и в противоположном случае выдаст адрес s[1], ошибки не произойдет.
← →
Ihor Osov'yak (2002-12-16 15:47) [36]2 2 Sha © (16.12.02 12:50)
Еще две цитаты:
от Sha © (16.12.02 09:19)
> Они будут одной строкой, использованной 3 раза, т.е. будут
> располагаться по одному адресу.
от Sha © (16.12.02 13:08)
Я даже не говорил, что он равен трем. Будьте внимательны, мил человек.
Это я к тому, что внимательно читаю постинги, на которые собираюсь дать критический ответ. Я, между прочим, не оспаривал тот факт, что строка заюзана три раза. Я обратил только внимание на то, что для строк-констант, счетчик использования блокирован - см Ihor Osov"yak © (16.12.02 10:38).
← →
Anatoly Podgoretsky (2002-12-16 15:48) [37]Надеюсь, что никто не будет оспаривать, что "" и nil для PChar строк это не одно и тоже, кстати на этом часто горят, при передаче в WinApi функцию как константы
← →
Ihor Osov'yak (2002-12-16 15:49) [38]2 Anatoly Podgoretsky © (16.12.02 15:46)
Маестро, Вы как всегда, правы.. :-)
← →
Sha (2002-12-16 16:15) [39]2 Ihor Osov"yak © (16.12.02 15:35)
> Ну и вы любитель разводить дисскусию на пустом месте + талант перекручивать слова собеседника ..
Зачем же вешать ярлыки? Будьте корректнее.
> Вы почемуто начали комментировать реализацию с промежуточной
> переменной t и с ручками по памяти... Не говоря уже о том, что
> нужно очень подумать, перед тем как такое делать....
Я начал комментировать возможную реализацию желаемого типа на
уровне компилятора. Жаль, что вы не поняли.
> D5, sp1... вы, возможно юзаете версию компилятора, которая
> размещает строки-константы в памяти с r/o, что, если быть очень
> дотошным, не совсем корректно...
Это в Борланд :)
> Да, и если у вас это действительно работает - можете запомнить
> на всю последующую жизнь, как пример плохого кода, который
> может вызывать проблемы под разными версиями комполяторов..
С чего вы взяли, что я этого не знаю. Более того, я делюсь своими знаниями с вами.
> Я обратил только внимание на то, что в коде, который привели
> вы, счетчик вообще не юзается, и это есть корректно, ибо не
> будем же удалять строку-константу, которая "живет" в образе PE,
> загруженном в память...
И это мне известно. Я тоже это подчеркивал.
>> pc:=@s[1] и pc:=PChar(t) работают по-разному
> И правильно делает...
Полностью согласен. И тоже знаю ПОЧЕМУ.
>Зы - если под отладчиком в контекте разговора вы понимаете
>отладку на уровне дизассемблера - то очень странно, что вы
>ожидаете, что pc:=@s[1] и pc:=PChar(t) сгенерят вам
>одинаковый код. Ибо это вещи совершенно разные.
Я и не ожидаю. И не хочу, чтобы другие ожидали. Как раз это
я и сказал в самом начале, приведя ответ на свою загадку.
>Если Вы работаете на уровне символьного отладчика - не
>поленитесь, углубтесь на уровень диссамилерного кода
>(предварительно несколько узучив ассемблер) -
>и на многое у вас будет точка зрения гораздо ближе к истинной ...
Почему вы решили, что я не знаю ассемблер. Вы телепат?
Мы оба понимаем, о чем речь. Не надо цепляться.
Уважайте чужие знания.
← →
Sha (2002-12-16 16:30) [40]2 2 Ihor Osov"yak © (16.12.02 15:47)
>Еще две цитаты:
>от Sha © (16.12.02 09:19)
>> Они будут одной строкой, использованной 3 раза, т.е. будут
>> располагаться по одному адресу.
>от Sha © (16.12.02 13:08)
>>Я даже не говорил, что он равен трем. Будьте внимательны, мил человек.
Это действительно так!!! Мы имеем три строки с одним и тем же значением. И ни слова не сказано про значение счетчика использований для этой константы.
> Это я к тому, что внимательно читаю постинги, на которые
> собираюсь дать критический ответ. Я, между прочим, не
> оспаривал тот факт, что строка заюзана три раза. Я обратил
> только внимание на то, что для строк-констант, счетчик
> использования блокирован - см Ihor Osov"yak © (16.12.02 10:38).
Это известный факт, я с этим согласен.
← →
Ihor Osov'yak (2002-12-16 17:11) [41]2 Danlicha © (16.12.02 12:42)
Зы, и я очень часто юзаю shortString; Для малых строк это самый оптимальный вариант, просто это было как-бы вне контекста разговора с Sha ©...
2 Sha - наш разговор начал походить на флейм. Посему есть предложение его закончить, во всяком случае я в будущем воздержусь от ответа в этой ветке . Но все-же возьму на себя смелость сделать три реплики:
- я не просил делится со мной вашими знаниями. Я припускаю, что ваши рассуждения могут быть много кому интересны, но не надо делать лично мне милость, адресуя их мне персонально (см Sha © (16.12.02 16:15)).
- у Вас в коде все же ошибка, ладно, можно сказать фрагмент, который при переходе на другую версию компилятора может вызвать проблемы (см. Sha © (16.12.02 09:19) и мой идущий следом постинг), а на это вы упорно закрываете глаза...
- единственное, что я, возможно, не совсем корректно воспринял - это то, что мне показалось, что по поводу операторов pc:=@s[1] и pc:=PChar(t) Вы ремствуете по причине того, что они рабоют по разному. Я не понял, что Вы делаете констатацию факта. В связи счем и приношу извинение (но только в этой части разговора)
С уважением,
← →
Sha (2002-12-16 17:24) [42]2 Ihor Osov"yak © (16.12.02 17:11)
Мне тоже надо было быть добрее.
← →
Sha (2002-12-16 19:41) [43]Добавлю до кучи еще одно отличие между PChar и String:
Если внутри строки типа String есть символ #0 (не в конце строки, а именно внутри) и PСhar указывает на первый символ этой строки, то строковые функции для типа String продолжают работать на всю длину, а для типа PChar - до первого #0.
← →
Зорький глаз (2002-12-16 20:34) [44]А еще разница между integer(2) и integer(4) в том, что применение операции and $02 с первым и вторым со втором даст нулевой результат, а с первым - ненулевой ....
← →
Питьливый ум (2002-12-16 20:53) [45]2 Зорький глаз (16.12.02 20:34)
И часто этим пользуешься?
← →
ssg_ (2002-12-22 11:06) [46]А как преобразовать строку из TStringList в PWideChar, например для ExtractAssociatedIcon
← →
ssg_ (2002-12-22 11:20) [47]А как преобразовать строку из TStringList в PWideChar, например для ExtractAssociatedIcon
← →
GrayWolf (2002-12-24 21:32) [48]Народ, а вам функция StrPas не пойдет? Она правда преобразует PChar в AnsiString, но в большинстве случаев другого на мой взгляд и не требуется... ))
← →
Alex Konshin (2002-12-25 06:06) [49]String имеет заголовок размером в 12, реально адрес указывает на конец этого заголовка и на первый символ строки.
Это ссылка на мою старую, коротенькую, но полезную для начинающих статью про String:
http://akzhan.midi.ru/devcorner/akdeltnt-content/akdeltnt-0033.html
← →
Dok_3D (2002-12-25 06:26) [50]2 All
Честное слово, мне бы ваши заботы ...
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2003.01.06;
Скачать: [xml.tar.bz2];
Память: 0.61 MB
Время: 0.009 c