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