Форум: "Начинающим";
Текущий архив: 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.6 MB
Время: 0.013 c