Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.04.23;
Скачать: CL | DM;

Вниз

динамический двумерный массви   Найти похожие ветки 

 
Std ©   (2006-04-08 18:48) [0]


uses
 SysUtils;
var
arr:array of array of string;
r,i,j,n,q:integer;
str:string;
begin
randomize;
q:=1;
n:=0;
for I:=0 to 10 do
 begin
   r:=random(2);
   if r<1 then
     begin
       SetLength(arr,10,q);
       arr[i,n]:=inttostr(r);
       inc(q);
       inc(n);
     end;
 end;
for I :=0 to length(arr) do
 begin
   for j:= 0 to length("длинна подмасива") do
    writeln(arr[j]);
 end;
readln;
end.

вообщем нада создать массив массивов(двумерный массив) сколько в нем будет i-ых элементов известно(10), а вот сколько будет j-ых элементов заранее не известно. Вот чтото не могу я понять что и куда всунуть нада в код чтоб оно работало :(


 
begin...end ©   (2006-04-08 18:58) [1]

> нада создать массив массивов(двумерный массив) сколько в
> нем будет i-ых элементов известно(10), а вот сколько будет
> j-ых элементов заранее не известно.

var
 A: array [1..10] of array of string;


 
Std ©   (2006-04-08 19:09) [2]

в том то и дело что в var нада обявить только A:array of array of string;
а потом дальше уже указать размер большого массива, а потом размеры маленьких :(


 
Std ©   (2006-04-08 19:18) [3]

вот делаю вот так:

SetLength(arr,10);
n:=0;
q:=1;
for I:=0 to 9 do
 begin
   r:=random(2);
   n:=0;
   q:=1;
   if r<5 then
     begin
       SetLength(arr[i],q);
       arr[i,n]:=inttostr(r);
       inc(q);
       inc(n);
     end;
 end;

но добавляется оно вот так:
arr[0]
 |
 -->arr[0]=значение
arr[1]
 |
 -->arr[0]=пусто
 |
 -->arr[1]=значение
arr[2]
 |
 -->arr[0]=пусто
 |
 -->arr[0]=пусто
 |
 -->arr[1]=значение

такое впечетления что я не там делаю n:=0 q:=1
а куда его правильно всунуть не соображу никак :(


 
Anatoly Podgoretsky ©   (2006-04-08 19:21) [4]

Зачем нужен двухмерный массив, если q=1?


 
Std ©   (2006-04-08 19:26) [5]

ну q вроде как указывает сколько должно быть элементов в "маленьком" массиве. Если не правильно делаю подскажите пж как зделать правильно, а то уже пол дня сижу над этим массивом и ничерта н получается :(


 
Anatoly Podgoretsky ©   (2006-04-08 19:41) [6]

q=1=одномерный массив


 
Rial ©   (2006-04-08 19:44) [7]

program MyProject;
{$AppType  Console}
Type MyType=Array of Array of String;

procedure AllocArray(Out Arr:MyType;
                    Const Sizes:Array of Integer);
Var I,L:Integer;
begin
L:=Length(Sizes);
SetLength(Arr,L);
For I:=0 to L-1 do
 SetLength(Arr[I],Sizes[I]);
end;

Var Arr:MyType;
begin
Randomize;
AllocArray(Arr,[5,6,7,8]);
Arr[0,4]:="La-la !";
WriteLn(Arr[0,4]);
ReadLn;
end.


 
Std ©   (2006-04-08 19:54) [8]

Anatoly Podgoretsky
q это начальный размер второго массива.
большой массив указывается
SetLength(arr,10);
а q это уже начальный размер arr[0](маленького массива)

Rial
но тут же тоже приходится указывать размер AllocArray(Arr,[5,6,7,8]);
а я этого самог размера не знаю :(


 
Std ©   (2006-04-08 20:16) [9]

Ладно, попробую обрисовать саму задачу, може подскажете какойто другой алгоритм ее решения...
есть файл в нем каждая строка имеет формат
Дата,слово1,слово2,слово3
есть StringList в котором каждая строка это дата_начала_недели-дата_конца_недели(чтото типа 01.01.2006-07.01.2006)
нада проверить весь файл и сгруппировать строки из файла по неделям
Например:
в файле есть строки:
02.01.2006,слово1,слово2,слово3
03.01.2006,слово1,слово2,слово3
05.01.2006,слово1,слово2,слово3
10.04.2006,слово1,слово2,слово3
11.04.2006,слово1,слово2,слово3
12.04.2006,слово1,слово2,слово3
нада чтобы в результате получился массив вида:
arr[0]
 |
 -->arr2[0]=02.01.2006,слово1,слово2,слово3
 |
 -->arr2[1]=03.01.2006,слово1,слово2,слово3
 |
 -->arr2[2]=05.01.2006,слово1,слово2,слово3
arr[1]
 |
 -->arr2[0]=10.04.2006,слово1,слово2,слово3
 |
 -->arr2[0]=11.04.2006,слово1,слово2,слово3
 |
 -->arr2[0]=12.04.2006,слово1,слово2,слово3

вот как раз згруппировать в такой массив и не получается.
Подскажите пж кто нибуть как делать


 
Rial ©   (2006-04-08 21:12) [10]


Type TArr=Array of Array of String;

function BuildSL(Out Arr:TArr;Const SL:TStringList;
                Const FileName:String):Boolean;
{
SL - Тот самый список, в котором, однако, хнанятся только
даты окончания неделей.
В SL.Strings[0] хранится начальная дата.
}
Var FileSL:TStringList;//Данные фaйла
   P,I,J,K,L,LL:Integer;
   S:String;
begin
Result:=False;
FileSL:=TStringList.Create;
Try
 Try
  FileSL.LoadFromFile(FileName);
 Except
  Exit;
 end;
 FileSL.Sorted:=True;// =:= FileSL.Sort
 L:=FileSL.Count;
 LL:=SL.Count;
 SetLength(Arr,L);
 I:=0;
 J:=0;
 S:=SL.Strings[J];
 While (I<=L-1)and(Copy(FileSL.Strings[I],1,10)<S)do
  Inc(I);
 While (I<=L-1)and(J<LL-1) do begin
  P:=I;
  Inc(J);
  S:=SL.Strings[J];
  While (P<=L-1)and(Copy(FileSL.Strings[P],1,10)<S)do
   Inc(P);
  If (P>I)then
   SetLength(Arr[J-1],P-I);
  For K:=0 to P-I-1 do
   Arr[J-1][K]:=FileSL.Strings[I+K];
  I:=P;
 end;
 SetLength(Arr,J-1);
Finally
 FileSL.Free;
end;
Result:=True;
end;//BuildSL


Проверка:

Var SL:TStringList;
   Arr:TArr;
begin
SL:=TStringList.Create;
Try
 SL.LoadFromFile("2.txt");
 BuildSL(Arr,SL,"1.txt");
Finally
 SL.Free;
end;


<2.txt>
01.01.2006
03.01.2006
10.01.2006
10.04.2006
17.04.2006
<1.txt>
02.01.2006,слово1,слово2,слово3
03.01.2006,слово1,слово2,слово3
05.01.2006,слово1,слово2,слово3
10.04.2006,слово1,слово2,слово3
11.04.2006,слово1,слово2,слово3
12.04.2006,слово1,слово2,слово3

Все работает.


 
Std ©   (2006-04-09 00:43) [11]

2Rial
не работает. так как StringList который содержит дату начала и дату конца недели в одной строке в виде 01.01.2006-07.01.2006
т.е. список имеет вид:
01.01.2006-07.01.2006
08.01.2006-14.01.2006
15.01.2006-21.01.2006
и т.д.
если не сложно подскажите пж как переделать что бы работало.
а то уже сил нет весь день сидеть над этим куском кода :((


 
Rial ©   (2006-04-09 00:50) [12]

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

А ты воовще уверен, что тебе именно ТАК все нужно сделать ?..


 
Std ©   (2006-04-09 01:02) [13]

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


 
Rial ©   (2006-04-09 01:09) [14]


> повторяющиеся интервалы удаляются).

Вот это сбивает с толку.
Надо это понимать так, что ты первый раз по датам составляешь список интервалов недель, а потом опять ищешь, к какому интервалу каждая дата относится ?
А не проще ли тогда на этапе построения этих интервалов и распределить даты?


 
Std ©   (2006-04-09 01:14) [15]


> Надо это понимать так, что ты первый раз по датам составляешь
> список интервалов недель, а потом опять ищешь, к какому
> интервалу каждая дата относится ?

получается что так


> А не проще ли тогда на этапе построения этих интервалов
> и распределить даты?

насчет проще или нет не знаю, но вот быстрее будет работать точно, но вот как это реализовать хз.
да, и еще нада учесть что у юзера сепаратор даты может быть "." или ":" или "/"


 
Rial ©   (2006-04-09 01:29) [16]


Type TArr=Array of Array of String;

function PerformStr(Const S:String):String;
begin
Result:=Copy(S,7,4)+Copy(S,4,2)+Copy(S,1,2);
end;

function BuildSL(Out Arr:TArr;Const SL:TStringList;
                Const FileName:String):Boolean;
Var FileSL:TStringList;//Данные фaйла
   P,I,J,K,L,LL:Integer;
   S:String;
begin
Result:=False;
FileSL:=TStringList.Create;
Try
 Try
  FileSL.LoadFromFile(FileName);
 Except
  Exit;
 end;
 L:=FileSL.Count;
 For I:=0 to L-1 do begin
  FileSL.Strings[I]:=PerformStr(Copy(FileSL.Strings[I],1,10))+FileSL.Strings[I];
 end;
 FileSL.Sort;
 For I:=0 to L-1 do begin
  S:=FileSL.Strings[I];
  FileSL.Strings[I]:=Copy(S,9,Length(S)-8);
 end;
 LL:=SL.Count;
 SetLength(Arr,L);
 I:=0;
 J:=0;
 While (I<=L-1)and(J<=LL-1) do begin
  P:=I;
  S:=PerformStr(Copy(SL.Strings[J],12,10));
  While (P<=L-1)and(PerformStr(Copy(FileSL.Strings[P],1,10))<=S)do
   Inc(P);
  If (P>I)then
   SetLength(Arr[J],P-I);
  For K:=0 to P-I-1 do
   Arr[J][K]:=FileSL.Strings[I+K];
  I:=P;
  Inc(J);
 end;
 SetLength(Arr,J);
Finally
 FileSL.Free;
end;
Result:=True;
end;//BuildSL



Var SL:TStringList;
   Arr:TArr;
begin
SL:=TStringList.Create;
Try
 SL.LoadFromFile("2.txt");
 BuildSL(Arr,SL,"1.txt");
Finally
 SL.Free;
end;

Входные файлы изменились
<1.txt>
02.01.2006,слово1,слово2,слово3
03.01.2006,слово1,слово2,слово3
11.01.2006,слово1,слово2,слово3
12.01.2006,слово1,слово2,слово3
05.01.2006,слово1,слово2,слово3
10.04.2006,слово1,слово2,слово3
11.04.2006,слово1,слово2,слово3
12.04.2006,слово1,слово2,слово3
18.04.2006,слово1,слово2,слово3
19.04.2006,слово1,слово2,слово3
<2.txt>
03.01.2006-09.01.2006
10.01.2006-16.01.2006
10.04.2006-16.04.2006
17.04.2006-23.04.2006

Размер кода возрос.
Надеюсь, это то, что тебе нужно.


 
Rial ©   (2006-04-09 01:32) [17]

А наличие различных сепараторов, если они состоят из одного символа,
ничего не изменит.
В этом можно убедиться, внимательно прочитав код.

Но суть задати немного бредовая получается.
Поэтому и код ужасно кривой получается у меня !..
В смысле, так, как ты ее хочешь реализовать.
Так что подумай над

> Std ©   (09.04.06 01:14) [15]


 
Std ©   (2006-04-09 01:56) [18]

опять не то немножко...
вобщем задание такое:
есть файл:

<date>,<open>,<high>,<low>,<close>,<volume>
19082004,100.00,104.06,95.96,100.34,22351898
20082004,101.01,109.08,100.50,108.31,11428600
23082004,110.75,113.48,109.05,109.40,9137200
24082004,111.24,111.60,103.57,104.87,7631300
25082004,104.96,108.00,103.88,106.00,4598900
26082004,104.95,107.95,104.66,107.91,3551000
27082004,108.10,108.62,105.69,106.15,3109000
30082004,105.28,105.49,102.01,102.01,2601000

необходимо сгруппировать данные по неделе и месяце.
при группировке в неделю выводится строка
<date>,<start>,<high>,<low>,<end>,<volume>
где <date> дата начала и дата конца недели
<start> число Первого дня недели
<high> максимальное из всех <high> за всю неделю
<low> минимальное число из всех <low> за всю неделю
<end> число последнего дня недели
<volume> сумма всех <volume> за неделю
при группировке в месяц необходимо выводить строку в виде
<date>,<start>,<high>,<low>,<end>,<volume>
где <date> дата начала и дата конца недели
<start> число Первого дня месяца
<high> максимальное из всех <high> за весь месяц
<low> минимальное число из всех <low> за весь месяц
<end> число последнего дня месяца
<volume> сумма всех <volume> за месяц

вот такую задачу потавил мне шеф...
если до понедельника не зделаю не видать мне отпуска еще неделю как минимум :(( а программированием я не часто занимаюся так что помогите пж...


 
Rial ©   (2006-04-09 02:17) [19]


> при группировке в месяц необходимо выводить строку в виде
> <date>,<start>,<high>,<low>,<end>,<volume>
> где <date> дата начала и дата конца недели


Так бы сразу все и выложил.

Тут все опять просто, но не сегодня и не в 2:16.


 
Std ©   (2006-04-09 02:29) [20]

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


 
Rial ©   (2006-04-09 02:30) [21]

Надеюсь, тут неискаженное условие (что- то я слышал о разделителях даты, а тут их нет).

Кстати, ести <date> есть дата начала и конца, то зачем <start> ?

Приведи пример формата сгруппированных срок для недель и месяцев.

Основная проблема должна была быть в вычислении даты начала недели с учетом года и месяца ...


 
Std ©   (2006-04-09 12:05) [22]

нее, <date> это просто одна дата в строке
<date>,<open>,<high>,<low>,<close>,<volume>
19082004,100.00,104.06,95.96,100.34,22351898
20082004,101.01,109.08,100.50,108.31,11428600
23082004,110.75,113.48,109.05,109.40,9137200
24082004,111.24,111.60,103.57,104.87,7631300
25082004,104.96,108.00,103.88,106.00,4598900
26082004,104.95,107.95,104.66,107.91,3551000
27082004,108.10,108.62,105.69,106.15,3109000
30082004,105.28,105.49,102.01,102.01,2601000
31082004,102.30,103.71,102.16,102.37,2461400
01092004,102.70,102.97,99.67,100.25,4573700
02092004,99.19,102.37,98.94,101.51,7566900
03092004,100.95,101.74,99.32,100.01,2578800
07092004,101.01,102.00,99.61,101.58,2926700
08092004,100.74,103.03,100.50,102.30,2495300
09092004,102.53,102.71,101.00,102.31,2032900
вот кусок файла
как видно в строке конкретный день
а при выводе необходимо вывести строку где указывается когда неделя начинается и когда заканчивается.
start должно быть число которое первое в этой неделе.
end это число последнего дня в неделе. остальные это максимальное(столбеца high) минимальное(столбца lov) и сумма за всю неделю(столбца volume)
для месяца выводить нада такую же строку но только start это первое число в месяце end последнее число в месяце

пример для приведенного куска файла:
недельная группировка
<date>,<open>,<high>,<low>,<close>,<volume>
16.08.2004-22.08.2004,100.00,109.08,95.961031,сумма_волумов_за_эту_неделю
23.08.2004-29.08.2004,110.75,108.62,103.57,106.15,сумма_волумов_за_эту_неделю
30.08.2004-05.09.2004,105.28,105.49,99.32,100.01,сумма_волумов_за_эту_неделю
06.09.2004-12.09.2004,101.01,103.03,99.61,102.31,сумма_волумов_за_эту_неделю
где:
<date> - дата начала и дата конца недели, <open>-первое число недели(по столбцу open), <high> - максимальное число недели(по столбцу high)
<low>-минимальное число недели(по столбцу low)
<close>-последнее число недели(по столбцу close), <volume> -- сумма всех волумов за неделю.
месячная группировка  
<date>,<open>,<high>,<low>,<close>,<volume>
01.08.2004-31.08.2004,100.00,113.48,95.96,102.37,сумма_волумов_за_этот_месяц
01.09.2004-30.09.2004,102.70,103.03,97.99,102.31,сумма_волумов_за_этот_месяц

где:
<date> - дата начала и дата конца месяца, <open>-первое число месяца(по столбцу open), <high> - максимальное число месяца(по столбцу high)
<low>-минимальное число месяца(по столбцу low)
<close>-последнее число месяца(по столбцу close), <volume> -- сумма всех волумов за месяц.

сепаратор даты мне нужен был для:
я брал строку, выбирал из нее дату, переводил ее в дату в формате dd.mm.yyyy и искал (и вот с этим самым была проблема, если у юзера в системе стоит сепаратор времени / то прога выдет шо dd.mm.yyyy не является датой)
ws:=StartOfTheMonth(dat); we:=EndOfTheMonth(dat); а потом сверял со строкой, если эта строка входит диапазон тих дат то пытался записать в массив(так и не записал :(  )
Это конешно ели будет использоватся такой метод как у меня, в других случаях думаю сепаратор не не важен...


 
Rial ©   (2006-04-09 22:03) [23]

Вот, чуть не целый час делал.
Мудрено получилось, но таково уж задание.

Если это не то, что нужно, то уж извини ...


unit DatenSort;

Interface

Uses Classes,SysUtils,Dialogs,Math;

function BuildDatenSort(Const InputSL,WeekSL,MonthSL:TStringList):Boolean;

Implementation
{
Формат входных данных:
19082004,100.00,104.06,95.96,100.34,22351898
20082004,101.01,109.08,100.50,108.31,11428600
23082004,110.75,113.48,109.05,109.40,9137200
24082004,111.24,111.60,103.57,104.87,7631300

Формат выходных данных
16.08.2004-22.08.2004,100.00,109.08,95.961031,сумма_волумов_за_эту_неделю
}

{$WARNINGS OFF}
function BuildDatenSort(Const InputSL,WeekSL,MonthSL:TStringList):Boolean;
Const NumOfMonth=12;
     NoInt=-1;

Var MonthData:Array [Boolean] of TDayTable;

//Ковертирование даты в индекс
function DateToIndex(Const Y,M,D:Int64):Int64;
Var N:Int64;
begin
N:=Y-1;
Result:=(N*365)+(N shr 2)+MonthData[(Y and 3)=0,M]+D;
end;

//Конвертация индекса в дату
function IndexToDateTime(Index:Int64):TDateTime;
Var Y,M,D:Int64;
   Fl:Boolean;
begin
Y:=Trunc(Index/365.25);
Dec(Index,(Y*365)+(Y shr 2));
Inc(Y);
Fl:=((Y and 3)=0);
M:=1;
While (MonthData[Fl,M]<Index) do
 Inc(M);
Dec(M);
D:=Index-MonthData[Fl,M];
TryEncodeDate(Y,M,D,Result);
end;

Const Delimeter=",";

Type TSingleData=record
     nD,nM,nY:Word;
     Index,iBW,iEW,iBM,iEM:Int64;
     Date:TDateTime;
     Open,High,Low,Close:Extended;
     Volume:Int64;
    end;

    TVoidData=Array[0..0]of TSingleData;

    ptVoidData=^TVoidData;

Var S,BufStr:String;
   J,P,Len:Integer;

//Процедура поиска разделителя или конца строки
procedure FindDelimeter;
begin
J:=P;
While (P<=Len)and(S[P]<>Delimeter) do
 Inc(P);
//Делаем выделение нужного участка и заменяем в нем символы "." на "," - формат
//действительного числа в Delphi/Pascal
BufStr:=StringReplace(Copy(S,J,P-J),".",",",[rfReplaceAll]);
Inc(P);
end;

function FloToStr(Const E:Extended):String;
begin
Result:=StringReplace(FloatToStr(E),",",".",[rfReplaceAll]);
end;

Var I,L:Integer;
   Size:Integer;
   ptV:ptVoidData;
   TmpDate:TDateTime;
   BB:Array[Boolean]of Word;
   N,eW,eM:Int64;
   WOpen,WHigh,WLow,WClose,MOpen,MHigh,MLow,MClose:Extended;
   WVolume,MVolume:Int64;
begin
Result:=False;
Try
 //Построение списка длин до указанного месяца
 BB[True]:=0;
 BB[False]:=0;
 For I:=1 to NumOfMonth do begin
  MonthData[True][I]:=BB[True];
  MonthData[False][I]:=BB[False];
  Inc(BB[True],MonthDays[True,I]);
  Inc(BB[False],MonthDays[False,I]);
 end;
 L:=InputSL.Count;
 //Сортировка дат по возрастанию
 For I:=0 to L-1 do begin
  S:=InputSL.Strings[I];
  InputSL.Strings[I]:=Copy(S,5,4)+Copy(S,3,2)+Copy(S,1,2)+S;
 end;
 InputSL.Sort;
 For I:=0 to L-1 do begin
  S:=InputSL.Strings[I];
  InputSL.Strings[I]:=Copy(S,9,Length(S)-8);
 end;
 //Выделение пемяти под массив
 Size:=SizeOf(TSingleData)*L;
 GetMem(ptV,Size);
 Try
  For I:=0 to L-1 do
   With ptV^[I] do begin
    S:=InputSL.Strings[I];//Кешируем строку
    Len:=Length(S);
    P:=1;                 //Позицию - на начало
    //Выделяем дату
    FindDelimeter;
    nD:=StrToInt(Copy(BufStr,1,2));
    nM:=StrToInt(Copy(BufStr,3,2));
    nY:=StrToInt(Copy(BufStr,5,4));
    TryEncodeDate(nY,nM,nD,Date);
    Index:=DayOfWeek(Date)-1; //День недели, с нуля
    N:=DateToIndex(nY,nM,nD); //Индекс даты
    iBW:=N-Index;  //Индекс начала недели
    iEW:=N+6;      //Индекс конца недели
    Index:=N;      //Индекс даты
    iBM:=Index-nD+1;                           //Индекс начала месяца
    iEM:=iBM+MonthDays[((nY and 3)=0),nM]-1;   //Индекс конца месяца
    //Выделяем Open
    FindDelimeter;
    Open:=StrToFloat(BufStr);
    //Выделяем High
    FindDelimeter;
    High:=StrToFloat(BufStr);
    //Выделяем Low
    FindDelimeter;
    Low:=StrToFloat(BufStr);
    //Выделяем Close
    FindDelimeter;
    Close:=StrToFloat(BufStr);
    //Выделяем Volume
    FindDelimeter;
    Volume:=StrToInt64(BufStr);
   end;//Все, массив с данными готов !
  eW:=0;
  eM:=0;
  WVolume:=NoInt;
  MVolume:=NoInt;
  For I:=0 to L-1 do
   With ptV^[I] do begin
    If(Index>eW)then begin
     If (WVolume<>NoInt)then
      WeekSL.Add(DateToStr(IndexToDateTime(iBW))+"-"+DateToStr(IndexToDateTime(iEW))+
                 Delimeter+FloToStr(WOpen)+Delimeter+FloToStr(WHigh)+Delimeter+FloToStr(WLow)+
                 Delimeter+FloToStr(WClose)+Delimeter+IntToStr(WVolume));
     //Запоминаем начальные данные
     WOpen:=Open;
     WHigh:=High;
     WLow:=Low;
     WClose:=Close;
     WVolume:=Volume;
     //Запись следующей даты окончания
     eW:=iEW;
    end else begin//Рассчет статистики
     WHigh:=Max(WHigh,High);
     WLow:=Min(WLow,Low);
     Inc(WVolume,Volume);
     WClose:=Close;
    end;
    If(Index>eM)then begin
     If (MVolume<>NoInt)then
      MonthSL.Add(DateToStr(IndexToDateTime(iBM))+"-"+DateToStr(IndexToDateTime(iEM))+
                  Delimeter+FloToStr(MOpen)+Delimeter+FloToStr(MHigh)+Delimeter+FloToStr(MLow)+
                  Delimeter+FloToStr(MClose)+Delimeter+IntToStr(MVolume));
     //Запоминаем начальные данные
     MOpen:=Open;
     MHigh:=High;
     MLow:=Low;
     MClose:=Close;
     MVolume:=Volume;
     //Запись следующей даты окончания
     eM:=iEM;
    end else begin//Рассчет статистики
     MHigh:=Max(MHigh,High);
     MLow:=Min(MLow,Low);
     Inc(MVolume,Volume);
     MClose:=Close;
    end;
   end;
 Finally
  FreeMem(ptV,Size);
 end;
Except
 Exit;
end;
Result:=True;
end;
{$WARNINGS ON}

end.



Пример работы:


program MyProject;

uses
 Classes,
 DatenSort in "DatenSort.pas";

Var InputSL,WeekSL,MonthSL:TStringList;
begin
InputSL:=TStringList.Create;
WeekSL:=TStringList.Create;
MonthSL:=TStringList.Create;
Try
 InputSL.LoadFromFile("1.txt");
 BuildDatenSort(InputSL,WeekSL,MonthSL);
 WeekSL.SaveToFile("2.txt");
 MonthSL.SaveToFile("3.txt");
Finally
 InputSL.Free;
 WeekSL.Free;
 MonthSL.Free;
end;
end.


<1.txt>
19082004,100.00,104.06,95.96,100.34,22351898
20082004,101.01,109.08,100.50,108.31,11428600
23082004,110.75,113.48,109.05,109.40,9137200
24082004,111.24,111.60,103.57,104.87,7631300
25082004,104.96,108.00,103.88,106.00,4598900
26082004,104.95,107.95,104.66,107.91,3551000
27082004,108.10,108.62,105.69,106.15,3109000
30082004,105.28,105.49,102.01,102.01,2601000
31082004,102.30,103.71,102.16,102.37,2461400
01092004,102.70,102.97,99.67,100.25,4573700
02092004,99.19,102.37,98.94,101.51,7566900
03092004,100.95,101.74,99.32,100.01,2578800
07092004,101.01,102.00,99.61,101.58,2926700
08092004,100.74,103.03,100.50,102.30,2495300
09092004,102.53,102.71,101.00,102.31,2032900


 
Std ©   (2006-04-09 23:33) [24]

спасибо, но вот даты в результате не правильные выводятся...
22.08.2004-01.09.2004,100,113.48,95.96,106,55147898
первые 3 интервала недель для этого файла вот такие:
16.08.2004-22.08.2004
23.08.2004-29.08.2004
30.08.2004-05.09.2004

и в результирующем файле нету первой недели, и первого месяца
тоесть файл с месяцвми начинается с 9 месяца(отсутствует 01.08.2004-31.08.2004)
и отсутствует первая неделя
16.08.2004-22.08.2004

З.Ы. неделя начинается понедельником. заканчивается воскресеньем


 
Std ©   (2006-04-09 23:39) [25]

а не проще было бы дату начала и дату конца недели находить как:
startOfTheWeek EndOfTheWeek(для недели)
StartOfTheMonth EndOfTheMonth(для месяца)


 
Rial ©   (2006-04-10 00:44) [26]


> спасибо, но вот даты в результате не правильные выводятся.
> ..
> 22.08.2004-01.09.2004,100,113.48,95.96,106,55147898
> первые 3 интервала недель для этого файла вот такие:
> 16.08.2004-22.08.2004
> 23.08.2004-29.08.2004
> 30.08.2004-05.09.2004
>
> и в результирующем файле нету первой недели, и первого месяца
> тоесть файл с месяцвми начинается с 9 месяца(отсутствует
> 01.08.2004-31.08.2004)
> и отсутствует первая неделя


Извиняюсь, поторопился, исправил.


unit DatenSort;

Interface

Uses Classes,SysUtils,Dialogs,Math;

function BuildDatenSort(Const InputSL,WeekSL,MonthSL:TStringList):Boolean;

Implementation
{
Формат входных данных:
19082004,100.00,104.06,95.96,100.34,22351898
20082004,101.01,109.08,100.50,108.31,11428600
23082004,110.75,113.48,109.05,109.40,9137200
24082004,111.24,111.60,103.57,104.87,7631300

Формат выходных данных
16.08.2004-22.08.2004,100.00,109.08,95.961031,сумма_волумов_за_эту_неделю
}

{$WARNINGS OFF}
function BuildDatenSort(Const InputSL,WeekSL,MonthSL:TStringList):Boolean;
Const NumOfMonth=12;
     NoInt=-1;

Var MonthData:Array [Boolean] of TDayTable;

//Ковертирование даты в индекс
function DateToIndex(Const Y,M,D:Int64):Int64;
Var N:Int64;
begin
N:=Y-1;
Result:=(N*365)+(N shr 2)+MonthData[(Y and 3)=0,M]+D;
end;

//Конвертация индекса в дату
function IndexToDateTime(Index:Int64):TDateTime;
Var Y,M,D:Int64;
   Fl:Boolean;
begin
Y:=Trunc(Index/365.25);
Dec(Index,(Y*365)+(Y shr 2));
Inc(Y);
Fl:=((Y and 3)=0);
M:=1;
While (MonthData[Fl,M]<Index) do
 Inc(M);
Dec(M);
D:=Index-MonthData[Fl,M];
TryEncodeDate(Y,M,D,Result);
end;

Const Delimeter=",";

Type TSingleData=record
     nD,nM,nY:Word;
     Index,iBW,iEW,iBM,iEM:Int64;
     Date:TDateTime;
     Open,High,Low,Close:Extended;
     Volume:Int64;
    end;

    TVoidData=Array[0..0]of TSingleData;

    ptVoidData=^TVoidData;

Var S,BufStr:String;
   J,P,Len:Integer;

//Процедура поиска разделителя или конца строки
procedure FindDelimeter;
begin
J:=P;
While (P<=Len)and(S[P]<>Delimeter) do
 Inc(P);
//Делаем выделение нужного участка и заменяем в нем символы "." на "," - формат
//действительного числа в Delphi/Pascal
BufStr:=StringReplace(Copy(S,J,P-J),".",",",[rfReplaceAll]);
Inc(P);
end;

function FloToStr(Const E:Extended):String;
begin
Result:=StringReplace(FloatToStr(E),",",".",[rfReplaceAll]);
end;

Var WOpen,WHigh,WLow,WClose,MOpen,MHigh,MLow,MClose:Extended;
   WVolume,MVolume:Int64;

procedure WriteToWeek(Const iBW,iEW:Int64);
begin
WeekSL.Add(DateToStr(IndexToDateTime(iBW))+"-"+DateToStr(IndexToDateTime(iEW))+
           Delimeter+FloToStr(WOpen)+Delimeter+FloToStr(WHigh)+Delimeter+FloToStr(WLow)+
           Delimeter+FloToStr(WClose)+Delimeter+IntToStr(WVolume));
end;

procedure WriteToMonth(Const iBM,iEM:Int64);
begin
MonthSL.Add(DateToStr(IndexToDateTime(iBM))+"-"+DateToStr(IndexToDateTime(iEM))+
            Delimeter+FloToStr(MOpen)+Delimeter+FloToStr(MHigh)+Delimeter+FloToStr(MLow)+
            Delimeter+FloToStr(MClose)+Delimeter+IntToStr(MVolume));
end;

Var I,L:Integer;
   Size:Integer;
   ptV:ptVoidData;
   BB:Array[Boolean]of Word;
   N,eW,eM:Int64;
begin
Result:=False;
Try
 //Построение списка длин до указанного месяца
 BB[True]:=0;
 BB[False]:=0;
 For I:=1 to NumOfMonth do begin
  MonthData[True][I]:=BB[True];
  MonthData[False][I]:=BB[False];
  Inc(BB[True],MonthDays[True,I]);
  Inc(BB[False],MonthDays[False,I]);
 end;
 L:=InputSL.Count;
 //Сортировка дат по возрастанию
 For I:=0 to L-1 do begin
  S:=InputSL.Strings[I];
  InputSL.Strings[I]:=Copy(S,5,4)+Copy(S,3,2)+Copy(S,1,2)+S;
 end;
 InputSL.Sort;
 For I:=0 to L-1 do begin
  S:=InputSL.Strings[I];
  InputSL.Strings[I]:=Copy(S,9,Length(S)-8);
 end;
 //Выделение пемяти под массив
 Size:=SizeOf(TSingleData)*L;
 GetMem(ptV,Size);
 Try
  For I:=0 to L-1 do
   With ptV^[I] do begin
    S:=InputSL.Strings[I];//Кешируем строку
    Len:=Length(S);
    P:=1;                 //Позицию - на начало
    //Выделяем дату
    FindDelimeter;
    nD:=StrToInt(Copy(BufStr,1,2));
    nM:=StrToInt(Copy(BufStr,3,2));
    nY:=StrToInt(Copy(BufStr,5,4));
    TryEncodeDate(nY,nM,nD,Date);
    Index:=DayOfWeek(Date)-1; //День недели, с нуля
    N:=DateToIndex(nY,nM,nD); //Индекс даты
    iBW:=N-Index;  //Индекс начала недели
    iEW:=iBW+6;      //Индекс конца недели
    Index:=N;      //Индекс даты
    iBM:=Index-nD+1;                           //Индекс начала месяца
    iEM:=iBM+MonthDays[((nY and 3)=0),nM]-1;   //Индекс конца месяца
    //Выделяем Open
    FindDelimeter;
    Open:=StrToFloat(BufStr);
    //Выделяем High
    FindDelimeter;
    High:=StrToFloat(BufStr);
    //Выделяем Low
    FindDelimeter;
    Low:=StrToFloat(BufStr);
    //Выделяем Close
    FindDelimeter;
    Close:=StrToFloat(BufStr);
    //Выделяем Volume
    FindDelimeter;
    Volume:=StrToInt64(BufStr);
   end;//Все, массив с данными готов !
  eW:=0;
  eM:=0;
  WVolume:=NoInt;
  MVolume:=NoInt;
  For I:=0 to L-1 do
   With ptV^[I] do begin
    If(Index>eW)then begin
     If (WVolume<>NoInt)then
      With ptV^[I-1] do
       WriteToWeek(iBW,iEW);
     //Запоминаем начальные данные
     WOpen:=Open;
     WHigh:=High;
     WLow:=Low;
     WClose:=Close;
     WVolume:=Volume;
     //Запись следующей даты окончания
     eW:=iEW;
    end else begin//Рассчет статистики
     WHigh:=Max(WHigh,High);
     WLow:=Min(WLow,Low);
     Inc(WVolume,Volume);
     WClose:=Close;
    end;
    If(Index>eM)then begin
     If (MVolume<>NoInt)then
      With ptV^[I-1] do
       WriteToMonth(iBM,iEM);
     //Запоминаем начальные данные
     MOpen:=Open;
     MHigh:=High;
     MLow:=Low;
     MClose:=Close;
     MVolume:=Volume;
     //Запись следующей даты окончания
     eM:=iEM;
    end else begin//Рассчет статистики
     MHigh:=Max(MHigh,High);
     MLow:=Min(MLow,Low);
     Inc(MVolume,Volume);
     MClose:=Close;
    end;
   end;
   With ptV^[L-1] do begin
    If(Index<=eW)and(WVolume<>NoInt)then
     WriteToWeek(iBW,iEW);
    If(Index>eM)and(MVolume<>NoInt)then
     WriteToMonth(iBM,iEM);
   end;
 Finally
  FreeMem(ptV,Size);
 end;
Except
 Exit;
end;
Result:=True;
end;
{$WARNINGS ON}

end.



> З.Ы. неделя начинается понедельником. заканчивается воскресеньем

Здорово, а я то полчаса думал, как же так, вроде со вторника всегда начаналась !..


> и отсутствует первая неделя
> 16.08.2004-22.08.2004
>

Готов поспорить. У меня календарь есть за 2004 г., он не врал никогда раньше:
15.08.2004-21.08.2004


> startOfTheWeek EndOfTheWeek(для недели)
> StartOfTheMonth EndOfTheMonth(для месяца)
>

Откровенно говоря, не знаю таких. Откуда взял?
Всегда все ручками делаю, если что.
В SysUtils нет.


 
Std ©   (2006-04-10 00:57) [27]


> Откровенно говоря, не знаю таких. Откуда взял?

в deteutils есть, правда делфа 2006

> Готов поспорить. У меня календарь есть за 2004 г., он не
> врал никогда раньше:
> 15.08.2004-21.08.2004


ага, с 15.08.2004-21.08.2004 если первый день недели это воскресенье а последний суббота(это ISO, тобиш американский стандарт
а у нас все на так как и них, или у них не так как у нас). Я вот глянул только что виндовйы календарь за 2004 год так там 16.08.2004-22.08.2004


 
Std ©   (2006-04-10 01:18) [28]

и еще вопрос где что подправить что бы число 100.00 так и выводилось а не 100 каквыводится в двнном случае?


 
Rial ©   (2006-04-10 02:36) [29]


function _FloatToStr(Const E:Extended;Const P1,P2:Integer;Const FloatFormat:TFloatFormat):String;
Var Buffer:Array[0..63] of Char;
begin
SetString(Result, Buffer, FloatToText(Buffer, E, fvExtended,
          FloatFormat, P1, P2));
end;



Тебе подойдет FloatFormat=ffFixed или ffNumber.

P1- количество значащих знаков до запятой,
P2- после запятой.

"100.00" =:= _FloatToStr(100.0,8,2,ffFixed);


 
Rial ©   (2006-04-10 02:42) [30]

P. S.


Index:=DayOfWeek(Date)-1;


Исправь на


Index:=DayOfWeek(Date)-2;


 
Std ©   (2006-04-10 11:41) [31]

шото после _FloatToStr вообще после заятой не выводится ниче..



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

Текущий архив: 2006.04.23;
Скачать: CL | DM;

Наверх




Память: 0.61 MB
Время: 0.038 c
2-1144313131
Der Nechk@ssoff
2006-04-06 12:45
2006.04.23
Он существует или нет?


2-1144395175
pavlov
2006-04-07 11:32
2006.04.23
макросы


2-1144332919
Sergio77
2006-04-06 18:15
2006.04.23
Объясните пожалуйста.


2-1144682165
новенький
2006-04-10 19:16
2006.04.23
котрольная сумма


2-1144392986
Bryak
2006-04-07 10:56
2006.04.23
progressBar!