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

Вниз

Непростой вопрос по string   Найти похожие ветки 

 
ps2006 ©   (2006-07-24 13:06) [0]

Всем привет, многоуважаемый ALL !

Есть вопросик по стрингу: есть поток, с него нужно прочитать n (ну например 7) байт в переменную типа string.
Я делаю так:


var
 s: string;
 FResponse: TMemoryStream;

begin
 ...  другой код  ...

 SetLength(s, 7);
 FResponse.Read(s[1], 7);


Неужели нет более красивого решения ?
Меня не совсем устраивает обращение к переменной так: s[1]

Спасибо.


 
tesseract ©   (2006-07-24 13:08) [1]


> Меня не совсем устраивает обращение к переменной так: s[1]


Чем?


 
Stakan ©   (2006-07-24 13:10) [2]

ps2006 ©   (24.07.06 13:06)
FResponse.Read(Pointer(s)^, 7);
Так красивее?


 
Reindeer Moss Eater ©   (2006-07-24 13:17) [3]

SetString(s,PChar(FResponse.Memory),7);


 
ps2006 ©   (2006-07-24 13:21) [4]

>FResponse.Read(Pointer(s)^, 7);
>Так красивее?

Да, так однозначно красивее, спасибо :-)

только нужно сделать немного по другому:

SetLength(s, 7);
FResponse.Read(Pointer(s)^, 7);

Спасибо


 
ps2006 ©   (2006-07-24 13:29) [5]

>> Меня не совсем устраивает обращение к переменной так: s[1]
>Чем?

не знаю, чем мне не нравится такое обращение к переменной, у меня "чутье" на плохой стиль написания кода.


 
ps2006 ©   (2006-07-24 13:30) [6]

Спасибо всем за ваши ответы !


 
Семеныч ©   (2006-07-24 13:30) [7]


> Непростой вопрос

Да?


 
Stakan ©   (2006-07-24 13:30) [8]

ps2006 ©   (24.07.06 13:21) [4]

>только нужно сделать немного по другому:
>
>SetLength(s, 7);
> FResponse.Read(Pointer(s)^, 7);

Ну это подразумевалось :) Была приведёна строчка кода которую можно изменить.


 
Loginov Dmitry ©   (2006-07-24 16:21) [9]

> не знаю, чем мне не нравится такое обращение к переменной,
> у меня "чутье" на плохой стиль написания кода.


Чутье вас подводит. Такой стиль - ОТЛИЧНЫЙ! Более красивого решения нет. Имхо.


 
Reindeer Moss Eater ©   (2006-07-24 16:25) [10]

Более красивого решения нет. Имхо

SetString(s,PChar(FResponse.Memory),7);


 
Loginov Dmitry ©   (2006-07-24 16:26) [11]

> только нужно сделать немного по другому:
>
> SetLength(s, 7);
> FResponse.Read(Pointer(s)^, 7);


И что это будет? Бред!


 
Loginov Dmitry ©   (2006-07-24 16:31) [12]

> SetString(s,PChar(FResponse.Memory),7);


Потоки для чего чего сделаны? Чтобы можно было последовательно считать данные в разные переменные. А здесь получается, что только первые 7 байт потока скопируются в проку. В этом плане [0] все-же проще и универсальнее.


 
Reindeer Moss Eater ©   (2006-07-24 16:34) [13]

При чем здесь эта лабуда с простотой и универсальностью?
Я просто показал, что есть более красивые решения для этого конкретного случая.


 
Loginov Dmitry ©   (2006-07-24 16:43) [14]

В догонку! Вот еще вспомнил вполне рабочий способ:

S := PChar(FResponse.Memory);

Красиво? То-то.
Только эта хрень сработает, если в потоке будет символ завершения строки.
Тогда запись в поток нужно делать так:

FResponse.Write(S[1], Length(S) + 1);

Красиво. Но не универсально. Для конкретного случая сгодится.


 
Reindeer Moss Eater ©   (2006-07-24 16:46) [15]

Мой пример сработает и без нуля в восьмой позиции.


 
Stakan ©   (2006-07-24 16:59) [16]

Loginov Dmitry ©   (24.07.06 16:26) [11]

> И что это будет? Бред!

Бывает полезно справку читать, перед тем как говорить.
If you are passing a string to a read or write function, you need to be aware of the correct syntax. The Buffer parameters for the read and write routines are var and const types, respectively. These are untyped parameters, so the routine takes the address of a variable.
The most commonly used type when working with strings is a long string. However, passing a long string as the Buffer parameter does not produce the correct result. Long strings contain a size, a reference count, and a pointer to the characters in the string. Consequently, dereferencing a long string does not result in only the pointer element. What you need to do is first cast the string to a Pointer or PChar, and then dereference it. For example:

procedure caststring;

var
 fs: TFileStream;
const
 s: string = "Hello";
begin
 fs := TFileStream.Create("temp.txt", fmCreate or fmOpenWrite);
 fs.Write(s, Length(s)); // this will give you garbage
 fs.Write(PChar(s)^, Length(s)); // this is the correct way
end;


 
ps2006 ©   (2006-07-24 17:02) [17]

Не ругайтесь, у каждого есть своя точка зрения.

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

Похоже, что все-таки наиболее красивым будет такое решение:
FResponse.Read(s[1], 7);
Обьясняю - это будет работать независимо от типа s - ShortString или AnsiString.
Я конечно могу ошибаться насчет красоты, тогда укажите свои аргументы "за" и "против"


 
Reindeer Moss Eater ©   (2006-07-24 17:16) [18]

Словно SetString вдруг перестало работать с shortstring


 
ps2006 ©   (2006-07-24 17:36) [19]

>SetString(s,PChar(FResponse.Memory),7);
>Словно SetString вдруг перестало работать с shortstring

Это конечно тоже выход из положения, но мне не понравилось следующее:
1) код не очень читабелен (нужно вникнуть, чтобы понять, что читается 7 байт с потока в переменную);
2) читается 7 байт с начала потока, а не с текущей позиции;
3) я привык создавать шаблоны (у себя в голове), чтобы их быстро и надежно использовать, если нужно будет использовать процедуру, которая читает(пишет) в(из) буфера, то при Вашем подходе нужно будет создать еще одну переменную для буфера. Пример:

var
 s: string;
 fs: TFileStream;
 buf: array[1..1024] of bytes; // или другой буффер, это неважно
begin
 .....
 fs.Read(buf; n);
 SetString(s, buf, m);


 
Reindeer Moss Eater ©   (2006-07-24 17:41) [20]

1) код не очень читабелен (нужно вникнуть, чтобы понять, что читается 7
байт с потока в переменную);

нечитабелен для того, кто не пользуется Setstring никогда.

2) читается 7 байт с начала потока, а не с текущей позиции;Это еще почему?  Кто мешает использовать смещение?

3) я привык создавать шаблоны (у себя в голове), чтобы их быстро и надежно использовать, если нужно будет использовать процедуру, которая читает(пишет) в(из) буфера, то при Вашем подходе нужно будет создать еще одну переменную для буфера. Пример:

Никаких буферных переменных у меня не используется. Есть переменная S из исходной задачи в которую надо считать данные из потока.


 
Loginov Dmitry ©   (2006-07-24 18:17) [21]

> Stakan ©   (24.07.06 16:59) [16]


> Бывает полезно справку читать, перед тем как говорить.


Вот именно, что бывает иногда полезно справку почитать, перед тем как говорить. А в справке ясно написано, что PChar, но никоим образом не Pointer, как указано в [2].
А еще иногда бывает полезно проверить то, что пишешь.


 
ps2006 ©   (2006-07-24 18:18) [22]

1) соглашусь - я никогда не пользовался Setstring;

>Кто мешает использовать смещение?
2) в принципе согласен, но этот метод не универсальный. Вы сможете работать таким образом с любым наследником TStream ?

> Никаких буферных переменных у меня не используется.
3) согласен, но это только для этого случая.

Речь не идет о том, как прочитать 7 байт из потока в переменную, речь идет о том, как это лучше сделать. Я говорю о подходе к программированию. У каждого человека он свой. Согласитесь, что легче программировать, когда везде используется один подход. Когда при изменении ТЗ если переделки приводят к "разваливанию" программы - это не подход.

(IMHO)


 
Loginov Dmitry ©   (2006-07-24 18:19) [23]

Медленно но верно все сводится к [0] ;)


 
Reindeer Moss Eater ©   (2006-07-24 18:22) [24]

Если говорить про "вообще" и про "универсальность" и про "как лучше", то скажу, что лучше сразу создавать экземпляр TStringStream, а не TMemoryStream? чтобы не маяться потом с перегонкой байтов и битов туда-сюда.


 
Stakan ©   (2006-07-24 18:33) [25]

Loginov Dmitry ©   (24.07.06 18:17) [21]
Повторюсь ещё раз: справку неплохо почитать и как можно внимательнее:

If you are passing a string to a read or write function, you need to be aware of the correct syntax. The Buffer parameters for the read and write routines are var and const types, respectively. These are untyped parameters, so the routine takes the address of a variable.
The most commonly used type when working with strings is a long string. However, passing a long string as the Buffer parameter does not produce the correct result. Long strings contain a size, a reference count, and a pointer to the characters in the string. Consequently, dereferencing a long string does not result in only the pointer element. What you need to do is first cast the string to a Pointer or PChar, and then dereference it. For example:

procedure caststring;

var
fs: TFileStream;
const
s: string = "Hello";
begin
fs := TFileStream.Create("temp.txt", fmCreate or fmOpenWrite);
fs.Write(s, Length(s)); // this will give you garbage
fs.Write(PChar(s)^, Length(s)); // this is the correct way
end;



 
Stakan ©   (2006-07-24 18:38) [26]

Ещё бывает неплохо читать исходники:

procedure TStrings.LoadFromStream(Stream: TStream);
var
 Size: Integer;
 S: string;
begin
 BeginUpdate;
 try
   Size := Stream.Size - Stream.Position;
   SetString(S, nil, Size);
   Stream.Read(Pointer(S)^, Size);
   SetTextStr(S);
 finally
   EndUpdate;
 end;
end;


 
ps2006 ©   (2006-07-24 18:47) [27]

> Если говорить про "вообще" и про "универсальность" и про "как лучше", то скажу, что лучше сразу создавать экземпляр TStringStream, а не TMemoryStream? чтобы не маяться потом с перегонкой байтов и битов туда-сюда.

нет, не лучше - не всегда в потоке находятся одни стринги (у меня как раз такой случай).

Для себя я выяснил следующее:
если попадается ситуация, когда некая процедура возвращает данные в буфер, и эти данные нужно загнать в стринговую переменную, то лучшим решением будет следующее:

 SetLength(s, n);
 ПроцедураЧтенияВБуфер(s[1], n); // ну или m вместо n

То же касается и записи:
 ПроцедураЗаписиИзБуфера(s[1], n); // ну или Length(s) вместо n

(IMHO)


 
Reindeer Moss Eater ©   (2006-07-24 18:51) [28]

Ну и в чем был смысл исходного вопроса?


 
Loginov Dmitry ©   (2006-07-24 19:25) [29]

> Stakan ©   (24.07.06 18:33) [25]


Ну ладно, сдаюсь, был не прав. Как говориться, в споре рождается истина, и мы становимся более просвещенными. Не буду раскрывать причины такого заскока, т.к. самому смешно становится. Спасибо за науку!


 
GrayFace ©   (2006-07-24 23:44) [30]

ps2006 ©   (24.07.06 17:02) [17]
Я конечно могу ошибаться насчет красоты, тогда укажите свои аргументы "за" и "против"

Против - то, что если включена проверка на выход за границы массива может вылететь exception при пустой строке.
ИМХО, shortstring"и - от лукавого, о них не стоит заботиться, надо просто запретить подачу их в качестве аргументов функций в своих модулях (есть, помнится, такая директива компиллятора).


 
ps2006 ©   (2006-07-25 16:45) [31]

GrayFace ©   (24.07.06 23:44)
Против - то, что если включена проверка на выход за границы массива может вылететь exception при пустой строке.

Насколько я понимаю - при обьявлении переменной типа shortstring, если не указывать размер, т.е. так:
var
 s: string;

это будет эквивалентно
 s: string[255];

т.е. exception не выскочит. Поправьте, если я неправ


 
GrayFace ©   (2006-07-26 04:58) [32]

Я про обычные string"и - AnsiString. Я не проверял, но по идее тут должно выскочить.



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

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

Наверх





Память: 0.53 MB
Время: 0.049 c
15-1152965102
Андрей Пазик
2006-07-15 16:05
2006.08.13
Вот ТАК! нужно бороться с коррупцией


2-1153731983
ps2006
2006-07-24 13:06
2006.08.13
Непростой вопрос по string


3-1149593377
Fiallo4ka
2006-06-06 15:29
2006.08.13
связи в таблицах


3-1149738973
Soi
2006-06-08 07:56
2006.08.13
Экспорт данных из одной таблицы в другую


2-1153987406
Константин_
2006-07-27 12:03
2006.08.13
Как запретить обновление отображения формы?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский