Главная страница
Навигация по странице:

  • Обязательно (!!!) необходимо делать формальную проверку считанных данных

  • 1. Ввод и вывод данных

  • 3. Подсчет времени работы программы

  • 4. Работа с клавиатурой.

  • Учебный план по специальности 230400 Информационные системы и технологии


    Скачать 346 Kb.
    НазваниеУчебный план по специальности 230400 Информационные системы и технологии
    Дата20.12.2022
    Размер346 Kb.
    Формат файлаdoc
    Имя файлаTP_Metod_ukaz_k_KR (2).doc
    ТипУчебный план
    #854753
    страница3 из 7
    1   2   3   4   5   6   7

    4. Методические рекомендации по разработке программного средства.

    4.1. Порядок решения задачи курсовой работы


    Приведенные ниже правила носят рекомендательный характер, особенно это касается порядка в котором они перечислены, и могут быть переработаны как самим студентом, так и его руководителем.

    1. В самом начале разработки полезно использовать нижеприведенную универсальную заготовку.


    var

    i,j,k:longint;
    procedure readdata;

    begin

    assign(input,'');

    reset(input);

    end;
    procedure outdata;

    begin

    assign(output,'');

    rewrite(output);

    close(output)

    end;
    procedure initial;

    begin

    fillchar(i,?,0);

    end;
    procedure run;

    begin

    end;
    begin

    readdata;

    initial;

    run;

    outdata

    end.


    1. Затем следует очень внимательно прочитать условие задачи вашего варианта и постараться правильно (!!!) понять в чем заключается эта задача. Если что-то непонятно, в том числе и в формате ввода и вывода, то лучше задать вопрос руководителю курсовой работы. Несмотря на очевидность данного правила, очень часто студенты разрабатывают не соответствующие поставленной задачи алгоритмы.

    2. Если вы приступили к решению задачи и основная структура данных для нее вам ясна, то можно описать основные глобальные переменные и набрать процедуру readdata ввода данных, чтобы она считывала все параметры задачи так, как это указано в условии. Обязательно (!!!) необходимо делать формальную проверку считанных данных, то есть проверять соответствие введенных значений переменных условию задачи.

    3. В процедуре initial следует обнулить или присвоить соответствующие начальные значения всем (!!!) глобальным переменным, за исключением тех, которые будут использоваться в качестве параметров циклов. Затем запрограммировать вывод результата в процедуре outdata так, как это требуется в условии задачи.

    4. Используйте метод нисходящего программирования, т.е. запрограммируйте решение задачи в виде вызовов процедур и функций, которые пока следует описать в виде “заглушек” (мнимого или пустого действия или имитации настоящего действия, которое должна выполнять ваша программа). Таким образом, вы сможете отладить логику вашей программы, которая опять же должна оставаться “работающей”.

    5. Затем следует по одной набирать и отлаживать уже описанные процедуры и функции, добиваясь, чтобы свое действие каждая из них выполняла правильно в любом случае. например, поиск максимумов, сортировка массивов, комбинаторные подпрограммы и т.п. должны работать корректно при любых входных параметрах, вне зависимости от программного контекста, из которого они будут вызываться. Особое внимание следует уделять программированию вырожденных случаев. Так, если у вас в программе встречается деление, то сразу подумайте, не может ли делитель быть нулем и рассмотрите этот случай отдельно. При программировании циклов добивайтесь, чтобы зацикливания не происходило ни при каких начальных значениях переменных, использующихся в том или ином цикле, и т. д. и т.п.

    6. Если вы не придумали эффективного решения задачи, то запрограммируйте его по-простому: например, с помощью полного перебора или простой эвристики (приближенного решения в ряде случаев дающего точный ответ). Если и это сложно, то упростите себе задачу, то есть отбросьте условия, которые вам мешают или добейтесь, чтобы программа проходила на самых простых, например, вырожденных тестах (большинство параметров равны 0 или 1).

    7. Постарайтесь запустить ваш exe-файл непосредственно в операционной системе хотя бы для одного теста, чтобы убедиться в его работоспособности. Причины, по которым работающая в среде программирования программа, может оказаться не работоспособной в виде исполняемого файла заключаются, в основном, в неинициализации значений ряда переменных.

    4.2. Техника программирования задачи курсовой работы


    Рассмотрим подробнее некоторые технические приемы в программировании.

    1. Ввод и вывод данных

    В большинстве задач ввод данных и вывод результатов работы программы предлагается производить из текстового файла. Типичные ошибки при работе с текстовыми файлами заключаются в следующем:

    – в некоторых обращениях к процедурам ввода или вывода имя файловой переменной оказывается пропущенным;

    – при работе с файлом, открытым на запись, забывают в конце программы указать процедуру, закрывающую файл. В таком случае, создаваемый программой выходной файл скорее всего окажется пустым. Дело в том, что реальная запись данных на жесткий диск происходит или при выполнении команды close или, если количество выводимой информации велико, в момент переполнения буфера оперативной памяти, предназначенного для ускорения работы с файлами.

    Рассмотрим прием программирования ввода данных. В условии задачи ввод большого количества чисел может быть задан двумя способами. В первом способе сначала предлагается ввести количество чисел, а уж затем сами эти числа. В данном случае при программировании сложности не возникают. Во втором же случае количество чисел приходится определять в процессе их считывания. Пусть, например, для каждой строки входного файла требуется найти среднее арифметическое для чисел, расположенных в ней, количество чисел в каждой из строк и количество строк при этом неизвестно. Наиболее простым и правильным будет следующее решение такой задачи:

    while not eof(f) do

    begin

    n:=0;

    s:=0;

    while not eoln(f) do

    begin

    read(f, a);

    s:=s+a;

    n:=n+1

    end;

    if n>0 then writeln(s/n:0:2) else writeln

    end;
    2. Инициализация данных и создание динамических переменных

    Одна из типичных ошибок при программировании в том числе и олимпиадных задач — неинициализация глобальных переменных. Нулевые значения всем статическим переменным в программе присвоить достаточно легко. Сделать это можно, например, так, как было показано в процедуре initial в “универсальной программе ”, а именно:

    fillchar(i,ofs(Last)-ofs(i)+sizeof(Last),0)

    Здесь i — имя обязательно первой из описанных в программе переменных, Last— последней. Таким образом данная стандартная процедура заполнит нулями все байты памяти, которые используют статические переменные. После выполнения этой операции все числовые переменные, в том числе и элементы массивов, получат нулевые значения, всем символьным будет присвоен символ с кодом 0, а всем строковым — пустые строки, так как в байт, отвечающий за длину строки также занесен ноль и т.д. Если же количество глобальных переменных в программе невелико и не для всех из них ноль подходит в качестве начального значения, то инициализацию можно проводить для каждой переменной в отдельности. Для простых переменных это можно делать с помощью оператора присваивания или путем описания переменных как типизированных констант (в разделе описаний const, но с одновременным указанием и типа переменной и ее значения). Для массивов— с использованием все той же процедуры fillchar, но в пределах конкретного массива. Например:

    var a:array[1..1000]of integer;

    c:array[1..10000]of char;

    begin

    fillchar(a,sizeof(a),0);{заполняем массив a нулями}

    fillchar(с,sizeof(с),'+');{заполняем символом плюс массив с}



    end.

    К сожалению, таким способом ненулевые значения можно присвоить лишь массивам, элементы которых по размеру не превосходят один байт (типы byte, shortint, char, boolean). Значения элементов массивов других типов задавать приходится в цикле. Однако, если два массива одного и того же типа требуется проинициализировать одинаково, то заполнить в цикле можно только один из них, а второму массиву просто присвоить первый (присваивание — единственная допустимая операция над составными переменными, такими как массив, как над целыми объектами). Иногда массивы удобно описывать и задавать в разделе констант путем непосредственного перечисления значений всех элементов массивов.

    Как уже говорилось выше, для размещения всех глобальных переменных программе отводится не более 64 килобайт оперативной памяти. Однако при решении задач иногда требуется завести несколько массивов, размер каждого из которых не менее 32 килобайт. Покажем, как достаточно просто решить подобную проблему:

    const n=150;

    type aa=array[1..n,1..n] of integer;

    var a:aa; {a - массив}

    b:^aa;{b - указатель на массив}

    i,j:integer;

    begin

    fillchar(a,sizeof(a),0);

    new(b);{создание динамического массива}

    b^:=a;{копирование массива a в динамический массив}

    for i:=1 to n do

    for j:=1 to n do

    b^[i,j]:=i+j;{обращение к элементам динамического массива}



    end.

    Из примера видно, что работа с динамическими массивами не намного отличается от работы со статическими. Причем использовать данный прием можно “по образцу”, не вдаваясь в механизм работы с указателями. Если же размер двумерного массива превосходит 64 килобайта, то создать его с помощью динамических переменных можно, например, следующим образом:

    const n=500;

    m=100;

    type aa=array[1..n] of integer;

    var b:array[1..m] of ^aa;

    {b - массив указателей на одномерный массив}

    i,j:integer;

    begin

    for i:=1 to m do

    new(b[i]);{создание m динамических массивов}

    for i:=1 to m do

    for j:=1 to n do

    b[i]^[j]:=i+j;{обращение к элементам двумерного массива}



    end.

    Таким образом, использование динамических переменных позволяет практически не изменять алгоритм решения задачи в случае, когда использование статических массивов уже невозможно. Использование же таких переменных требует лишь небольшой аккуратности в их создании и корректного обращения с уже созданными динамическими переменными.
    3. Подсчет времени работы программы

    Во многих задачах курсовой работыирования определять время работы программы или сеанса пользователя. Покажем как это можно сделать
    var Timer:longint absolute $40:$6c;

    Timeold:longint;

    TimeinSec:real;

    begin

    Timeold:=Timer;

    ...

    ...

    ...

    TimeinSec := (Timer-Timeold)/18.2;
    end.

    Данная программа использует тот факт, что к значению четырехбайтовой целой переменной, расположенной по абсолютному адресу $40:$6С, раз в 1/18.2 секунды аппаратно прибавляется единица. Поэтому, если мы опишем в нашей программе переменную, привязав ее к этому адресу, то легко сможем определить время работы программы. А именно, запомнив в самом начале программы значение этой переменной (в нашем примере это оператор timeold:=timer), в процессе работы определить время выполнения в секундах можно по формуле (timer - timeold)/18.2.
    4. Работа с клавиатурой.

    Для организации интерактивного взаимодействия пользователя с программой необходимо уметь определять код нажатой клавиши. Для этого в Турбо Паскале используется функция ReadKey

    Клавиши на клавиатуре можно разделить на две группы. Первая группа, - обычные клавиши, возвращающие один сканкод, вторая группа, - спецклавиши, возвращающие два сканкода подряд при одном нажатии. Первый из этих двух сканкодов всегда символ #0. Для определения кодов клавиш можно применять предлагаемую ниже программу, или программу аналогичную по своему действию.
    PROGRAM Scan_Key;

    Uses Crt;

    Var

    ch:char;
    Begin

    Repeat

    ch:=ReadKey; { Приём первого символа }

    if ch=#0 { Если #0 то спецклавиша }

    then begin

    ch:=ReadKey; { Приём сканкода }

    writeln('спецклавиша: ', ord(ch));

    end

    else writeln('обычная клавиша: ', ord(ch));

    Until ch=#13; { #13 - ASCII-код клавиши "Enter" }

    End.
    Одной из полезных функций при работе с клавиатурой является функция KeyPressed. Эту функцию очень удобно применять при завершении работы программы, или прекращения действия определённого фрагмента по нажатии любой клавиши и т.д. Наиболее часто она применяется как условие завершения цикла с постусловием:

    Repeat Until KeyPressed;

    Возможно также применение этой функции как условия в цикле с предусловием:

    While not KeyPressed do <тело цикла>

    В этом случае тело цикла будет выполняться до тех пор, пока не будет нажата любая клавиша на клавиатуре.
    Program EX_1;

    Uses Crt;

    Var

    ch: char;

    done: boolean;
    Begin

    Writeln('---------------------');

    Writeln('F4 - включить звук');

    Writeln('F5 - выключить звук');

    Writeln('F10 - выход.');

    Writeln('---------------------');
    done:=false;

    Repeat

    ch:=ReadKey;

    if ch=#0 then

    begin

    ch:=ReadKey;

    case ch of

    #62: sound(5000); {включение звука клавишей F4}

    #63: nosound; {выключение звука клавишей F5}

    #68: done:=true; {выход - клавиша F10}

    end;

    end;

    Until done;

    End.
    Для улучшения понимания кода программы рекомендуется коды клавиш определить как константы в самом начале программы:

    program cursor_keys;

    uses Crt;

    const

    KEYUP=72;

    KEYDOWN=80;

    KEYLEFT=75;

    KEYRIGHT=77;

    KEYESC=27;

    KEYENTER=13;

    KEYSPACE=32;

    var key : char;

    begin

    writeln('Нажмите одну из курсорных клавиш ');

    key := readkey;

    if ord(key) <> 0 then writeln('обычная клавиша')

    else begin

    key := readkey;

    case ord(key) of

    KEYRIGHT: writeln('стрелка вправо');

    KEYLEFT: writeln('стрелка влево');

    KEYUP: writeln('стрелка вверх');

    KEYDOWN: writeln('стрелка вниз');

    else writeln('не стрелка');

    end;

    end;

    end.
    1   2   3   4   5   6   7


    написать администратору сайта