Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
BOOK_С_INTUIT.docx
Скачиваний:
31
Добавлен:
11.02.2015
Размер:
6.34 Mб
Скачать

Контрольные вопросы

  1. Какие различия и общие черты имеются у структур и объединений?

  2. Для чего используются объединения в языке С? Как они определяются?

  3. Как осуществляется инициализация полей объединения?

  4. Как можно вывести значения полей объединения на дисплей?

  5. Для чего служит перечислимый тип данных в языке С? Как он определяется?

  6. Какие операции разрешено выполнять над объединениями?

  7. Какие значения по умолчанию присваиваются полям перечислимого списка?

Библиографический список

  1. Прата С. Язык программирования С. Лекции и упражнения : пер. с англ. / С. Прата. – 5-е изд. – М.: Вильямс, 2006. – 960 с.

  2. Керниган Б. У. Язык программирования С : пер. с англ./Б. У.Керниган, Д. М.Ритчи. – 2-е изд. – М.: Вильямс, 2007. – 304 с.

  3. Подбельский В.В. Программирование на языке Си: учеб. пособие/ В.В.Подбельский, С.С.Фомин. – 2-е изд., доп. – М.: Финансы и статистика, 2007. – 600 с.

  4. Шилдт Г. Полный справочник по С : пер. с англ./Г. Шилдт. – 4-е изд. – М.: Вильямс, 2007. – 704 с.

  5. Кочан С. Программирование на языке С : пер. с англ./С. Кочан. – 3-е изд.– М.: Вильямс, 2007. – 496 с.

Тема 15 Структуры и функции языка с

Рассматриваются способы передачи структур в функции, создание функций, которые возвращают структуры и указатели на структуры.

ТЕОРЕТИЧЕСКАЯ ЧАСТЬ

Разрешенными операциями над структурами являются копирование или присваивание структуры как целого, взятие ее адреса операцией &, а также обращение к ее элементам [1]. Копирование и присваивание включают также передачу аргументов в функции и возвращение значений из функций.

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

struct fred

{

char x;

int y;

float z;

char str[10]; // с учетом символа окончания строки

} mike;

Тогда каждый член этой структуры можно передать функции:

func(mike.x); // передается символьное значение х

func2(mike.y); // передается целое значение y

func3(mike.z); // передается значение с плавающей точкой z

func4(mike.str); // передается адрес строки str[10]

func(mike.str[2]);// передается символьное значение str[2]

Если же нужно передать адрес отдельного члена структуры, то перед именем структуры должен находиться оператор &. Для рассмотренных примеров получим

func(&mike.x); // передается адрес символа х

func2(&mike.y);// передается адрес целого y

func3(&mike.z);// передается адрес члена z с плавающей точкой

func4(mike.str);// передается адрес строки str

func(&mike.str[2]);// передается адрес символа в str[2]

Когда в качестве аргумента функции используется структура, для передачи целой структуры выбирается обычный способ вызова по значению [2], т. е. любые изменения в содержимом параметра внутри функции не отразятся на той структуре, которая передана в качестве аргумента.

При использовании структуры в качестве параметра надо помнить, что тип аргумента должен соответствовать типу параметра. В качестве примера рассмотрим следующий программный код [2]:

#include <stdio.h>

#include <conio.h>

// Определение глобального типа структуры

struct struct_type {

int a, b;

char ch;

};

// Прототип функции

void fun(struct struct_type parm);

int main (void) {

struct struct_type arg;

arg.a = 1000;

fun(arg);

printf("\n Press any key: ");

getch();

return 0;

}

// Определение функции

void fun(struct struct_type parm)

{

printf("\n %d\n", parm.a);

}

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

Когда используется указатель на структуру, вместо оператора точки применяют оператор «стрелка». Видоизменим рассмотренную программу, введя в нее указатель на структуру:

#include <stdio.h>

#include <conio.h>

// Определение глобального типа структуры

struct struct_type { int a, b; char ch; };

// Прототип функции

void fun(struct struct_type *parm);

int main (void)

{

struct struct_type arg,*PTR;

PTR = &arg;

PTR->a = 999;

fun(PTR);

printf("\n Press any key: ");

getch();

return 0;

}

// Определение функции

void fun(struct struct_type *parm)

{

printf("\n %d\n", parm->a);

}

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

#include <stdio.h>

#include <conio.h>

// Определение глобального типа структуры

struct struct_type {int a, b; char ch; };

// Прототип функции

void fun(struct struct_type STRUCT3);

int main (void) {

struct struct_type struct2 = {2, 3, 'Z' };

fun(struct2);

printf("\n Press any key: ");

getch();

return 0; }

// Определение функции

void fun(struct struct_type STRUCT3) {

printf("\n %c: %d + %d = %d\n", \

STRUCT3.ch, STRUCT3.a, STRUCT3.b, STRUCT3.a + STRUCT3.b);

}

В современных версиях языка С, в том числе вANSI C, структуры не только можно передавать функции в качестве аргументов, но и возвращать их из функции [3]. При использовании функций для возврата структур становится возможным отправлять информацию из вызываемой функции в вызывающую. Указатели на структуры допускают также двусторонний обмен данными.

ПРАКТИЧЕСКАЯ ЧАСТЬ

Пример1.Написать программу передачи частей структуры в качестве аргументов функции на примере подсчета суммы двух вещественных чисел, которые вводятся с клавиатуры с именами двух пользователей.

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#define MAX 20

// Шаблон структуры

struct test {

char A[MAX+1]; double ax;

char B[MAX+1]; double by;

};

//Прототип вспомогательной функции

double sum(double, double);

// Главная функция

int main (void)

{

struct test AB; // создание новой структурной переменной

//Заполнение полей структуры

printf("\n\t Type 1 st name: ");

gets_s(AB.A, MAX);

printf("\t Enter the first real number: ");

scanf_s("%lf", &AB.ax);

_flushall();

printf("\n\t Enter 2 nd name: ");

gets_s(AB.B, MAX);

printf("\t Enter the second real number: ");

scanf_s("%lf", &AB.by);

printf("\n\t The sum of two numbers \

%1.2f and %1.2f, %c and %c: %1.2f\n",

AB.ax, AB.by, AB.A, AB.B, sum(AB.ax, AB.by));

printf("\n Press any key: ");

getch();

return 0;

}

// Функция суммирования двух чисел

double sum(double x, double y) {

return (x + y);

}

Возможный результат выполнения программы показан на рис.15.1.

Рис.15.1. Сумма двух чисел, переданных в качестве аргументов функции

Задание1

  1. Одним из вводимых имен примите свое имя (имя пользователя).

  2. Предусмотрите предварительный подсчет суммы двух чисел по возвращаемому значению функции sum().

  3. Произведите инициализацию структуры в программе и передайте ее вещественные данные в функцию для подсчета их суммы.

  4. Напишите функцию, аргументом которой будет вычисленная сумма двух чисел – полей структуры, чтобы эта функция выполняла вывод на консоль полученной суммы.

  5. В программе операцию «точка» замените на операцию «стрелка».

Пример2.Написать программу выполнения арифметических действий с комплексными числами на основе структурного типа данных и печати результатов выполненных действий с помощью вспомогательной функции.

Для решения данного примера следует выполнить действия с комплексными числами, заданными в алгебраической форме [4].

Суммойдвух комплексных чиселz1 = x1 + y1iиz2 = x2 + y2iназывается числоz = x + yiтакое, что справедливы равенствах = х1 + х2,у = у1 + у2, т.е.

z = (x1 + x2) + (y1 + y2)i,

где  i – мнимая единица.

Правило сложения. При сложении комплексных чисел складываются действительные и мнимые части соответственно.

Разностьючиселz1иz2называется числоzтакое, чтоz1 = zz2.

Правило вычитания. При нахождении разностиz1z2из действительной и мнимой частей уменьшаемогоz1вычитаются соответственно действительная и мнимая части вычитаемого:

z = (x1x2) + (y1y2)i.

Произведением двух комплексных чиселz1 = x1 + y1iиz2 = x2 + y2iназывается числоz = x + yiтакое, что выполняются равенства:

х = х1х2у1у2,

у = х1у2 + х2у1.

Правило умножения. Комплексные числа перемножаются как двучлены, при этом учитывается, что.

Частнымот деления числаz1наz2(z2 ≠ 0) называется числоzтакое, что справедливо равенствоzz2 = z1.

Правило деления. Чтобы разделить числоz1наz2(z2 ≠ 0), следует числитель и знаменатель дробиz1/z2умножить на число, сопряженное знаменателю. Комплексные числа называютсясопряженными, если у них равны действительные части, а мнимые противоположны по знаку.

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#include <locale.h>

// Шаблон структуры

struct comp

{

long double Re;

long double Im;

};

// Прототип функции с аргументами:

// структура и симольная переменная

void complex (struct comp ri[2], char op);

int main (void)

{

long double x, y;

char op;

// Определение структурной переменной

struct comp ri[2];

setlocale(LC_ALL, ".1251"); // для русских шрифтов

//Для определения чисел с десятичной точкой

setlocale(LC_NUMERIC, "English");

printf("\n\t ДЕЙСТВИЯ С КОМПЛЕКСНЫМИ ЧИСЛАМИ\n");

printf("\n Введите действительную часть 1-го комплексного числа: ");

scanf_s("%lf", &x); _flushall();

ri[0].Re = x;

printf(" Введите мнимую часть 1-го комплексного числа: ");

scanf_s("%lf", &y); _flushall();

ri[0].Im = y;

printf("\n Введите действительную часть 2-го комплексного числа: ");

scanf_s("%lf", &x); _flushall();

ri[1].Re = x;

printf(" Введите мнимую часть 2-го комплексного числа: ");

scanf_s("%lf", &y); _flushall();

ri[1].Im = y;

printf("\n Введите арифметический оператор: ");

scanf_s("%c", &op, 1); _flushall();

//Вызов функции расчета комплексных чисел

printf("\n Результат действия (\"%c\") над двумя комплексными числами\n (результат с десятичной запятой):", op);

// Для русских шрифтов с числами с десятичной запятой

setlocale(LC_ALL, ".1251");

complex (ri, op);

//Для определения числа с десятичной точкой

setlocale(LC_NUMERIC, "English");

//Вызов функции расчета комплексных чисел

printf("\n Результат действия (\"%c\") над двумя комплексными числами\n (результат с десятичной точкой):", op);

complex (ri, op);

printf("\n Нажмите любую клавишу (Press any key): ");

getch();

return 0;

}

// Вспомогательная функция

void complex (struct comp ri[2], char z) {

double num1, num2, den; // вспомогательные переменные

// Выбор арифметического действия

switch (z) {

case '+' :

if ((ri[0].Im + ri[1].Im) >= 0)

printf("\n\t %1.4f + %1.4fi\n", ri[0].Re + ri[1].Re, ri[0].Im + ri[1].Im);

if ((ri[0].Im + ri[1].Im) < 0)

printf("\n\t %1.4f - %1.4fi\n", ri[0].Re + ri[1].Re, -(ri[0].Im + ri[1].Im));

break;

case '-' :

if ((ri[0].Im - ri[1].Im) >= 0)

printf("\n\t %1.4f + %1.4fi\n", ri[0].Re - ri[1].Re, ri[0].Im - ri[1].Im);

if ((ri[0].Im - ri[1].Im) < 0)

printf("\n\t %1.4f - %1.4fi\n", ri[0].Re - ri[1].Re, -(ri[0].Im - ri[1].Im));

break;

case '*' :

if ((ri[0].Re*ri[1].Im + ri[1].Re*ri[0].Im) >= 0)

printf("\n\t %1.4f + %1.4fi\n",\

ri[0].Re * ri[1].Re - ri[0].Im*ri[1].Im, ri[0].Re*ri[1].Im + ri[1].Re*ri[0].Im);

if ((ri[0].Re*ri[1].Im + ri[1].Re*ri[0].Im) < 0)

printf("\n\t %1.4f - %1.4fi\n",\

ri[0].Re * ri[1].Re - ri[0].Im*ri[1].Im, -(ri[0].Re*ri[1].Im + ri[1].Re*ri[0].Im));

break;

case '/' :

if (ri[1].Re != 0 && ri[1].Im != 0) {

den = ri[1].Re*ri[1].Re + ri[1].Im*ri[1].Im;

num1 = (ri[0].Re*ri[1].Re - ri[0].Im*(-ri[1].Im))/den;

num2 = (ri[0].Re*(-ri[1].Im) + ri[1].Re*ri[0].Im)/den;

if (num2 >= 0)

printf("\n\t %1.4f + %1.4fi\n",num1, num2);

if (num2 < 0)

printf("\n\t %1.4f - %1.4fi\n",num1, -num2);

}

else

printf("\n\t Ошибка! Деление на нуль.\n");

break;

default : printf("\n\t Ошибка! Неизвестный оператор.\n");

break;

}

}

Возможный результат выполнения программы приведен на рис.15.2.

Рис.15.2. Результат действия над двумя комплексными числами

Задание2

  1. Дополните программу вычислением модуля комплексного числа, полученного в результате произведенного арифметического действия.

  2. Консольный вывод запишите в текстовый файл с именем compX.txt, где Х – номер компьютера, на котором выполняется лабораторная работа.

  3. Напишите программу ввода комплексных чисел в виде одной строки, например (4+5.5i) – первое вводимое число как строка, (2–3.3i) – второе вводимое число как строка. Предусмотрите также арифметические действия над комплексными числами.

  4. Напишите программу возведения комплексного числа в степень (см. формулу бинома Ньютона).

Пример3.Написать программу имитатора случайного таймера с помощью указателей на структуру [2].

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#include <time.h>

#include <stdlib.h>

// Глобальный шаблон структуры

struct mtime

{

int hours; // часы

int minutes; // минуты

int seconds; // секунды

};

// Прототипы вспомогательных функций

void update (struct mtime *t);

void display (struct mtime *t);

// Главная функция

int main (void) {

int i;

//Создание переменной структурного типа

struct mtime systime;

// Для изменения псевдослучайной последовательности

srand((unsigned) (long)time(NULL));

// Начальная инициализация структурной переменной

systime.hours = 0;

systime.minutes = 0;

systime.seconds = 0;

// Цикл вывода расчетного времени

for (i = 0; i < 10; ++i) {

update(&systime);

display(&systime);

}

printf("\n\n Press any key: ");

getch();

return 0;

}

// 1-я вспомогательная функция

void update (struct mtime *t) {

// Заполнение полей структуры случайными числами

t -> hours = (int)(24*rand()/RAND_MAX);

t -> minutes = (int)(60*rand()/RAND_MAX);

t -> seconds = (int)(60*rand()/RAND_MAX);

// Условия расчетного времени

t -> seconds += 1;

if (t -> seconds == 60)

{ t -> seconds = 0; t -> minutes++; }

if (t -> minutes == 60)

{ t -> minutes = 0; t -> hours++; }

if (t -> hours == 24)

t -> hours = 0;

}

// 2-я вспомогательная функция

void display (struct mtime *t) {

printf("\n System time: ");

printf("%02d:", t -> hours);

printf("%02d:", t -> minutes);

printf("%02d\n", t -> seconds);

}

В программе аргументами функций update() иdisplay()являются указатели на структуру с дескриптором (этикеткой)mtime. При этом в главной функцииmain()создается структурная переменнаяsystimeпо шаблонуstruct mtimeи она передается в функцииupdate()иdisplay()через свой адрес, т.е.&systime. Так происходит 10 раз (в цикле).

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

void update (struct mtime *);

void display (struct mtime *);

Возможный результат выполнения программы представлен на рис.15.3.

Рис.15.3. Пример вывода полей структуры на консоль

Задание3

  1. Проверьте работу программы без начальной инициализации полей структурной переменной systime.

  2. Результат выполнения программы запишите в текстовый файл с именем compX.txt, где Х – номер компьютера, на котором выполняется лабораторная работа.

  3. В программу добавьте нумерацию итераций цикла: 1), 2), , 10).

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

Пример4.Написать программу, в которой используются функции, имеющие на входе структуру и возвращающие структуру.

Создадим программу расчета средней успеваемости студента за последнюю экзаменационную сессию (или другим экзаменам) с использованием структурного типа данных.

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#define MAX 79

// Шаблон структуры

struct table {

char name[MAX+1];

char surname[MAX+1];

char subject_1[MAX+1];

char subject_2[MAX+1];

char subject_3[MAX+1];

char subject_4[MAX+1];

int mark[4];

float mean;

} student = { // инициализация структурной переменной

"Peter",

"Bobrov",

"Mathematics",

"Informatics",

"Programming",

"Physics",

{0,0,0,0},

0.0f };

// Прототип вспомогательной функции

struct table infor(struct table student);

// Главная функция

int main (void) {

// Объявление и инициализация структурной переменной

struct table infor2 = {" "," "," "," "," "," ", {0,0,0,0},0.0f};

infor2 = infor(student); // присвоение структуры от функции

printf("\n The level of knowledge a student of %c %c is: \

%1.2f\n", infor2.name, infor2.surname, infor2.mean);

printf("\n\n Press any key: ");

getch();

return 0;

}

// Вспомогательная функция с аргументом структурного типа

// и возвращающая структуру

struct table infor(struct table student) {

float x = 0.0f;

int i;

printf("\n\t Enter a name: ");

gets_s(student.name, MAX);

printf("\t Enter a surname: ");

gets_s(student.surname, MAX);

printf("\t Enter 1-st academic subject: ");

gets_s(student.subject_1, MAX);

printf("\t Enter a mark in the first subject: ");

scanf_s("%d",&student.mark[0]);

_flushall();

printf("\t Enter 2-nd academic subject: ");

gets_s(student.subject_2, MAX);

printf("\t Enter a mark in the second subject: ");

scanf_s("%d",&student.mark[1]);

_flushall();

printf("\t Enter 3-rd academic subject: ");

gets_s(student.subject_3, MAX);

printf("\t Enter a mark in the third subject: ");

scanf_s("%d",&student.mark[2]);

_flushall();

printf("\t Enter 4-th academic subject: ");

gets_s(student.subject_4, MAX);

printf("\t Enter a mark in the fourth subject: ");

scanf_s("%d",&student.mark[3]);

// Расчет средней оценки по 4 предметам

for (i = 0; i < 4; ++i) {

x += student.mark[i];

student.mean = x/4;

}

// Возвращение структурной переменной

return (student);

}

В программе приведена инициализация структурной переменной student для наглядности. Инициализация переменной типаfloatвыполнена с суффиксомf. Присвоение одной структурной переменной другой может реализовано только в случае, когда они принадлежат одному и тому же шаблону структур. Функции_flushall()введены для того, чтобы устранить пустую строку перед использованием функцииgets_s()(илиgets()) после ввода с помощью функцииscanf_s(илиscanf()).

Возможный результат выполнения программы показан на рис.15.4.

Рис.15.4. Пример расчета средней успеваемости студента

Задание4

  1. Проверьте содержимое структурной переменной student.

  2. Вместо структурной переменной studentв аргументе вспомогательной функции используйте собственную фамилию.

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

  4. В программу добавьте вывод в главной функции main()всех полей структуры.

  5. Запишите результаты заполнения полей структуры в текстовый файл с именем compX.txt, где Х – номер компьютера, на котором выполняется лабораторная работа.

  6. Проверьте работу программы без начальной инициализации структурной переменной.

  7. Примените оператор typedefпри создании шаблона структуры.

Пример5.Написать программу, в которой функция возвращает указатель на структуру при поиске служебных слов языкаС, вводимых с клавиатуры пользователем [3;8].

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#include <string.h>

#define MAX 1000

// Функция ввода строки с клавиатуры

void getLine(char str[], int m) {

int c, i;

for (i = 0; i < m-1 && (c = getchar())!= EOF && c != '\n'; i++)

str[i] = c;

// После цикла

str[i] = '\0'; // завершение символом окончания строки

}

// Создание структуры глобального типа

struct key

{

char**keyword;

//int keycount;

} tab[] = {

"for",

"if",

"do",

"if",

"else",

"switch",

"case",

"break",

"default"

}, *bam;// указатель на структуру

// Вспомогательная функция

// с указателем на структуру key

struct key *PTR_ANALYSE(char**word, struct key tab[], int n)

{

int i;

struct key *PTR;

for (i = 0; i < n; ++i)

if (strcmp(tab[i].keyword, word) == 0) {

PTR = &tab[i];

// возвращение указателя на структуру типа key

return (PTR); }

return NULL; // служебное слово не найдено

}

// Главная функция

int main (void)

{

int c;

char str[MAX];

printf("\n The analysis of input of syntactic words\n of the programming language C\n\n");

printf("\n The end of the session: press Ctrl+Z after pressing Enter\n\n");

// Цикл с постусловием

do {

printf("\t Enter a new line: ");

getLine(str, MAX);

printf(" ");

bam = PTR_ANALYSE(str, tab, 9); // 9 - число слов

if (bam != NULL)

printf("\t String found: %c\n press Enter to continue or Ctrl+Z to quit: ", bam->keyword);

else

printf("\t STRING NOT FOUND:\n press Enter to continue or Ctrl+Z to quit: ");

} if ((c = getchar()) != EOF);

printf("\n Press any key: ");

getch();

return 0;

}

В программе ввод слов осуществляется посимвольно с помощью специальной функции getLine(). Шаблон структуры – этоstruct key, для него определяется переменнаяtab[]как массив структур. Одновременно создается указатель на эту структуру*bam.

Функция struct key *PTR_ANALYSE()возвращает указатель на структуру. Параметрами этой функции являются указатель на типchar, массив структур и целая переменная. Циклdoifприменен для того, чтобы тело цикла выполнялось хотя бы один раз. Массив структур с именемtab[]инициализирован служебными словами – операторами управления. Результат выполнения функцииstruct key *PTR_ANALYSE() присваивается указателю*bam, который определен по шаблону глобальной структуры.

Возможный результат выполнения программы представлен на рис.15.5.

Рис.15.5. Пример интерактивного поиска служебных слов

Задание5

  1. В программе используйте прототипы вспомогательных функций.

  2. В качестве служебных слов задайте основные типы данных и их производных языка программирования С.

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

  4. Функцию анализа вводимых с клавиатуры слов напишите без дополнительного указателя на структуру типа key.

  5. В программе предусмотрите копирование консольного содержания в текстовый файл с именем compX.txt, где Х – номер компьютера, на котором выполняется лабораторная работа.

Пример6.Написать программу сравнения введенного целого числа с имеющимися целыми случайными числами одномерного массива на основе структурного типа данных и двоичного поиска (метода половинного деления) для упорядоченного массива.

Программный код решения примера

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include <time.h>

#include <locale.h>

#define MAX 1000

// Функция ввода числа как строки с клавиатуры

void getLine(int num[], int m) {

int i, j, k;

time_t tic;

srand((unsigned) time(&tic));

for (i = 0; i < m; ++i)

num[i] = (int)m*rand()/RAND_MAX;

printf("\n\t The initial array of numeric data:\n");

for (i = 0; i < m; ++i)

printf(" %3d", num[i]);

puts(" ");

// Сортировка массива по возрастанию

for (i = 1; i < m; ++i) {

for (j = 0; j < m-1; ++j) {

if (num[j] > num[j+1]) {

k = num[j];

num[j] = num[j+1];

num[j+1] = k;

}

}

}

printf("\t Assorted array of numerical data:\n");

printf(" ");

for (i = 0; i < m; ++i)

printf(" %3d", num[i]);

puts(" ");

}

// Создание структуры глобального типа

struct numb {

int index;

int numbers;

} tab, *bam;// указатель на структуру

// Вспомогательная функция

// с указателем на структуру numb

struct numb *PTR_ANALYSE(int x, int mass[], int n) {

int min = 0;

int max = n - 1;

int mid;

struct numb *PTR = &tab;

// Бинарный поиск

if (min <= max) {

mid = (max + min)/2; // переход в середину массива

if (x == mass[mid]) {

PTR->numbers = mass[mid];

PTR->index = mid;

return (PTR); // возвращение указателя на структуру

}

else if (x < mass[mid])

max = mid - 1;

else

min = mid + 1;

} // End if

return NULL; // число не найдено

} // End function

// Главная функция

int main (void) {

int c, x;

int N, arr[MAX];

// Русские шрифты

setlocale(LC_ALL, ".1251");

printf("\n УГАДЫВАНИЕ ЧИСЛА В ЧИСЛОВОМ ОТСОРТИРОВАННОМ МАССИВЕ\n");

// Латинские шрифты

setlocale(LC_ALL, "English");

printf("\n The end of the session: press Ctrl+Z after pressing Enter\n");

printf("\n\t Enter the dimension of the array of more than 3: ");

scanf_s("%d", &N);

_flushall();

getLine(arr, N);

puts(" ");

do {

printf("\t Enter an integer: ");

scanf_s("%d", &x);

_flushall();

printf(" ");

bam = PTR_ANALYSE(x, arr, N);

if (bam != NULL) {

printf("\t The number is found: %d\n ", bam->numbers);

printf("\t The index number of assorted array: %d\n", bam->index+1);

printf("\n\t Press Enter to continue or Ctrl+Z to quit: ");

}

else

printf("\t The number is not found.\n Press Enter to continue or Ctrl+Z to quit: ");

} if ((c = getchar()) != EOF);

printf("\n Press any key: ");

getch();

return 0;

}

При двоичном алгоритме поиска после каждого сравнения исключается половина элементов массива, в котором производится поиск [5]. Алгоритм находит средний элемент массива и сравнивает его с ключом поиска (в программе переменная х). Если они равны, ключ считается найденным и возвращается индекс этого элемента. Если они не равны, задача упрощается до поиска в одной половине массива.

Если ключ поиска меньше среднего элемента, поиск производится в первой половине массива, в противном случае – во второй половине. Если ключ в указанном подмассиве не найден, алгоритм повторяется для четверти массива. Поиск продолжается до тех пор, пока ключ не окажется равен среднему элементу подмассива или пока подмассив не будет состоять из одного элемента, не равного ключу (это означает, что ключ поиска не найден).

Возможный результат выполнения программы приведен на рис.15.6.

Рис.15.6. Результат двоичного поиска по совпадению ключей

Задание6

  1. Перед началом бинарного поиска по заданному ключу отсортируйте массив случайных чисел по убыванию.

  2. Организуйте случайный массив из 5Х целых чисел. Интервал формирования случайных чисел примите от Х до 5Х, где Х – номер компьютера, на котором выполняется лабораторная работа. Выведите отсортированный массив на консоль. Введите число (ключ поиска), соответствующее последнему элементу массива. Подсчитайте количество итераций (количество сравнений в двоичном поиске), которое потребуется для поиска заданного ключа.

  3. Заданную программу дополните поиском по заданному ключу последовательным перебором. Определите количество сравнений, которое потребуется при бинарном поиске и с помощью последовательного перебора.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]