IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

 
 Ответить  Открыть новую тему 
> Анализ log-файла..., программа обработки огромного лог файла
сообщение
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Роман

Репутация: -  0  +


Собственно вот задание: Написать программу по разбивке и анализу содержимого файла отчета работы ПО (log-файла).
Необходимо проанализаровать и подсчитать запросы, а также вывести их в алфавитном порядке с подсчетом колическтва повторений.

Программа должна выдавать отчет о своей работе в виде:

Дата Запросы
25.04.2002 - 12
26.04.2002 - 10
27.04.2002 - 5
...

Всего было сделано (запросов) - 1679

Сортировка запросов:

Бухгалтерский учет - 25
Бухгалтерский журнал - 30
Экономика Томска - 6
Экономика Якутии - 1
...

Пример файла отчета работы программы wslog.txt
Сортировку запросов необходимо проводить по CGI-переменным
S21STR=
S21ALL=
Проблема в том что у меня во второй части программы (подсчет и сортировка самих текстовых запросов) переполняется массив... а вот как сделать без массива не пойму...


program Laba_2;
uses crt;
var
s2:string;
f,f1:text;
g:char;
a,x,i,j,q,p:integer;
zap,m:string;
n:array [1..1000] of byte;
zn:array [1..1000]of string[40];
s,s1:string[10];
begin
clrscr;
assign(f,'wslog.txt');
assign(f1,'output.txt');
reset(f);
rewrite(f1);
x:=0;
a:=0;
q:=0;
Readln(f,s1);
Repeat
Readln(f,s);
if (s<>s1) and (s1<>'') then {если строки не одинаковы,то считает кол-во запросов в день}
begin
Writeln(f1,s1,' - ',a);
x:=x+a;
a:=0;
s1:=s;
end
else a:=a+1;{иначе суммирует кол-во одинаковых строк}
until eof(f);
Writeln(f1,' vsego zaprosov :');
Writeln(f1,x);
Reset(f);
{S21STR}
Repeat
Readln(f,s2);
a:=pos('S21STR=',s2);
if a<>0 then
begin
a:=a+7;
zap:='';
if S2[a]='' then q:=q+1 else
Repeat
zap:=zap+s2[a]; {считывает послед.символы после 'S21STR=' до &}
a:=a+1;
Until s2[a]='&';
for i:=1 to 1000 do
begin
if zap=zn[i] then begin n[i]:=n[i]+1; break; end;
if zn[i]='' then begin zn[i]:=zap; inc(n[i]); break;
{считает кол-во запросов}
end;
end;
end;
until eof(f);

{S21ALL аналогично}

Repeat
Readln(f,s2);
a:=pos('S21ALL=',s2);
if a<>0 then
begin
a:=a+7;
zap:='';
if s2[a]='' then q:=q+1 else
Repeat
zap:=zap+s2[a];
a:=a+1;
Until s2[a]='&';
for i:=1 to 1000 do
begin
if zap=zn[i] then begin n[i]:=n[i]+1; break; end;
if zn[i]='' then begin zn[i]:=zap; inc(n[i]); break; end;
end;
end;
until eof(f);
{сортирует строки}
for i:=1000 downto 1 do
for j:=1 to i-1 do
if zn[j]>zn[j+1] then
begin {}
m:=zn[j+1]; p:=n[j+1];
zn[j+1]:=zn[j]; n[j+1]:=n[j];
zn[j]:=m; n[j]:=p;
end;
{выводит рез-ты в файл}
writeln(f1,' ',' ',q);{выводит кол-во пустых запрсов}
for i:=1 to 1000 do
if zn[i]<>'' then
writeln(f1,zn[i],' ',n[i]);
close(f);
close(f1);
end.


Прикрепленный файл  wslog.txt ( 408.21 килобайт ) Кол-во скачиваний: 538
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
Проблема в том что у меня во второй части программы (подсчет и сортировка самих текстовых запросов) переполняется массив
проблема возникнет раньше. К примеру, в твоем файле, который прикреплен - строка №1034 является проблемной. Ты прочтешь ее из файла, найдешь в ней подстроку 'S21STR=', а вот символа '&' уже не найдешь. Он вне досягаемости в Турбо-Паскале. Потому что находится на позиции №258 в строке, а прочтешь ты только 255 (больше в String просто не влезет). В итоге получишь банальный вылет программы.

Отсюда первый вопрос: уверен, что хочешь продолжать именно с использованием Турбо-Паскаля, и изобретать костыли, вместо того, чтоб взять нормальный компилятор и начать решать задачу? В зависимости от твоего ответа будем думать дальше: либо как обойти эти ограничения, либо... Какой компилятор использовать взамен (хотя тут, конечно, решение напрашивается само собой)...

Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Роман

Репутация: -  0  +


Цитата(IUnknown @ 28.05.2011 20:07) *

проблема возникнет раньше. К примеру, в твоем файле, который прикреплен - строка №1034 является проблемной. Ты прочтешь ее из файла, найдешь в ней подстроку 'S21STR=', а вот символа '&' уже не найдешь. Он вне досягаемости в Турбо-Паскале. Потому что находится на позиции №258 в строке, а прочтешь ты только 255 (больше в String просто не влезет). В итоге получишь банальный вылет программы.

Отсюда первый вопрос: уверен, что хочешь продолжать именно с использованием Турбо-Паскаля, и изобретать костыли, вместо того, чтоб взять нормальный компилятор и начать решать задачу? В зависимости от твоего ответа будем думать дальше: либо как обойти эти ограничения, либо... Какой компилятор использовать взамен (хотя тут, конечно, решение напрашивается само собой)...

ну можно попробовать другой компилятор. Как я понял вы имели ввиду FPC?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Да, я именно его имел в виду. Перекомпилируй свою программу в FPC с ключом {$H+} и увеличенным размером массивов (я сделал
const maxsize = 2000;
// ...
n:array [1..maxsize] of byte;
zn:array [1..maxsize]of string[40];
// и ниже по тексту все 1000 заменил на maxsize

), и чуть-чуть поправь вот этот цикл:

   a:=pos('S21ALL=',s2);
if a<>0 then
begin
a:=a+7;
zap:='';
if s2[a]='' then q:=q+1 else
Repeat
zap:=zap+s2[a];
a:=a+1;
Until s2[a]='&'; // <--- Вот это очень нехорошо...
, если в строке после S21STR не будет амперсанда - будет вылет опять же (такая строка - под номером 205 в твоем файле). Надо в Until добавить условие, чтоб проверялся конец строки:

   Until (a > length(s2)) or (s2[a]='&');
Ну, или запоминать в целочисленной переменной длину строки (чтоб каждый раз ее не вычислять), и сравнивать со значением этой переменной...

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

Хотя, по хорошему, и искать Pos-ом строки в FPC не нужно. Есть регулярные выражения, вытягивать из строки можно что хочешь и как хочешь.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Я.
****

Группа: Пользователи
Сообщений: 809
Пол: Мужской
Реальное имя: Саша

Репутация: -  11  +


Цитата
Хотя, по хорошему, и искать Pos-ом строки в FPC не нужно. Есть регулярные выражения, вытягивать из строки можно что хочешь и как хочешь.
Можно подробнее?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Что именно? Про регулярки? Есть модуль regexpr вот в этой папке: \FPC\2.4.2\units\{target}\regexpr, в нем присутствует все необходимое для работы с регэкспами. Можно прикрутить известный дельфийский модуль, если функционала regexpr не хватает.

Согласись, проще за один проход вытащить из строки дату/время/ключевые слова, чем бегать в поисках разных подстрок Pos-ом. А ведь при использовании Pos надо еще найти конец искомого текста, с чем как раз у автора были проблемы. Регулярное выражение от этой необходимости избавляет, сразу будет найден кусок текста, расположенный между определенными словами или символами.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Так... Ну, регэкспы в FPC - такие, что лучше б их вообще не было, поэтому...

...вот что получилось: (Показать/Скрыть)


Всё остальное (всего запросов, количество пустых запросов, что там еще нужно - добавь сам). Кстати, твоя программа некорректно считала количество дат. Посмотри внимательно, сколько строк в логе, и сколько тебе показывает "всего запросов" - увидишь о чем я.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Роман

Репутация: -  0  +


Спасибо, все перекомпилировал, все работает.

lstQueries.Add(copy (s, start + Length(Tags[ i ]),
finish - start - Length(Tags[ i ])));



Process (lstData, fout, @PrintData);
LstQueries.CustomSort(@MySort);
Process (lstQueries, fout, @PrintQuery);
lstData.Free;
lstQueries.Free;



function MySort(List: TStringList; Index1, Index2: Integer): Integer;
begin
if List[Index1] > List[Index2] then exit(1)
else
if List[Index1] = List[Index2] then exit(0);
exit(-1);
end;


Можно поподробнее как это работает?)

Сообщение отредактировано: Роман -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
Можно поподробнее как это работает?)
Что именно? Функция MySort - это самописная функция сортировки двух строк, которые находятся в StringList-е. Она должна возвращать 0, если строки равны, 1 - если первая строка больше второй, и (-1) - если наоборот, вторая строка больше первой. Потом, такая функция передается параметром в метод CustomSort, и производится сортировка строк StringList-а (все, что надо для сортировки - это знать, нужно ли менять местами 2 строки в определенный момент, так? Вот CustomSort и вызывает переданную ему функцию, чтобы понять, какая из строк больше, и в зависимости от направления сортировки, принимает - или не принимает - решение об обмене их местами). Посмотри исходники CustomSort - станет понятно, что там происходит...

Первый фрагмент - это добавление в список текста запроса. То есть, start - позиция начала одного из тегов, finish - позиция амперсанда (&), процитированная тобой строка вычленит собственно сам запрос (без тега, без знака "=" и без амперсанда), и добавит его в список.

А второй процитированный фрагмент - это сама "соль" программы:
   // для начала - печатаем все даты в файл. Причем для печати
// каждой из них используется функция PrintData.
// Это - потому, что я решил запросы оборачивать кавычками,
// а с датами этого делать не нужно.
Process (lstData, fout, @PrintData);

// Так. Даты напечатаны, теперь переходим к запросам.
// Сначала отсортируем их по алфавиту:
LstQueries.CustomSort(@MySort);

// Теперь уже отсортированный список выводим в тот же файл,
// но уже используя свою функцию, чтоб запросы брались в кавычки
Process (lstQueries, fout, @PrintQuery);

// Ну, и удаляем оба списка, разумеется...
lstData.Free;
lstQueries.Free;


Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Новичок
*

Группа: Пользователи
Сообщений: 15
Пол: Мужской
Реальное имя: Роман

Репутация: -  0  +


Спасибо теперь всё окончательно понятноsmile.gif Программа четко выполняет поставленную задачуsmile.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 25.04.2024 22:54
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name