next up previous
Next: About this document ... Up: Лабораторный практикум по информатике Previous: Библиотечные функции.

Циклы.

Их предназначение -- в многократном выполнении однообразных действий вплоть до выполнения определенных условий.

Для выполнения многократных вычислений с изменяющейся с определенным шагом переменной используется цикл for, а для действий, завершающихся лишь после выполнения какого-либо условия -- цикл while.

Цикл for имеет следующий вид: for(Нач.действия; Усл.; Операция){ Тело цикла }, где Нач.действия -- действия, которые выполняются при самом первом запуске цикла, чаще всего это присваивание переменной цикла определенного значения; Усл. -- условие, которое проверяется каждый раз в конце цикла, если оно не выполняется, цикл завершается; Операция -- действия, производящиеся каждый раз после невыполнения условия Усл.; Тело цикла -- действия, выполняющиеся в цикле. Любой из параметров в скобках цикла может отсутствовать (даже одновременно все три).

Итак, создадим программу, которая будет вычислять факториал числа n, введенного пользователем. Факториал $n$ ($n!$) -- произведение всех чисел от 1 до $n$.

Первый вариант factor1.c создадим по всем правилам организации цикла, т.е. вначале запросим пользователя ввести число n, затем организуем цикл от 1 до n, в котором будем умножать переменную-ответ на счетчик цикла. Составьте блок-схему программы. Вы на собственном опыте убедитесь, что для одной и той же блок-схемы можно создать множество реализаций программы. Наберите, откомпилируйте и посмотрите результаты выполнения всех вариантов программы.

Итак, первый вариант:

#include <stdio.h>
int n;

long factor(int n){
    int i;
    long f = 1;
    for(i = 2; i <= n; i++) f *= i;
    return f;
}

int main(){
    printf("Введите значение n\n");
    scanf("%d", &n);
    printf("Факториал %d равен %d\n", n, factor(n));
    return 0;
}

Здесь вводится тип данных <ong, позволяющий вместить большее число, чем тип int. Факториал -- быстрорастущая функция, поэтому уже при $n=32$ наша функция вернет неверное значение из-за того, что ответ будет больше, чем может вместиться в тип <ong.

Запустите программу и посмотрите, как она работает.

Теперь модифицируем нашу функцию factor. Скопируйте файл factor1.c в factor2.c командой cp factor1.c factor2.c или же сохраните его в текстовом редакторе под новым именем.

Сделаем так, чтобы факториал вычислялся в теле функции. Воспользуемся тем, что в разделе Операция цикла for можно писать любую функцию.

long factor(int n){
    long f = 1;
    for(; n > 0; f *= i--);
    return f;
}

Теперь мы воспользовались тем, что в функцию передается копия аргумента, т.е. внутри нее мы можем делать с ним все, что угодно.

Цикл for(; n > 0;) эквивалентен циклу while(n > 0). Сделаем еще одну модификацию, использующую этот цикл:

long factor(int n){
    long f=1;
    while(n > 0) f *= i--;
    return f;
}

Досрочно можно выйти из цикла командой break, а заставить его перейти к началу -- командой continue. Зная английский язык легко можно разобраться с программами.

Напишите программу, которая будет считать сумму квадратов первых $n$ чисел. Сначала составьте ее блок-схему. Подумайте, сколько переменных понадобится для программы. Не забывайте, что нужно по крайней мере две переменных: для хранения введенного числа $n$ и результата вычисления. Подумайте, нужна ли отдельная переменная для хранения счетчика цикла (посмотрите предыдущие примеры). Для вычисления степени числа используется оператор ^. Например, чтобы вычислить $x^2$, необходимо записать x2. Кроме того, для небольших степеней можно использовать вместо оператора возведения в степень многократное умножение (x*x). Обратите внимание на представление целых чисел в памяти компьютера. Если результат вычисления будет очень большим (например, когда вы введете 10000, на экране отобразится отрицательное число. Это не ошибка. Просто старший бит числа отражает его знак, а для хранения большого числа может понадобиться заполнить знаковый бит. Чтобы результат отображался всегда правильно, необходимо указать, что данная переменная беззнаковая, указав в ее определении unsigned, например, для беззнакового целого unsigned int.

Операции с файлами.

Для операций с файлами существует структура FILE. Команда fopen(char* n, char* m) (n -- имя файла (указатель на символьную строку, m -- режим доступа к файлу -- см. man fopen) возвращает указатель на эту структуру, который будет использоваться в командах ввода/вывода fscanf и fprintf. Синтаксис последних команд аналогичен scanf и printf за исключением того, что первым их аргументом идет указатель на структуру FILE.

Указатель -- это адрес переменной в памяти компьютера. С указателями следует обращаться осторожно, чтобы не уйти за пределы дозволенной области. Указатели очень удобно передавать вместо аргументов функций, если они занимают много места в памяти, т.к. на аргумент выделяется столько места, сколько он занимает, а указатель требует всего 2-4 байта. Чтобы получить по указателю содержимое данной величины, используется оператор *, а чтобы получить адрес переменной -- оператор t.

В этом задании вы научитесь совершать простые операции с файлами, кроме того, узнаете как передавать данные в программу посредством аргументов командной строки.

Функцию main мы всегда записывали, опуская аргументы. На самом деле, полный ее формат -- int main(int argc, void **argv), где argc -- количество аргументов функции, **argv -- указатель на указатель на структуру, хранящую аргументы командной строки. Доступ к указателю можно получить как через элемент массива (char* name = argv[2]), так и путем разыменования указателя (char* name = *argv++). Тип void* (указатель на ничто) необходимо явным образом преобразовать к любому необходимому типу данных, указав, например, int main(int argc, char **argv).

В нашей программе будет использоваться массив -- индексируемый набор данных одного типа. В нем будет храниться имя файла, с которым будет работать программа. Объявление char name[128] означает, что в памяти выделится блок в 128 байт (т.к. char занимает 1 байт), а его имя является указателем на первый элемент (name[0]). Обратите внимание, что нумерация массивов начинается с 0, а не с 1.

Итак, напишем программу, которая будет открывать файл (имя которого можно ввести как первый аргумент программы), записывать в него оставшиеся аргументы (если таковые есть), затем спрашивать у пользователя радиус круга и рисовать этот круг в том же файле.

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

Наберите данную программу (назовите ее file.c). Т.к. программа использует математическую функцию sqrt, возвращающую квадратный корень ее аргумента, необходимо сообщить компилятору, что объявление этой функции находится в файле math.h. Кроме того, этот файл не входит в стандартную библиотеку, поэтому компилятору нужно указать явно, что необходимо подключить математическую библиотеку ключом -lm (ключ пишется до имени файла с программой).

#include <stdio.h>
#include <math.h>

FILE *f;
char name[128];

void printstar(int r, int n){
    int i;
    fprintf(f, "   ");
    for (i = 0; i < n; i++) fprintf(f, " ");
    if (n != r){
        fprintf(f, "*");
        for (i = 2*(r-n)-1; i > 0; i--) fprintf(f, " ");
    }
    fprintf(f, "*\n");
} 

int main(char argc, char** argv){
    if (argc < 2){
        printf("Введите имя файла для записи\n");
        scanf("%s", name);
         }
    else strcpy(name, argv[1]);
    if ((f = fopen(name, "w")) == NULL){
        printf("Ошибка открытия файла\n");
        return -1;
        }
    fprintf(f, "Мой файл:\n");
    int a = 1;
    while (++a < argc) fprintf(f, "%s\n", argv[a]);

    unsigned char r;
    printf("Введите радиус круга\n");
    scanf("%d",&r);
    for(a = r; a > 0; a--) printstar(r, r - sqrt((double)(r*r - a*a)));
    for(a = 0; a <= r; a++ ) printstar(r, r - sqrt((double)(r*r - a*a)));
    fclose(f);    
    return 0;
}

Скомпилируйте программу (>cc -lm file.c -o file). Запустите ее сначала без аргументов (./file), а затем -- с несколькими аргументами (./file myfile arg1 arg2 arg3). Посмотрите выходной файл (в первом случае он будет носить имя, которое вы ему дадите в диалоге с программой, а во втором его именем будет первый аргумент командной строки).


\begin{answ}
\begin{itemize}
\item Почему ,,круг'' вытянут вдоль вертикальной ос...
...rintf(\ldots)}?
\item Какова роль функции \t{printstar}?
\end{itemize}\end{answ}

Теперь скопируйте файл с текстом программы в файл file1.c, откройте этот файл в текстовом редакторе, и измените его так, чтобы функция печатала в файл сумму квадратов целых чисел от 1 до $n$, беря значением $n$ первый аргумент командной строки, а именем файла -- второй аргумент. Если же программа была запущена без аргументов, число $n$ и имя файла следует запросить у пользователя.

Для получения числа используется функция atoi (напр., int i = atoi(argv[1])). Программирование на C. Создание интерактивных консольных программ. Теперь, когда мы научились составлять простые программы, попробуем более сложные. Для взаимодействия пользователя и компьютера используется множество элементов. Самый простой способ -- консольный ввод/вывод: программа запрашивает у пользователя необходимые данные, которые тот набирает на клавиатуре. Более сложный -- графический. Для запуска графических программ требуется графическая оболочка (Х), а также подключение к программе графических библиотек. Программирование графических программ несколько сложнее, чем консольных.

Простейшие интерактивные программы. Приветствие пользователя. Создайте программу, запрашивающую у пользователя его имя и приветствующую его по имени. Для начала составьте блок-схему программы, после этого -- приступайте к ее написанию.

Чтобы упростить себе работу, используйте готовые блоки из предыдущих программ. Редактировать несколько файлов сразу можно при помощи редактора >edit: зайдите в свою рабочую папку с файлами и наберите в командной строке >edit *.c. Откроется редактор, в котором каждый файл можно редактировать, активировав соответствующую вкладку.

Итак, для имени вам понадобится символьный массив длиной около 128 символов, ввод имени будет осуществляться при помощи команды scanf, а вывод данных -- printf.

Приветствие пользователя 2. Наверное, вы заметили, что при вводе имени при помощи функции scanf ввод производится до первого пробела, т.е. фамилию, имя и отчество так ввести не получится. Функция fgets позволяет вводить данные до символа ,,конец файла'' или символа новой строки (enter). Формат команды таков: fgets(char* BUFFER, int NUM, FILE *NAME), где BUFFER -- указатель на символьный массив (его длина должна быть не меньше NUM), NUM -- максимальное количество введенных символов, NAME -- указатель на файл, с которого следует производить считывание.

В Linux при запуске программы сразу открывается три файла: stdin (ввод), stdout (вывод) и stderr (поток ошибок). Для ввода имени вам необходимо считывать с файла stdin, который и надо будет указать третьим аргументом. Итак, необходимо будет строку считывания имени заменить на fgets(name, sizeof name, stdin), если символьный массив вы назвали name.

Файловые операции. Создадим программу, позволяющую составлять ,,картотеку'' пользователей, куда будет заносится их фамилия, имя и дата рождения.

В начале программы объявите переменные для хранения фамилии, имени и даты рождения, например, так: char firstname[32], lastname[32], birthdate[32]. Не забудьте подключить библиотеку стандартного ввода/вывода stdio.h. Еще нам понадобится переменная-символ, в которой будет храниться введенная команда (char command) и указатель на файл-базу данных (FILE* file).

Далее, нам понадобятся две функции: распечатывающая весь список (void printcard()) и добавляющая пользователя (void newuser).

Функция, добавляющая пользователя, должна запросить ввести его фамилию, имя и дату рождения, а затем оператором fprintf записать эти данные в файл-базу данных.

Функция, печатающая ,,картотеку'', должна для начала ,,перемотать'' файл-базу данных на начало (функция rewind(file)), затем считать из него первую запись (функция fscanf) и в цикле печатать/считывать информацию, вплоть до достижения конца файла. Здесь удобнее использовать цикл do ... while:

do printf("%s\t%s\t%s\n", firstname, lastname, birthdate);
while(fscanf(file,"%s %s %s\n", firstname, lastname, birthdate)!=EOF);

Этот цикл сначала выполняет свое тело, а потом проверяет условие. Нам необходимо считать данные вплоть до конца файла, для этого в операторе проверки условия выполнения цикла while мы считываем следующую запись. Если предыдущая запись -- последняя, функция fscanf возвращает признак конца файла EOF, тогда цикл прекращается.

Теперь дошла очередь и до основной программы. Во-первых, откроем файл базы данных (назовите его как угодно, в данном случае откроется файл card). Так как при первом запуске файла может не существовать, необходимо, чтобы в этом случае он создался. Если же запуск не первый, файл должен открыться для дописывания данных в его конец. Для этого используем функцию open со вторым аргументом "a+" -- открыть для дописи и чтения: file=fopen("card", "a+");.

Теперь создадим цикл считывания символа и проверки, является ли введенный символ командой. Этот цикл подолжается до тех пор, пока не будет введено q. Для такого бесконечного цикла удобно использовать скобки do ... while.

Проверку введенной команды проще осуществлять при помощи функции switch, за которой следует последовательность вариантов case ... : ... ; break. Если аргумент функции совпадает с аргументом какого-либо case, выполняются все действия после этого case вплоть до оператора break, выходящего из оператора проверки.

Итак, последний участок функции main можно оформить так:

do{
    printf("Введите команду\n(n - новый пользователь, p - отобразить картотеку, q - выход):\n");
    command = getchar();
    switch(command){
        case 'n': newuser(); break;
        case 'p': printcard(); break;
        case 'q': fclose(file); exit(0);
        }
    }
while(command != 'n' || command != 'e' || command != 'q')

Составьте блок-схему данной программы, наберите ее текст, откомпилируйте и запустите. Создайте несколько записей, проверьте реакцию программы на ввод посторонних символов, введите команду ,,р'' и посмотрите, как выглядят все записи.

Выйдите из программы, посмотрите содержимое файла, в котором хранилась ваша база данных. Составление алгоритмов управления станками с ЧПУ. Введение Современный технологический процесс не обходится без цифровой электроники. Электроникой ,,напичканы'' многие приборы, начиная от наручных часов и заканчивая космическими аппаратами. На производстве тоже внедряется электроника: это и станки с ЧПУ, и роботы, и даже целые роботизированные предприятия, управляемые единой АСУ.

Оперирование такими приборами требует знания элементарной цифровой логики и основ алгоритмизации и программирования. Логические элементы. Все цифрове схемы основаны на трех ,,китах'' -- элементарных логических элементах: это элементы ,,И'', ,,ИЛИ'', ,,НЕ''. Каждый элемент характеризуется таблицей истинности -- соответствия выходного сигнала разным значениям входного. Названия элементов вполне логически соответствуют производимым ими операциям:

Таблица истинности для элементов ,,И'', ,,ИЛИ'' и ,,НЕ''

$\quad A\quad$ $\quad B\quad$ $\quad A\land B\quad$ $\quad A\lor B\quad$ $\quad\overline A\strut\quad$
0 0 0 0 1
0 1 0 1 1
1 0 0 1 0
1 1 1 1 0

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

Триггер предназначен для хранения одного бита информации. Его выходной сигнал зависит от подачи логической 1 на один из двух входов (,,Установить в 1'' и ,, Установить в 0'').

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

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

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

Датчики и микроконтроллеры в АСУ. Программируемый микроконтроллер (ПМК) представляет собой специализированную управляющую микро ЭВМ, работающую в режиме реального времени по фиксированной рабочей программе, размещенной в ОЗУ ПМК. ПМК может работать как в паре с ПК, так и отдельно от него.

Обычно ПМК содержит аналогово-цифровые преобразователи (АЦП) -- для кодирования измеряемых аналоговых сигналов в привычную для ЭВМ форму; ЦАП -- для обратного преобразования цифровых сигналов в аналоговые; коммутаторы каналов -- для последовательного опроса цифровых каналов; ОЗУ, в котором хранятся исполняемая программа и ее данные; ПЗУ -- содержацая операционную систему.

Программирование ЧПУ. Для программирования работы станка с ЧПУ необходимо разработать карту технологического процесса, а затем составить алгоритм работы устройства.

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

Составьте алгоритм работы роботизированного сверлильного станка для сверления десяти металлических заготовок размером 100х200 мм. В них необходимо сделать 5 отверстий диаметром 10 мм.: одно в центре и четыре по углам на расстоянии 20 мм от краев заготовок. Алгоритм оформите в виде блок-схемы. Перед выполнением сверления следует проверить соответствие размеров заготовок требуемым размерам. Допуск размеров $\pm0.1$ мм. Для подсчета готовых изделий следует ввести счетчик, увеличивающийся на 1 каждый раз, как только окончен процесс изготовления очередной детали.

Теперь представьте, что вы оперируете АСУ конвейера, производящего гайки М3. На входе вы имеете металлический лист толщиной 2.5 мм и размерами 3х3 м. Составьте технологическую карту производства гаек (методом штамповки) из такого листа. После штамповки, и сверления следует отшлифовать гайки, затем -- просверлить в них отверстие под резьбу (вспомните, какой диаметр сверла необходимо взять для этого), нарезать резьбу и оцинковать.

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

Не забывайте, что автомат, после окончания штампованных заготовок, должен дать команду прессовочному станку произвести следующую их партию. Работа в компьютерных сетях. Работа с протоколом http. Для просмотра гипертекстовых документов в Linux существует множество браузеров, как консольных, так и графических. Они работают обычно не только с протоколом http, но и с другими протоколами, позволяя, например, скачивать файлы по протоколу ftp, заходить на защищенные сайты по протоколу https, читать новости и т.п.

В интернете существует множество разнообразных ресурсов, содержащих огромное количество документов. Кроме того, интернет предлагает средства текстового общения (форумы, блоги, ICQ, IRC и многое другое), рассылки писем, новостей, телефонии, видеофонии.

Консольные браузеры: <ynx и <inks. Откройте окно виртуальной консоли (например, konsole или xterm). Запустите в нем сначала браузер Lynx командой <ynx www.sgpk.ru. Полистайте страницы. Обратите внимание, как браузер реагирует на нажатие тех или иных клавиш. Активация гиперссылки происходит при нажатии клавиши Enter, перемещение между ссылками -- клавишами ,,вверх'' и ,,вниз''.

Откройте страницу с фреймами (например, ссылку ,,разные картинки''). Обратите внимание, что фреймы можно просматривать только по отдельности.

Что такое ,,фрейм'' и для чего он нужен?

Теперь откройте тот же сайт при помощи браузера Links (<inks www.sgpk.ru). Посмотрите, как теперь выглядят страницы с фреймами. Скажите, в чем недостаток текстовых браузеров, а в чем их преимущества перед графическими.

Графические браузеры. Откройте любой графический браузер (Mozilla, Konqueror, Firefox) на сайте www.sgpk.ru. Пройдитесь по ссылкам. Обратите внимание на самое главное отличие графических браузеров от консольных.

Зайдите на форум и оставьте в нем какую-нибудь запись. Сможете ли вы удалить запись после того, как ее добавили?

Зайдите на хранилище документации. Как сохранить документ? Как открыть его или найти после сохранения?

Зайдите на хранилище изображений. Как сделать изображение заставкой на рабочем столе?

Протокол ftp. FTP служит для обмена файлами. Для просмотра ресурсов ftp-серверов служат браузеры, а также консольная программа ftp.

Зайдите на ресурс ftp.sgpk.ru при помощи mc. Для этого, нажав клавишу <F9>, выберите в меню соответствующей панели пункт ,,FTP-соединение''. Активируйте его и введите адрес ресурса. После соединения вы можете просматривать его как локальную папку. Скачайте какой-нибудь файл к себе в домашнюю папку.

Зайдите на тот же ресурс при помощи графического браузера. Для этого в строке адреса перед адресом ресурса следует указать протокол: ftp://ftp.sgpk.ru. Браузер будет выступать в роли графического файлового менеджера.

Создание домашней страницы. Ваши домашние папки хранятся на сервере. Он настроен так, что, если вы создадите в папке ~/www файл index.html с соответствующим содержанием, у вас появится домашняя страничка, выйти на которую можно по адресу www.sgpk.ru/~<login>, где <login> -- ваше регистрационное имя в системе. Краткое обозначение домашней папки -- ~/, поэтому вы можете быстро войти в какой-нибудь свой каталог, набрав cd ~/каталог. Для того, чтобы просто войти в домашнюю папку, достаточно набрать команду cd без параметров.

Создать домашнюю страничку можно в любом текстовом редакторе, но для этого вы должны знать язык гипертекстовой разметки html. Проще создать этот документ при помощи специальной программы -- компоновщика. Например, при помощи компоновщика браузера Mozilla (Mozilla composer).

Создайте в Mozilla новую страницу компоновщика. Напишите в ней какой-нибудь текст о себе, добавьте изображений. Для более красивого размещения текста и картинок используйте таблицы. Раскрасьте элементы в разные цвета. Название страницы выделите крупным шрифтом.

Сохраните страницу под именем index.html в папку ~/www/. Теперь, если вы все сделали правильно, зайдите на свою домашнюю страницу при помощи любого браузера. Посмотрите ее в нескольких разных браузерах. Объясните причины различия представления одной и той же информации в разных браузерах.


next up previous
Next: About this document ... Up: Лабораторный практикум по информатике Previous: Библиотечные функции.
Edward V. Emelianoff 2007-04-25
Hosted by uCoz