На прошлом
занятии мы научились писать простейшие программы, которые умеют выполнять
действия, идущие одно за другим, никуда не сворачивая. Такие программы похожи
на работника, который о своей работе говорит так: «Могу копать, могу не копать!»
- не интересно…
Сегодня мы
рассмотрим две программы. Одна будет проверять пароль, и не пускать нас дальше
до тех пор, пока мы не введем его правильно.
А вторая
программа будет угадывать любой, самый сложный пароль.
Сразу скажу честно: да,
с помощью второй программы вы могли бы взломать чужие Вконтакте, почту, сайт
Пентагона и даже банкомат… если бы смогли запустить эту программу в нужном
месте. А вот как прицепить эту программку к почтовому серверу я вам
рассказывать не буду. И вообще: взлом уголовно наказуем. А мы – приличные люди, не нарушающие законов.
Итак, первая
задача: написать программу, которая будет запрашивать пароль. Если пароль
введен верно – написать «Добро пожаловать», если не верно – вернуться к вводу
пароля.
Начинаем мы с
определения количества и типов переменных. Нам надо две переменных, которые
будут содержать более, чем один символ, буквы и цифры. Значит, это будут
переменные типа String.
Почему две? В
первую мы запомним правильный пароль, а во вторую будем записывать то, что
вводит пользователь.
Что мы будем
делать в ходе программы? Мы будем проверять, равны ли между собой наши
переменные. Если равны – выводить сообщение «Добро пожаловать», если нет –
отправлять пользователя на ввод пароля еще раз.
Для того, чтобы
вернуться по тексту программы назад, нам нужны метки в программе. Для этого мы
в «шапке» не забудем записать раздел Label, сразу в словарике посмотрите, что это за слово такое.
Поехали! Вы же
помните, то, что написано красным курсивом в
текст программы писать не надо?
Program password; - мы назвали
программу английским словом «пароль». Почему нет?
Label 1; - мы сможем вернуть программу «назад во времени».
Var
Pas1, pas2: String; - готовим две
переменные. Pas1 – правильный пароль, pas2 – то, что введет пользователь.
Begin
Writeln (‘Vvedi ishodnyj parol’); - надо же
нам с чем-то сравнивать…
Readln (pas1); - запомним
исходный пароль
1: Writeln (‘Vvedi parol’); - теперь мы спросим второй вариант пароля.
Readln (pas2); - запомним пароль,
который ввел пользователь.
If (pas1 = pas2) then – Если pas1 = pas2 тогда – это то,
что написано в этой строке.
Writeln (‘Dobro pojalovat’) – если условие строкой выше выполнилось – написать «Добро
пожаловать»
Else goto 1; - Иначе отправиться к метке 1. Кстати, где
она? Какая строка начинается с «1:»?
Readln; - приостановим программу, посмотрим на результат.
End. – закончим программу.
Набрали программу?
Заработало? Если да – браво.
Если нет, спорим, вы поставили «точку с запятой» после строки Writeln (‘Dobro pojalovat’) …
Дело
в том, что перед оператором Else НИКОГДА не ставят «точку с
запятой». Почему? «Точка с запятой» означает логическое окончание фразы.
Например: программа называется так-то; - фраза окончена. Напечатать на экране
вот то и вот это – фраза окончена. А что же там с Else?
Если( If) условие
выполнилось тогда (then) сделайте это иначе (Else) сделайте что-то другое ; - фраза
логически заканчивается только здесь. Вот почему ПЕРЕД Else «точку с запятой» не ставят.
А теперь давайте
сделаем нашу программу лучше. Вот, например, мы вводим пароль с клавиатуры, и
даже не прячем его. Трудно не угадать такой пароль, правда?
Изменим программу
так, чтоб:
- Пароль
загадывался в отдельном файле;
- Сообщение
о результате угадывания пароля выводилось в отдельный файл.
Для этих
улучшений надо проделать дополнительную работу:
- Создаем
на диске D: папку Pr1
- Создаем
в этой папке два пустых файла в редакторе «Блокнот», называем их «Input.txt» и «output.txt»
- Морально
готовимся к тому, что мы сохраним нашу программу в эту папку.
Открываем TP 7.0 и вводим программу.
Внимание!
Программа очень похожа на предыдущую, поэтому можно открыть старую программу и
просто внести в нее изменения. Изменения в программе я обозначу зеленым цветом.
Program
password2;
Label 1;
Var
pas1, pas2:
string;
f,g: text; - мы вводим две новых переменных для работы с файлом. У них новый тип - text
Begin
assign (f, 'input.txt'); - связываем в
сознании компа переменную f и файл input.txt
reset (f); - открываем текстовый файл для чтения
read (f, pas1); - считываем пароль
из файла input.txt и запоминаем его в переменную pas1
close (f); - закрываем текстовый
файл f
1: writeln
('vvedi parol');
readln(pas2);
assign (g, 'output.txt'); - связываем в
сознании компа переменную g и файл output.txt
rewrite(g); - открываем
текстовый файл для записи
If
(pas1=pas2) then
writeln (g,
'Ugadal!')
else
goto 1;
close (g); - закрываем текстовый файл
readln;
end.
Что мы имеем в
результате?
Наша папка PR1 на диске D: выглядит так:
В файл input.txt вы
можете вписать любой пароль, и программа будет бродить по кругу пока вы не
введете его правильно. После этого в файле output.txt появится надпись Ugadal!
Как сохранить
файл из Паскаля в нужную папку? В самом конце каждого списка файлов есть такие
точки:
Если на них
нажать, мы перейдем на один уровень вверх – в папку Паскаля. Поднимемся еще на
один уровень и так до тех пор, пока не увидим название нашей папки PR1 на диске D:
Итак, первая
задача решена.
Перейдем к
решению второй задачи. Напомню, наша вторая задача должна уметь подбирать любые
пароли. Давайте договоримся, что пароль у нас будет не длиннее 20 символов.
Просто чтоб набирать для проверки было меньше.
Сколько
переменных какого типа нам будут нужны?
Как взрослые
программисты, мы будем записывать пароль в один файл, а результат угадывания
выводить в другой файл. Значит, нам нужны переменные типа text, и их будет две – одна для файла ввода, другая для
файла вывода.
Мы договорились,
что наш пароль будет не длиннее 20 символов, значит, нам нужны 20 переменных
типа char для загадывания пароля и 20
переменных типа char для разгадывания пароля. Всего
40. Но мы не будем их вводить по одной,
мы сделаем два массива. Подробности – в "Словарике".
А еще нам нужны
будут переменные для счета: i,n типа integer.
И одна
переменная, которую мы будем использовать для подбора символов, типа char.
Теперь о идее
решения.
Сначала мы
откроем наш файл ввода данных и начнем считывать из него символы до тех пор,
пока символы в файле не закончатся. Каждый считанный символ мы будем запоминать
в массив а, в переменную со следующим по счету номером. Заодно будем
подсчитывать количество этих символов.
Потом мы будем
делать следующее: брать переменную а[ номер
будем менять постепенно] и сравнивать её со всеми возможными символами
подряд.
Кстати, хочу отметить, что есть определенный порядок расположения
символов. Сначала идут все цифры от 0 до 9. Потом все большие латинские буквы
от «A» до «Z», а потом все маленькие латинские буквы от «a» до «z».
Как только мы будем находить
совпадающий с а[ номер которого мы сейчас
рассматриваем] символ, мы будем присваивать переменной b[ того же самого номера, что и а] этот символ.
А когда мы их
всех переберем – выведем в файл вывода.
Поехали!
program Vzlom;
Var
f,g:text; -наши
переменные для текстовых файлов
a,b:array[1..20] of char; - это мы задали 20 переменных а и 20 переменных
b
p:char; - переменная для перебора символов
i,n:integer; -
переменные для счета
begin
i:=1; - номер первой а равен 1
n:=0; - мы пока не знаем, сколько символов в пароле
assign (f,'input.txt'); - готовим
файл ввода
reset(f); - открываем его для чтения
while not eof (f) do begin – пока файл
не кончится, делать…
read (f, a[i]); - читать символ и запоминать в а [ i ]
i:=i+1; - поменять
номер а на следующий
n:=n+1; - посчитать очередной символ
end; - уф!
Мы прочитали весь наш файл ввода. Все символы из него мы
запомнили в последовательность переменных a[1],
a[2],…, a[n]. А
получившееся в конце число n – это количество символов в
пароле.
close (f); - файл ввода можно закрывать.
For i:=1 to n do – для всех номеров от
1 до n делать…
For p:='0' to 'z' do – меняя
все возможные символы от '0' до
'z'
if a[i]=p then b[i]:=p; - если а [ i ]=
этому символу, запомнить его в b[ i ],
если нет – ничего не делать.
assign(g,'output.txt'); - готовим файл для вывода данных
rewrite(g);
For i:=1 to n do – печатаем в него все
найденные символы
write(g, b[i]);
close
(g); - закрываем файл вывода
end. –
конец программы
Сохраните свою программу в ту же папку PR1.
Введите какой-нибудь набор больших и маленьких букв и цифр в файл Input.txt и сохраните его.
Запустите программу. Откройте файл вывода. Получилось? Классно!
Самостоятельная работа:
- Почему
при использовании внешних файлов нужно сохранять программу в папку с этими
файлами?
- Что
означает строчка a:array[1..10] of Real; ?
- Какими строками в программе подготовить считывание
информации из внешнего файла?
- Какие ДВЕ команды общие при работе с внешними файлами
ввода и вывода?
- Напишите программу, которая будет считывать символы из
файла ввода информации, и записывать их В ОБРАТНОМ ПОРЯДКЕ в файл вывода
информации. Например: в файле ввода «1 2 3 4 5», тогда в файле вывода «5 4 3 2
1»
Подсказка:
Пусть у нас в файле
ввода n символов, причем n=5. После того, как мы заполним массив а, мы должны
заполнить массив b, взяв элементы массива а в обратном порядке. Массив b мы потом будем
выводить.
Если мы зададим такой
цикл:
For i:=1 to n do
For j:=n downto 1 do
b[ i
]:=a[ j ];
Что мы получим в итоге в массиве b?