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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.61 MB
Время: 0.014 c
2-1144724162
Laymer
2006-04-11 06:56
2006.04.23
FastReport


6-1136908622
GanibalLector
2006-01-10 18:57
2006.04.23
Select (Socket API)


2-1144405937
Максим_86
2006-04-07 14:32
2006.04.23
Поместить иконку на панель задач


2-1144753994
ffo
2006-04-11 15:13
2006.04.23
Допишите строку!!!!!!!!


15-1144081818
Mozart
2006-04-03 20:30
2006.04.23
А как на западе с лицензионным ПО (подумал я)....





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