Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Посимвольно формировать 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]}

Что-то не очень верится...


Наверх

Титульная страница Поиск, карта сайта Написать письмо