1. Заголовок темы должен быть информативным. В противном случае тема удаляется ... 2. Все тексты программ должны помещаться в теги [code=pas] ... [/code]. 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.
Цитата
В задании не оговаривалось что делать с двойными ссылками, я думаю можно оставить как проще, хотя было бы интересно узнать альтернативу простому.
Если не обязательно обеспечивать уникальность ссылки - то условие