понедельник, 20 октября 2014 г.

Занятие 2. Много нового.


На прошлом занятии мы научились писать простейшие программы, которые умеют выполнять действия, идущие одно за другим, никуда не сворачивая. Такие программы похожи на работника, который о своей работе говорит так: «Могу копать, могу не копать!» - не интересно…

Сегодня мы рассмотрим две программы. Одна будет проверять пароль, и не пускать нас дальше до тех пор, пока мы не введем его правильно.

А вторая программа будет угадывать любой, самый сложный пароль. 

Сразу скажу честно: да, с помощью второй программы вы могли бы взломать чужие Вконтакте, почту, сайт Пентагона и даже банкомат… если бы смогли запустить эту программу в нужном месте. А вот как прицепить эту программку к почтовому серверу я вам рассказывать не буду. И вообще: взлом уголовно наказуем. А мы – приличные люди, не нарушающие законов.

Итак, первая задача: написать программу, которая будет запрашивать пароль. Если пароль введен верно – написать «Добро пожаловать», если не верно – вернуться к вводу пароля.

Начинаем мы с определения количества и типов переменных. Нам надо две переменных, которые будут содержать более, чем один символ, буквы и цифры. Значит, это будут переменные типа 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;            - если а [ ]= этому символу, запомнить его в b], если нет – ничего не делать.

assign(g,'output.txt');               - готовим файл для вывода данных
rewrite(g);
For i:=1 to n do                   – печатаем в него все найденные символы
write(g, b[i]);

close (g);                                - закрываем файл вывода

end.                                      – конец программы


Сохраните свою программу в ту же папку PR1.

Введите какой-нибудь набор больших и маленьких букв и цифр в файл Input.txt и сохраните его.

Запустите программу. Откройте файл вывода. Получилось? Классно!

Самостоятельная работа:
  1. Почему при использовании внешних файлов нужно сохранять программу в папку с этими файлами?
  2. Что означает строчка a:array[1..10] of Real; ?
  3. Какими строками в программе подготовить считывание информации из внешнего файла?
  4. Какие ДВЕ команды общие при работе с внешними файлами ввода и вывода?
  5. Напишите программу, которая будет считывать символы из файла ввода информации, и записывать их В ОБРАТНОМ ПОРЯДКЕ в файл вывода информации. Например: в файле ввода «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?

Комментариев нет:

Отправить комментарий