![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Посимвольно формировать String [D7]
810 © (2005-05-25 06:20:00)Пишу простейшую функцию. Берет из первой строки i-тый симовол и приклеивает в конец второй строки.
-----------------------------------------------
var
s1:String;
s2:String;
i: integer;
begin
s1:='eiouirwulerjkq.knci34t934urlj,mvmdjgf';
s2:='';
FOR i:=1 To length(s1) DO
begin
{здесь действия, не затрагивающие значения s1[i]}
s2:=s2+s1[i];
end
result:=s2;
end;
-------------------------------------------------------
Проблема: s2 всегда пустая!!! Явно, что-то не так с типами.
Прошу ткнуть носом.
SergP. (2005-05-25 18:37:00) [1]
> В цикле иду от первого символа до последнего и если текущий
> символ = '.' то меняю на ','
А зачем? Есть же готовая процедура для поиска и замены....
sniknik (2005-05-25 18:28:00) [2]и еще проще это зделать sql запросом (наверное... ;), для jet например конвертация строки с числом и точкой в качестве разделителя в "истинное" число вообще пройдет "автоматом", про остальные поля не скажу (поэтому и "наверное")
sniknik (2005-05-25 18:15:00) [3]> Если я применю DecimalSeparator, то он (наверное) подействует глобально.
правильно. но можно обойти, прочитай внимательнее [11].
> Т.е. все равно придется заменять, тогда уже, точку на запятую при записи в TDbf2
неверно. достаточно заменить на чтото одно. в данном случае на точку т.к.
> В источнике сумма содержится в поле CHARACTER с разделителем '.' а в приемнике NUMERIC с разделителем ','
так примерно, если конечно этот TDbf аналогичен стандартным компонентам по методам (AsFloat/AsString).
DecimalSeparator:= '.'
WHILE [некоторое условие]
TDbf2.Append;
TDbf2Summa.AsFloat:= StrToFloat(TDbf1Sum.AsString);
{и другие поля с другими трансформациями (штук 15 полей)}
TDbf1.Next;
end;
if (TDbf2.State = dsEdit) or (TDbf2.State = dsInsert) then TDbf2.Post; {на случай пустой таблици, и едит конечно лишнее но пусть будет ;}
810 (2005-05-25 17:25:00) [4]Это тоже не помогает?
----------------------------------------------------------
Ну вот, начали пинать.....:-)))))) (шютка юмора)
Я ж начинающий. О нумерации стрингов с 1 не знал. Ибо самоучка.
Чтобы искать в хелпе, тоже надо знать, что ищешь. Кто ж мог предполагать, что есть DecimalSeparator..... Ведь если не знаешь как он называется - в хелпе фиг найдешь.
Лучше расскажу о задаче.
Задача очень маленькая. Программа по сути - насос из одной DBF в другую, но DBF эти - разных форматов. В источнике сумма содержится в поле CHARACTER с разделителем '.' а в приемнике NUMERIC с разделителем ','
Здесь вмешиваться никуда нельзя и повлиять ни на что - тоже. То есть, в данной "задаче" это - секция "Дано:"
Поскольку все очень просто, и чтобы не нагружать программу излишними фичами (типа БДЕ) я использую фришный компонент TDbf вместо TTable.
При закачке записей делаю:
{Активирую нужный индекс в TDbf1
Устанавливаю указатель на первую запись
по некоторому условию}
WHILE [некоторое условие]
TDbf2.Append;
TDbf2Summa.Value := StrTran(TRIM(TDbf1Sum.Value), '.' , ',' );
{и другие поля с другими трансформациями (штук 15 полей)}
TDbf2.Post;
TDbf1.Next;
end;
Если я применю DecimalSeparator, то он (наверное) подействует глобально. Т.е. все равно придется заменять, тогда уже, точку на запятую при записи в TDbf2. В этом могу и ошибаться, ибо как я говорил - новичок (надо попробовать....)
Ну, и все. В таблицах никогда не будет более пары-тройки тыщ записей (это с запасом на будущее), ибо в конце дня они принудительно очищаются и пакуются..... "Тормозов" не замечено,
хотя результирующая таблица висит в сетке и будут работать с ней ежедневно и одновременно не более 20 юзеров.
Спасибо всем, кто просвящал меня, "темного"
evvcom (2005-05-25 08:43:00) [5]
> При использовании StrToFloat() она ругается на точку.
есть function StrToFloat(const S: string; const FormatSettings: TFormatSettings): Extended; overload; и FormatSettings.DecimalSeparator. Это тоже не помогает?
sniknik (2005-05-25 08:40:00) [6]> При использовании StrToFloat() она ругается на точку. Приходится заменять.
исправь первопричину и ничего замешать будет не нужно. DecimalSeparator:= '.'; перед использованием и ругаться не будет. (в написании мог ошибится, если так иши в хелпе похожее)
begin...end (2005-05-25 08:10:00) [7]> 810 (25.05.05 07:59) [7]
> А почему именно так?
1. Прибавление очередного символа к строке каждый раз приводит к перераспределению памяти под строку. Это замедляет весь процесс, и особенно заметно это будет для больших по величине строк. Поскольку здесь размер строки-результата заранее известен (он равен размеру исходной строки), лучше сразу установить нужную длину результирующей строки (т.е. сразу выделить необходимую память) и обращаться к её символам.
2. Строки, которые не изменяются внутри функции (в данном случае -- s), лучше передавать с модификатором const. Это позволит компилятору сгенерировать более компактный и быстрый код.
3. Поскольку речь в данном случае идёт о замене одиночного символа на другой одиночный символ, то ss и sr лучше сделать типа Char, а не string. Так будет правильнее и быстрее.
MBo (2005-05-25 08:00:00) [8]см. в хелпе StringReplace
810 (2005-05-25 07:59:00) [9]начальное значение счётчика на 1
------------------------------------------
Да, действительно, это помогло. Кто бы знал .......
Но я бы сделал функцию примерно так:
------------------------------------------
А почему именно так? У вас есть время объяснить начинающему?
Все дело в жестко фиксированных размерах?
begin...end (2005-05-25 07:40:00) [10]> 810 (25.05.05 07:31) [5]
> For i:= 0To Length(s) do
> begin
> IF s[i]=ss Then r:=r+sr ELSE r:=r+s[i];
> end;
Нумерация символов в длинной строке начинается с единицы. Вы на первом проходе обращаеттесь к символу S[ 0], там, вероятно, оказывается символ #0, он прибавляется к строке r и является её завершающим символом. Нужно изменить в заголовке цикла начальное значение счётчика на 1.
Но я бы сделал функцию примерно так:
function StrTran(const s: string; ss, sr: Char): string;
var
I, L: Integer;
begin
L := Length(s);
SetLength(Result, L);
for I := 1 to L do
if s[I] = ss then
Result[I] := sr
else
Result[I] := s[I]
end.
810 (2005-05-25 07:31:00) [11]Вот РЕАЛЬНЫЙ код (copy + paste):
-----------------------------------------------------------------
function StrTran(s, ss, sr: string): string;
{
s - исходная строка например '156.50'
ss - заменяЕМЫЙ символ например '.'
sr - замещаЮЩИЙ символ например ','
}
var
i: integer;
r: string;
begin
i:=0;
r:=' ';
For i:=0 To Length(s) do
begin
IF s[i]=ss Then r:=r+sr ELSE r:=r+s[i];
end;
result:=string(PChar(r));
ShowMessage('Sum= '+r);
end;
-----------------------------------------------------------------
Вот этот ШоуМессадьж выдает мне пустую строку.
Инициализировать r пробелом пробовал - не помогает.
Antonn (2005-05-25 07:18:00) [12]хотя и так все работает...
Antonn (2005-05-25 07:10:00) [13]а поробуй временно не s2:='' а s2:=' '
810 (2005-05-25 07:03:00) [14]Этот код правильный...
---------------------------------------
Почему тогда s2 пустая?
А зачем именно в цикле копировать ?
> {здесь действия, не затрагивающие значения s1[i]}
Что-то не очень верится...
--------------------------------------------
Вообще-то функция замещает в символьной строке указанный символ другим указанным символом. Используется при конвертации символьных полей, содержащих значения денежных сумм типа "1235646.56" При использовании StrToFloat() она ругается на точку. Приходится заменять.
В цикле иду от первого символа до последнего и если текущий символ = '.' то меняю на ','
Skier (2005-05-25 06:51:00) [15]Этот код правильный...
А зачем именно в цикле копировать ?
> {здесь действия, не затрагивающие значения s1[i]}
Что-то не очень верится...