Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Visual_Studio_2010

.pdf
Скачиваний:
109
Добавлен:
03.03.2016
Размер:
5.94 Mб
Скачать

Рис.20.15. Форма с откомпилированным проектом

Программный код главной функции проекта

#include <stdio.h>

#include <conio.h>

#include "..\..\stack.h" #include "..\..\queue.h"

int main (void)

{

int i;

queue_t *q = queue_create(); stack_t *s = stack_create(-1);

for (i = 0; i < 16; ++i) // заполнение стека stack_push (s, i);

printf("\n Stack content:\n"); while (!stack_is_empty (s))

printf (" %3d\n", stack_pop (s)); stack_destroy (s); // разрушение стека

for (i = 0; i < 14; ++i) // заполнение очереди queue_push (q, i);

printf("\n Queue content:\n");

381

while (!queue_is_empty (q))

printf (" %3d\n", queue_pop (q)); queue_destroy (q); // разрушение очереди

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

_getch(); return 0; }

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

Рис.20.16. Результат выполнения программы с файлами из библиотеки

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

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

3 5 1 8 12 21 25.

Результат симметричного представления:

25 21 12 8 1 5 3 5 1 8 12 21 25.

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

// Файл основного модуля проекта main.c #include <stdio.h>

#include <conio.h> #include <stdlib.h> #include "xyx.h"

382

int main (void) { int i, n = 7;

int M[] = {3, 5, 1, 8, 12, 21, 25};

printf("\n Initial array:\n"); for (i = 0; i < n; ++i)

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

printf("\n\n New array:\n"); for (i = 0; i < (2*n-1); ++i)

printf(" %3d", *(xyx(M, n)+i));

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

return 0;

}

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

//file xyx.h

int *xyx(int M[], int n);

// Подключаемый файл xyx.c #include <stdlib.h>

int *xyx(int M[], int n) { int j, p = 2*n - 1; int *PTR;

PTR = (int *)calloc(p,sizeof(int)); for (j = 0; j < p; ++j)

PTR[j] = 0;

for (j = 0; j < p; ++j) if (j < n)

PTR[j] = M[(n-1) - j]; else

PTR[j] = M[j - (n-1)]; return PTR; }

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

Рис.20.17. Результат симметричного преобразования массива

383

Задание1

1.К проекту подключите статическую библиотеку с файлами xyx.h, xyx.c. Осуществите сборку проекта из приведенных файлов.

2.Предусмотрите ввод чисел массива с клавиатуры.

3.Напишите функцию типа xyx(), которая обрабатывает одномерные символьные массивы данных.

4.Видоизмените программу для преобразования массива с действительными числами, которые формируются случайным образом из интервала [– 2X; 2X], где Х – номер компьютера, на котором выполняется лабораторная работа.

Пример 2. Разработать абстрактный тип данных – двоичное дерево поиска. Выполнить вставки узлов в двоичное дерево случайными числами и произвести обход дерева с порядковой выборкой [2]. Созданные функции заполнения и обхода двоичного дерева поместить в статическую библиотеку.

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

Двоичное дерево поиска (с неповторяющимися значениями в узлах) устроено так, что значения в любом левом поддереве меньше, а значения в любом правом поддереве больше, чем значение в родительском узле [2]. На рис.20.18 изображена схема двоичного дерева поиска с 12 значениями.

47

25

77

11

43

65

93

7

17

31

44

68

Рис. 20.18. Пример двоичного дерева поиска

384

В программах, реализующих стеки, очереди, деревья и т. д., используются автореферентные структуры (self-referential), которые содержат в качестве элемента указатель, ссылающийся на структуру того же типа.

Например, определение

struct node { int data; struct node *nextPtr; };

описывает тип struct node. Элемент nextPtr указывает на структуру типа struct node – структуру того же самого типа, что и объявленная, т. е. структура ссылается сама на себя.

Для заданного примера используем целые случайные числа из интервала от 0 до 14.

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

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

#include <stdio.h>

#include <conio.h> #include <stdlib.h>

#include <time.h> #include <locale.h>

//#include "tree.h"

#define N 10 // количество случайных чисел - узлов

#define R 15 // случайные числа от 0 до R-1

// Автореферентная структура struct treeNode

{

struct treeNode *LeftPtr; //для левого поддерева int data;

struct treeNode *RightPtr; // для правого поддерева

};

typedef struct treeNode TreeNode; typedef TreeNode *TreeNodePtr;

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

void insertNode (TreeNodePtr *treePtr, int value); void inOrder(TreeNodePtr treePtr);

int main (void)

{

int i; int item;

time_t tic;

TreeNodePtr rootPtr = NULL; // пустое дерево setlocale(LC_ALL, ".1251"); // русские шрифты srand((unsigned) time(&tic)); // рандомизация случайных чисел

385

printf("\n Числа двоичного дерева:\n");

//Размещение в дереве случайных значений от 0 до (R-1) for (i = 1; i <= N; ++i)

{

item = rand() % R; printf(" %4d", item);

insertNode (&rootPtr, item);

}

//Обход дерева с порядковой выборкой

printf("\n");

printf("\n Результат обхода дерева с порядковой выборкой:\n"); inOrder(rootPtr); // вызов функции

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

return 0;

}

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

//Вставка узла в дерево

void insertNode (TreeNodePtr *treePtr, int value)

{

if (*treePtr == NULL)

{

*treePtr = malloc(sizeof(TreeNode));

// Присвоение данных

if (*treePtr != NULL)

{

(*treePtr)->data = value;

(*treePtr)->LeftPtr = NULL;

(*treePtr)->RightPtr = NULL;

}

else {

printf(" %d не вставлено. Нет памяти.\n", value);

}

}

else { //когда дерево не пусто

if ( value < (*treePtr)->data )

insertNode (&( (*treePtr)->LeftPtr), value);

else if( value > (*treePtr)->data )

insertNode (&( (*treePtr)->RightPtr), value);

else

printf("Дубл."); // дубликаты значений в узлах дерева

}

}

386

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

//Обход дерева с порядковой выборкой void inOrder (TreeNodePtr treePtr)

{

if (treePtr != NULL) { inOrder(treePtr->LeftPtr); printf(" %4d", treePtr->data); inOrder(treePtr->RightPtr);

}

}

Функции insertNode(), inOrder() используются рекурсивно, т. е. вызывают сами себя из тела функции.

В теле функции inOrder() нужно выполнить следующие шаги:

1)обойти вызовом inOrder() левое поддерево;

2)обработать значение в узле;

3)обойти вызовом inOrder() правое поддерево.

Обход двоичного дерева поиска вызовом функции inOrder() выдает

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

ного дерева [2].

Возможный результат работы программы показан на рис.20.19.

Рис.20.19. Пример обхода двоичного дерева

Задание 2

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

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

3.Увеличьте число узлов дерева до 11Х, где Х – номер компьютера, на котором выполняется лабораторная работа. Результат выполнения программы запишите в текстовый файл вида treeS.txt, где S – первая буква фамилии пользователя.

387

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

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

2.Какую нотацию рекомендуется использовать для созданных пользователем библиотечных модулей?

3.Какое расширение используется для созданных пользовательских библиотечных модулей?

4.Применяется или нет функция main() в статически подключаемой библиотеке, созданной пользователем?

5.По какой дисциплине происходит обработка данных в такой структуре данных, как стек?

6.По какой дисциплине происходит обработка данных в такой структуре данных, как очередь?

БИБЛИОГРАФИЧЕСКИЙ СПИСОК

1.Шилдт Г. Полный справочник по С : пер. с англ./Г. Шилдт. – 4-е изд. –

М. : Вильямс, 2007. – 704 с.

2.Дейтл Х.М. Как программировать на С : пер. с англ./Х. М. Дейтл, П. Дж. Дейтл. – 4-е изд. – М. : Бином-Пресс, 2006. – 912 с.

388

Тема 21

ИСПОЛЬЗОВАНИЕ АРГУМЕНТОВ КОМАНДНОЙ СТРОКИ В С

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

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

Аргумент командной строки – это информация, которая вводится в командной строке операционной системы вслед за именем программы [1].

В системных средах, поддерживающих язык программирования С, существует способ передавать в программу аргументы или параметры командной строки при запуске программы на выполнение [2]. Для этого в главную функцию main() включают два аргумента, обычно argc и argv. Первый (от англ. argument count – «счетчик аргументов») содержит количество аргументов командной строки, с которыми была запущена программа. Второй (от англ. argument vector – «вектор аргументов») указывает на массив символьных строк, содержащих сами аргументы, – по одному в строке. В общем случае имена аргументов могут быть произвольными.

Формально можно определить следующий прототип функции main() с параметрами

int main (int argc, char *argv[]);

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

int main (int argc, char **argv);

Каждый указатель значения типа char ссылается на одну из строк командной строки, при этом argv[0] указывает на имя команды (исполняемой программы), argv[1] – на первый аргумент командной строки, argv[2] – на второй аргумент и т. д. [3].

Аргументами командной строки могут быть исполняемые файлы. Из программы можно запустить на выполнение другую программу, новый процесс. Для этого существуют специальные функции библиотеки C Run–Time Library Reference системы Visual Studio (которую используем в качестве компилятора языка С).

Командная оболочка операционной системы Windows использует интерпретатор команд cmd.exe, который загружает приложения и направляет поток данных между приложениями, для перевода введенной команды в понятный системе код. Консоль командной строки присутствует во всех версиях операционных систем Windows.

389

В среде разработки MS Visual Studio 2010 аргументы командной строки можно задать в самой среде, для чего следует произвести соответствующую настройку. Предположим, что мы хотим создать проект под именем tcmd, чтобы он принимал аргументы командной строки, например, "Example 1" и E:\forma.exe. Для этого после (или во время) разработки проекта обратимся к закладке, показанной на рис. 21.1.

Рис. 21.1. Пример настройки и задания аргументов командной строки

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

Использование указанной возможности интегрированной среды разработки позволяет произвести отладку программы с аргументами командной строки. В дальнейшем задание параметров в соответствии с рис. 21.1 необязательно. Программа должна сама подхватывать аргументы командной строки, определенные с помощью утилиты cmd.exe (просто cmd) операционной системы.

Командную строку операционной системы Windows можно запустить следующими способами:

1)Пуск Программы (все программы) Стандартные Командная строка;

2)Пуск Выполнить cmd (ввести).

390

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