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

Спецификатор static

Переменные, объявленные со спецификатором static, хранятся постоянно внутри своей функции или файла. В отличие от глобальных переменных, они невидимы за пределами этой функции (файла), но сохраняют значение между вызовами [2]. Спецификаторstatic воздействует на локальные и глобальные переменные по-разному.

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

Спецификатор staticв объявлении глобальной переменной заставляет компилятор создать глобальную переменную, видимую только в том файле, в котором она объявлена. Тогда она подвергается внутреннему связыванию.

Таким образом, имена локальных статических переменныхвидимы только внутри блока, в котором они объявлены; именаглобальных статических переменных– только внутри файла, в котором они объявлены [2].

Спецификатор register

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

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

Ощутимый эффект от спецификатора register может быть получен только для переменных целого (int) и символьного (char) типов.

Спецификатор auto

Спецификатор autoприсваивает объявляемым объектам автоматический класс памяти, его можно применять только внутри функции [4]. Объявления с данным спецификатором одновременно являются определениями и резервируют память. Автоматический класс памяти задает автоматический период хранения, который могут иметь только переменные. Локальные переменные функции (определенные в списке параметров или в теле функции) обычно имеют автоматический период хранения. Ключевое словоautoопределяет их явным образом.

Автоматическое хранение помогает экономить память, поскольку автоматические переменные существуют только тогда, когда они необходимы. Они создаются при запуске функции, в которой определены, и уничтожаются при выходе из нее [3]. Автоматическое хранение является примером реализации принципа минимальных привилегий [3]. Поэтому переменные должны храниться в памяти и быть доступными, даже если в данный момент в них нет необходимости. Для переменных со спецификатором autoнет значения по умолчанию.

Обычно создаваемые программистом разработки на языке Спринято оформлять в виде файлов с расширением, хотя оно может быть любым, например,.txt,.docи т.д. Соответственно разработки дляС++имеют расширение.срр. Для создания собственного файла можно использовать инструментарийMicrosoftVisualStudio2010. Тогда из пункта менюFileследует выбрать подпунктNewи далее в соответствии с рис.17.2 –С++File(.cpp). После нажатия клавишиOpenоткроется файлSource1.cpp(при повторном обращении будетSource2.cppи т.д.), будет открыто окно редактирования для набора программного кода. Созданный файл можно сохранить с расширением.c. Теперь следует грамотно объявить переменные, используемые в проекте, и функции в файлах типа*.h,*.c. Создаваемые в средеVisualStudioфайлы можно раздельно компилировать, т.е. проверять ошибки, которые отслеживаются при обычной компиляции.

Следует отметить, что функции пользователя можно создавать при использовании обычного блокнота операционной системы Windows, оставив расширение.txt. После этого следует предусмотреть в проекте обращение к файлу с данным расширением. При этом ответственность формирования программного кода ложится на программиста, который создает этот файл (файлы).

Приведем возможные действия для создания файлов типа *.си*.hв программной средеMSVisualStudio2010. Для этого сначала следует открыть стартовую страницуMSVisualStudio2010, далее – пункт менюFileNewFile. Появится страница, показанная на рис.17.2. Зтем необходимо выбрать либоС++File(.cpp), либоHeader File(.h), после чего нажать кнопкуOpen. Если выбратьС++File(.cpp), то откроется окно для редактирования, которое по умолчанию имеет имяSource1.cpp. Написав необходимый код, надо сохранить файл с именем по усмотрению пользователя, но с расширением. Сохранение проведем по цепочке из пункта менюFile: FileSave  Source1.cpp As В пункте меню «Тип файла» нужно выбрать C Source File (*.c). В итоге откроется окно (в котором могут быть ранее созданные проекты), приведенное на рис. 17.3.

Рис. 17.3. Окно для сохранения С-файла

Сохранить файл можно где угодно. Целесообразно поместить его в папке разрабатываемого проекта, где будет находиться функция main.c. Такие же рекомендации обычно принимаются и для сохранения разрабатываемых программистомh-файлов. В случае когда проект разрабатывается несколькими программистами, для всех может использоваться один и тот жеh-файл. Тогда его следует расположить в какой-либо директории, находящейся на один или несколько уровней выше, чем папка создаваемого проекта. Подключение такого файла следует выполнить в соответствии со следующей нотацией:

#include "..\..\some.h"

Это означает, что файл some.hнаходится на два уровня выше, чем главный файлmain.c.

Можно указывать полный путь расположения заданного h-файла. Если разрабатывается проект, который переносится с диска на диск, то всякий раз придется прописывать полный путь кh-файлу, поэтому обычно договариваются переносить проект на новый диск со всеми файлами. Тогда каждый программист просто рассчитывает число уровней до заданногоh-файла. При этом структура объявлений функций остается неизменной, т.е. без указания полного пути.

Обычно в h-файлах дается описание прототипов разработанных файлов, постоянных, общих для проекта и препроцессорных директив. В случае использования препроцессорных директив(#define ) следует после них оставить одну пустую строку.

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

Пример1.Рассмотрим пример создания проекта вMicrosoftVisualStudio2010, состоящего из одного заголовочного файла (например,hfile.h) и двух подключаемых функций, созданных программистом (например,degree(),print()). В файлеmyfile3.cпоместим функциюdegree(), а функциюprint()отправим вmyfile2.c. Файл с главной функцией создаваемого проекта озаглавим какmain.c. При этом файлыhfile.h,myfile3.cиmyfile2.cразместим на другом диске, напримерD:.

В качестве примера запрограммируем решение следующей задачи. Сформировать матрицу, состоящую из строк. Число столбцов равноk.Cтолбцы матрицы заполняются +1 или –1 по степеням двойки. То есть первый столбец заполняется +1, –1, +1, –1, +1, –1 и т.д., второй  – +1, +1, –1, –1, +1, +1, –1, –1 и т.д., третий – +1, +1, +1, +1, –1, –1, –1, –1 и т.д. Эту матрицу называют матрицей планирования эксперимента типа. Ее расчет должен выполняться в одном файле, а печать результата – в другом, при этом результат можно записать в текстовый файл. В файлеmain.cпроисходит обращение к созданным функциям.

Чтобы получить число +1 или –1, следует использовать возведение в степень числа –1. Для нечетной степени получим –1, а для четной – +1. Разработаем специальную функцию возведения целого числа в целую степень. Для вывода результата на консоль или в файл создадим свою функцию.

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

#include <stdio.h>

#include <conio.h>

#include <math.h>

#include "D:\\hfile.h"

int main(void) {

double k;

printf("\n\tConstruction of a matrix of planning experiment N = 2^k\n");

printf("\n\tEnter a natural number: ");

scanf_s("%lf", &k);

if (k < 1 || (ceil(k) != k) ) {

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

getch(); return -1;

}

// Обращение к функции формирования матрицы планирования

print((int)k);

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

getch();

return 0; }

// Файл myfile3.c

int degree(int x, int k)

{

int i, a = 1;

for (i = 1; i <= k; ++i)

a *= x; return a;

}

// Файл myfie2.c

#include <math.h>

#include <stdlib.h>

void print(int k)

{

int i, j, N, *PTR;

FILE *fid;

N = degree(2,k); // N = 2^k

// Динамически выделяемая память

PTR = (int *)malloc(N*k*sizeof(int));

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

for (j = 0; j < k; ++j)

PTR[i*k + j] = 0; // заполнение нулями

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

for (j = 0; j < k; ++j)

PTR[i*k + j] = degree(-1,(int)floor(i/degree(2,j)));

printf("\n Matrix is planning experiment, N = 2^k, N = %d, k = %d\n", N, k);

if (k < 5)

{

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

{

printf("\n%4d) ", i+1);

for (j = 0; j < k; ++j)

printf(" %3d", PTR[i*k+j]);

}

}

else

{

fopen_s(&fid, "D:\\data.txt", "w");

fprintf(fid, "\r\n Matrix is planning experiment, N = 2^k, N = %d, k = %d\r\n", N, k);

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

{

fprintf(fid, "\r\n%4d) ", i+1);

for (j = 0; j < k; ++j)

fprintf(fid, "%3d", PTR[i*k+j]);

}

fclose(fid);

printf("\n See the result in the file \"D:\\data.txt\" \n");

}

}

// Заголовочный файл hfile.h

#include "D:\myfile3.c"

#include "D:\myfile2.c"

Подключение файлов сделано в двух местах: в главной функции main()и в заголовочном файлеhfile.h. При этом прототипы функций не прописаны. Заголовочный файлhfile.h«выгружает» содержимое файловmyfile3.c и myfile2.c перед главной функцией main(), поэтому в теле функции можно обращаться к функциям degree() и print(). Первая предназначена для возведения целого числа в степень, она формирует матрицу планирования (с помощью указателя *PTR) и вывода значений матрицы на консоль и (или) в текстовый файл. Важное значение имеет очередность подключения файлов myfile3.c и myfile2.c. Следует обратить внимание на синтаксис: заключение в двойные ковычки имени текстового файла data.txt. Функция ceil() возвращает наименьшее целое (представленное в виде значения с плавающей точкой), которое больше своего аргумента или равно ему [2]. Она включена на тот случай, если пользователь введет нецелое число.

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

Рис.17.4. Матрица планирования

Задание1

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

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

  3. Вместо разработанной функции degree()примените стандартную функциюpow(). Сравните полученные результаты.

  4. В программу добавьте изменения для вывода матрицы планирования при зеркальном отображении столбцов.

  5. Дополните программу запросом знак единицы в первом столбце матрицы планирования.

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

Пример2.Написать программу вывода на консоль содержимого текстового файла, расположенного в заданном каталоге, оформить вывод в виде отдельного файла.

Предположим, что программный проект расположен на диске Е:\Project_C, текстовый файл находится на дискеD:\data16.txt. Пусть содержимое текстового файла будет следующим:

1, 2, 3, 4, 5

Programming in C

department: electronic engineering

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

// Подключаемый файл fun1.c

#include <stdlib.h> // для функции exit()

void print_file(char**st)

{

char str[79+1];

FILE *fid;

printf("\n Data from \"%c\":\n", st);

if ( (fopen_s(&fid, st, "r")) )

{

printf("\n File could not be opened.\n");

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

getch();

exit(1);

}

printf("\n Data from the file \"%c"\n", st);

if (!feof(fid)) {

fgets(str, 79, fid);

printf("%c", str);

}

fclose(fid);

printf("\n");

}

// Основной программный модуль проекта main.c

#include <stdio.h>

#include <conio.h>

#include "D:\\fun1.c"

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

int main (void) {

char str[79+1];

printf("\n Enter the file name and path: ");

gets_s(str, 79);

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

print_file(str);

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

getch();

return 0;

}

Результат выполнения программы приведен на рис.17.5.

Рис.17.5. Содержимое заданного текстового файла

Задание2

  1. Выведите на консоль содержимое подключаемого файла fun1.c.

  2. Измените расположение подключаемого файла, например поместите его на диск D:\students\fun1.c.

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

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

  5. В программе вместо указателя, являющегося формальным параметром функции print_file(), примените массив символов.

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

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

Программный код решения примера состоит из шести файлов

// Основной программный модуль main.c

#include <stdio.h>

#include <conio.h>

#include "hdec.h"

int main (void) {

int index[3] = {0, 1, 2};

long int number;

int basen;

void (*fun[3])(long int) = {dec2, dec8, dec16};

printf("\n Enter a positive integer numbers: ");

scanf_s("%c", &number);

printf("\n Select base system notation (2, 8, 16): ");

scanf_s("%d", &basen);

if (basen == 2)

(*fun[0])(number);

else if (basen == 8)

(*fun[1])(number);

else if (basen == 16)

(*fun[2])(number);

else {

printf("\n\t Error choice.");

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

getch();

return -1;

}

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

getch();

return 0;

}

// Подключаемый файл Dec_2.c

// Перевод в двоичную систему счисления

#include "base.h"

void dec2 (long int x) {

int i = 0;

int Num[64];

int next;

long int xx = x;

do {

Num[i] = x % base2;

++i;

x /= base2;

} if (x != 0);

// Результат в обратном порядке

printf("\n Decimal number \"%c\" has a binary equivalent:\n", xx);

for (--i; i >= 0; --i) {

next = Num[i];

printf("%2d", next);

}

}

// Подключаемый файл Dec_8.c

// Перевод в восьмеричную систему счисления

#include "base.h"

void dec8 (long int y) {

int i = 0, next, Num[64];

long int yy = y;

do {

Num[i] = y % base8;

++i;

y /= base8;

} if (y != 0);

// Результат в обратном порядке

printf("\n Decimal number \"%c\" has an octal equivalent:\n", yy);

for (--i; i >= 0; --i) {

next = Num[i];

printf("%2d", next);

}

}

// Подключаемый файл Dec_16.c

// Перевод в шестнадцатеричную систему счисления

#include "base.h"

void dec16 (long int z) {

int i = 0;

int next, Num[64];

long int zz = z;

const char digits_16[16] = {

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',

'A', 'B', 'C', 'D', 'E', 'F' };

do {

Num[i] = z % base16;

++i;

z /= base16;

} if (z != 0);

// Результат в обратном порядке

printf("\n Decimal number \"%c\" has a hexadecimal equivalent:\n", zz);

for (--i; i >= 0; --i) {

next = Num[i];

printf("%2c", digits_16[next]);

}

}

// Подключаемый файл base.h

// Основания систем счисления

#define base2 2

#define base8 8

#define base16 16

// Подключаемый файл hdec.h

// Подключение файлов с функциями преобразования систем

// счисления

#include "Dec_2.c"

#include "Dec_8.c"

#include "Dec_16.c"

// Прототипы функций преобразования систем счисления

void dec2 (long int a);

void dec8 (long int b);

void dec16 (long int c);

В программе используется заголовочный файл base.hв целях демонстрации препроцессорных директив языкаС. Другой заголовочный файлhdec.hподключает файлы с программами преобразования чисел и прототипы функций.Внимание!Особенность при их создании заключается в том, что они должны заканчиваться пустой строкой (после всех операторов, прототипов функций и пр.)

Файлы Dec_2.c,Dec_8.c,Dec_16.c,base.h,hdec.hсозданы с помощью инструментальной средыMicrosoftVisualStudio2010. Эти файлы следует сохранить в папке с основным программным кодом функцииmain.c.

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

(*fun[0])(number);

Десятичное число numberпередается в функциюdec2(). Нулевой индекс соответствует выбору функции перевода десятичного числа в двоичный эквивалент.

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

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

Рис.17.6. Перевод десятичного числа в шестнадцатеричное

Задание3

  1. Получаемые результаты проверьте с помощью встроенного калькулятора calcоперационной системыWindows.

  2. Все файлы проекта, кроме main.c, расположите на один уровень выше с помощью нотации../.

  3. Дополните программу вывода преобразованного десятичного числа во всех системах счисления одновременно, т.е. по основаниям 2, 8, 16.

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

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

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

Пусть задан исходный одномерный массив:

1 2 3 4 5 6 7.

Тогда массив накопительной суммы (cumsum–cumulativesumofelements) будет выглядеть так:

1 3 6 10 15 21 28.

Программный код решения примера состоит из трех файлов

// Файл main.c, основной модуль проекта

//#include <stdio.h>

#include <conio.h>

//#include <stdlib.h>

#include <locale.h>

#include "hcum.h"

int main (void) {

int i, n;

int *M;// Указатель для исходного массива

int *N;// Указатель для накопительного массива

setlocale(LC_ALL, "rus"); // для поддержки русских шрифтов

printf("\n Введите размерность одномерного массива: ");

scanf_s("%d", &n);

M = (int *)calloc(n, sizeof(int));

// Формирование исходного массива

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

M[i] = (i + 1);

printf("\n Исходный массив:\n ");

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

if (M[i] < 10)

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

else if (M[i] == 10)

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

else if (M[i] > 10 && M[i] < 100)

printf("%4d", M[i]);

else

printf("%5d", M[i]);

printf("\n\n Массив накопительной суммы:\n ");

// M - фактический аргумент функции cumsum()

N = cumsum(M, n);

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

if (N[i] < 10)

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

else if (N[i] == 10 )

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

else if (N[i] > 10 && N[i] < 100)

printf("%4d", N[i]);

else

printf("%5d", N[i]);

// Освобождение выделенной памяти

free(M);

free(N);

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

getch();

return 0;

}

// Подключаемый заголовочный Файл hcum.h

#include <stdlib.h>

#include <stdio.h>

#include <locale.h>

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

int *(cumsum)(int *arr, int n);

// Подключаемый файл fcum.c

// Функция cumsum()

#include "hcum.h"

int *(cumsum)(int *arr, int n)

{

int i;

int *SUM;// Указатель для накопительного массива

// Выделение памяти для нового указателя

SUM = (int *)calloc(n, sizeof(int));

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

// Проверка выделенной памяти

if (SUM == NULL)

{

printf("\n Память не выделена. Нажмите любую клавишу");

getch();

exit(1);

}

// Основной код формирования накопительной суммы

SUM[0] = arr[0];

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

SUM[i] = SUM[i-1] + arr[i];

return (SUM);

}

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

В программе закомментированы библиотечные заголовочные файлы, которые включены в файл hcum.h. Сама накопительная функцияcumsum()определена через указатель. Поэтому она возвращает указатель, который принимает адрес нулевого элемента массива накопительной суммы.

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

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

Задание4

  1. Файлы hcum.hиfcum.cрасположите за пределами папки проекта. Примените различные комбинации расположения файловhcum.hиfcum.cв нескольких папках рабочего диска. Обеспечьте работоспособность программы.

  2. Внесите изменения в программу, чтобы она была работоспособной без заголовочного файла hcum.h.

  3. Напишите программу формирования накопительной суммы вещественных чисел заданного массива. Формирование исходного массива выполните по случайному равномерному закону из интервала [–X; +X], где Х – номер компьютера, на котором выполняется лабораторная работа.

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

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

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

Пример5.Написать программу быстрой сортировки Хоара одномерного массива целых чисел с расположением функций в разных файлах [5]. Предусмотреть формирование одномерного массива случайным образом с динамическим распределением памяти.

Программный код решения примера состоит из трех файлов

// 1-й файл с главной функцией - файл main.c

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include <locale.h>

#include <time.h>

#include "hsort.h"// cозданный заголовочный файл

int main (void)

{

int i, n;

int *M;// Указатель для исходного массива

int Limit = 100;

time_t t; // переменная текущего времени

// Рандомизация генератора псевдослучайных чисел

srand( (unsigned int) time(&t));

// Для поддержки русских шрифтов

setlocale(LC_ALL, ".1251");

printf("\n\t Быстрая сортировка Хоара\n");

printf("\n Введите размерность одномерного массива: ");

scanf_s("%d", &n);

// Выделение памяти для заданной размерности массива

M = (int *)malloc(n*sizeof(int));

// Формирование случайного исходного массива

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

M[i] = -Limit/2 + rand() % Limit;

printf("\n Исходный одномерный массив:\n");

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

if (abs(M[i]) < 10) {

if (M[i] < 0)

printf("%4d", M[i]);

else

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

}

else {

if (M[i] < 0)

printf("%5d", M[i]);

else

printf("%4d", M[i]);

}

printf("\n\n Отсортированный одномерный массив:\n");

QuickSort(M, n);

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

if (abs(M[i]) < 10) {

if (M[i] < 0)

printf("%4d", M[i]);

else

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

}

else {

if (M[i] < 0)

printf("%5d", M[i]);

else

printf("%4d", M[i]);

}

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

getch();

return 0;

}

// 2-й файл - подключаемый заголовочный файл hsort.h

// с прототипом функции быстрой сортировки Хоара

void QuickSort(int *A, int n);

// 3-й файл - подключаемый файл my_sort.c

// с кодом быстрой сортировки Хоара

void QuickSort (int *A, int n)

{

int i, j, s;

int L, R;

int k, x;

#define D 1000

struct stack {

int L;

int R;

} st[D];// имитация стека

s = 1; st[1].L = 0; st[1].R = n - 1;

do {

L = st[s].L; R = st[s].R; s--;

do {

i = L; j = R;

x = A[(L+R)/2]; // разделяющий элемент

do {

if (A[i] < x)

i++;

if (x < A[j])

j--;

if (i <= j){

k = A[i]; A[i] = A[j]; A[j] = k;

i++; j--;

}// end if

} if (i < j); // end 3d do

if (i < R)

{s++; st[s].L = i; st[s].R = R;}

R = j;

} if (L < R);

} if (s != 0);

}

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

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

Рис.17.8. Пример сортировки одномерного массива

Задание5

  1. Произведите сборку проекта из трех предложенных файлов.

  2. Напишите программу с сохранением исходного массива и полученного отсортированного массива.

  3. Выведите результаты в текстовый файл с именем compX.txt, где Х – номер компьютера, на котором выполняется лабораторная работа. В текстовом файле массивы выведите в виде двух столбцов: исходный массив и отсортированный массив. Размер массивов не менее 10.

  4. Измените программу, исключив заголовочный файл hsort.h.

  5. Введите изменения в программу для сортировки вещественных чисел.

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

Пусть задан полином в виде

Алгоритм схемы Горнера осуществляется при помощи формулы [6]

Полагая, что , расчет полинома в заданной точкепроизводится по следующей итерационной формуле [6]:

Для программной реализации примера примем полином

Рассчитаем значение полинома в точке .

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

#include <stdio.h>

#include <conio.h>

#include <locale.h>

// Размерность массива коэффициентов полинома

#define N 5

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

int main (void) {

int i;

// Массив коэффициентов полинома

double A[ ] = {1.0, 2.0, 3.0, 4.0, 5.0};

double x0 = 2.0, y;

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

// Для вывода чисел с плавающей точкой

setlocale(LC_NUMERIC, "English");

// Консольный заголовок

printf("\n\t Применение схемы Горнера\n");

printf(" Вычисление полинома P(x) %d порядка в точке х = %1.4f:\n", N-1, x0);

// Основной цикла расчета по схеме Горнера

y = A[0];

for ( i = N-2; i >= 0; --i )

y = y*x0 + A[(N-1)-i];

// Вывод результата

printf("\n\t P(x) = %0.4f \n", y );

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

getch();

return 0;

}

Следует обратить внимание на индексацию массива, который находится в теле цикла. В последней функции printf()использован спецификатор «\a» для подачи звукового сигнала.

Результат выполнения программы представлен на рис. 17.9.

Рис. 17.9. Результат вычисления полинома по схеме Горнера

Задание6

  1. Примените оператор цикла do  ifвместо оператора циклаfor.

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

  3. Предусмотрите ввод коэффициентов полинома с клавиатуры. Далее предусмотрите обращение к созданному файлу с реализацией схемы Горнера.

  1. Напишите программу символической записи на консоли заданного полинома по известным коэффициентам. Оформите этот фрагмент программы в виде подключаемого файла.

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