![]() |
1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!
![]() |
777 |
![]() ![]()
Сообщение
#1
|
Новичок ![]() Группа: Пользователи Сообщений: 19 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Нужно составить программу во FREE Паскале, которая из текстового файла забирает все имеющиеся в нём Интернет ссылки, и выводит их на экран + сохраняет их в другой текстовый файл! Чесно скажу, я учусь на заочном, второй семестр на занятиях полностью отсутствовал из за работы, и сейчас на работе такой завал, сто вникать в Паскаль просто нет возможности! Пожалуйста, помогите! Что такое программа Паскаль я узнал четыре дня назад, на лабораторной работе по информатике...
|
![]() ![]() |
volvo |
![]()
Сообщение
#2
|
Гость ![]() |
Цитата мне очень хочется повторить свою просьбочку, написать что каждая строка в программе обозначает. Я готов рассмотреть, как предложил Lapp, сначала разбить программу на части, если так проще понять... Смотри, я прокомментировал каждую строку своего кода, подробно прокомментировал... Попробуй разобраться, если что не понятно - то тогда уже можно разбить программу на подзадачи... Итак: вот прокомментированный код (в аттаче - тот же код, но без комментариев, можно сохранить файл к себе на диск, откомпилировать и проверить). У меня в программе ссылки вида www.google.com дополняются префиксом http://, а не https и не ftp. Program DZ;
{$mode objfpc}
uses
classes,
regexpr, sysutils, strutils;
// Ну, описания переменных, используемых в программе - это понятно...
var
re: TRegExprEngine;
s, subs, sLink, f_n: AnsiString;
ok: boolean;
index, len: longint;
sL_In, sL_Out: TStringList;
begin
// Итак, начинаем:
// Первым делом создаем два StringList-а (есть в ObjectPascal-е
// такой удобны для хранения строк класс) - первый для исходного
// текста, во второй "будем бросать кости", в смысле, выдернутые
// из текста ссылки
sL_In := TStringList.Create;
sL_Out := TStringList.Create;
// Теперь в защищенном блоке (даже если произойдет какая-нибудь ошибка,
// удалить-то созданные StringList-ы все равно надо), поэтому код, который
// может вызвать ошибку, пишем в секции try (попробуем выполнить, в смысле),
// а то, что ГАРАНТИРОВАННО должно произойти, даже если программа завершится
// с ошибкой - в секции finally
try
// Что же мы тут делаем?
// Для начала просим пользователя ввести название файла, который
// будем обрабатывать:
write('Enter file name: '); readln(f_n);
// Теперь заталкиваем содержимое этого файла в первый StringList...
sL_In.LoadFromFile(f_n);
// А вот теперь - внимательно. Это важный момент: берем то, что прочитали
// (sL_In.Text), заменяем в этом тексте "www." на "http://www." (будем
// надеяться, что ссылок на ww2.что_то в файле нет, только www.). Флажок
// rfReplaceAll заставляет функцию StringReplace изменить все вхождения,
// а не завершить выполнение после первой замены.
// Но стоп. Что же у нас получилось? Если адрес был записан в виде
// www.site.com, то все в порядке, будет добавлен протокол и получится
// httр://www.site.com, если сайт был записан как httр://site.com - тоже
// будет все в порядке, www не присутствует, ничего вообще меняться
// не будет. А что, если httр://www.site.com? Ведь после изменения у нас
// выйдет вот такой бред: httр://httр://www.site.com !!!
// Для этого добавлена в следующей строке еще одна замена: если есть
// дублирование протокола "http://http://", то исправим его, чтоб осталось
// "http://" один раз.
s := StringReplace(
StringReplace(sL_In.Text, 'www.', 'http://www.', [rfReplaceAll]),
'http://http://', 'http://', [rfReplaceAll]
);
// Дальше - генерируем новое регулярное выражение, которое в заданном тексте
// будет искать определенную последовательность символов. Я здесь задал такое
// выражение, которое будет искать правильно оформленную http:// -ссылку
ok := GenerateRegExprEngine('http://([\w+?\.\w+])+([a-zA-z0-9\~\!\@\#\$\%\^\&\*\(\)\_\-\=\+\\\/\?\.\:\;\"\,]*)?',[],re);
// В переменной Ok вернулся признак удачного создания регулярки.
// Если там false - то сообщаем о неудаче и заканчиваем работу
if not ok then writeln('error: init regexp')
else
begin
// Если пришли сюда - значит, регулярное выражение было создано. Идем дальше.
// Ну, вот тут я просто перестраховался, работал с копией текста
// из файла (subs), а не с самим текстом (s).
subs := s;
// До тех пор, пока есть что проверять (пока текст не обработан полностью)
while Length (subs) > 0 do
begin
// Натравливаем на этот текст регулярку. Если последовательность символов,
// которая является ссылкой, обнаружена - то в index вернется индекс
// её первого символа, а в len - длинна.
if RegExprPos(re, PChar(subs), index, len) then
begin
// Угу, ссылка найдена. Копируем ее из текста в отдельную переменную
sLink := Copy(subs, index + 1, len);
// Проверяем, есть ли она уже в списке ссылок?
// Если нету - то вернется (-1)
if sL_Out.IndexOf(sLink) = -1 then
begin
// Ссылка встетилась впервые, добавляем ее к списку ссылок
// и, заодно, выводим на экран.
sL_Out.Add(sLink);
writeln(sLink);
end;
// А теперь - просто, берем и удаляем из "рабочего" текста кусок,
// в котором только что была найдена ссылка, чтоб в нём же больше
// не искать... Таким образом "продвигаемся" вперед по тексту -
// удаляем из начала => продвигаемся к концу
subs := RightStr(subs, Length(subs) - index - len);
end
// Стоп. В оставшемся куске текста регулярка не нашла ссылку...
// Выходим из цикла
else
break;
end;
// Всё, цикл поиска ссылок закончился. Что осталось сделать?
// Правильно, удалить регулярку...
DestroyRegExprEngine(re);
// ..., спросить у пользователя куда сохранять файл с результатами,
// и сохранить их, собственно:
write('File name to store results: '); readln(f_n);
sL_Out.SaveToFile(f_n);
end;
finally
// Это будет выполнено, либо когда все ссылки найдены и все
// завершилось благополучно, либо при первой же ошибке при выполнении
// программы.
sL_Out.Free;
sL_In.Free;
end;
// Всё, миссия завершена, выходим...
end.
Цитата В задании не оговаривалось что делать с двойными ссылками, я думаю можно оставить как проще, хотя было бы интересно узнать альтернативу простому. Если не обязательно обеспечивать уникальность ссылки - то условие if sL_Out.IndexOf(sLink) = -1 then // строка 88
можно просто убрать...Прикрепленные файлы ![]() |
777 |
![]()
Сообщение
#3
|
Новичок ![]() Группа: Пользователи Сообщений: 19 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Смотри, я прокомментировал каждую строку своего кода, подробно прокомментировал... Попробуй разобраться, если что не понятно - то тогда уже можно разбить программу на подзадачи... Даааааа!!! ![]() Я вечером попытаюсь это как-то переварить ![]() Ничего, если у меня будет очень много тупых вопросов, откровенно тупых, но без ответов на которые мне будет ещё сложнее??? |
![]() ![]() |
![]() |
Текстовая версия | 1.08.2025 17:31 |