Структуры и функции языка С
Пример 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", "while", "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: %s\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: "); } while ((c = getchar()) != EOF); printf("\n Press any key: "); _getch(); return 0; }
В программе ввод слов осуществляется посимвольно с помощью специальной функции getLine().
Шаблон структуры – это struct key, для которого определяется переменная tab[] как массив структур. Одновременно определяется указатель на эту структуру, т.е. *bam.
Функция struct key *PTR_ANALYSE() возвращает указатель на структуру. Параметрами этой функции являются указатель на тип char, массив структур и целая переменная. Цикл do – while применен для того, чтобы тело цикла выполнялось хотя бы один раз. Массив структур с именем tab[] инициализирован служебными словами – операторами управления. Результат выполнения функции struct key *PTR_ANALYSE() присваивается указателю *bam, который определен по шаблону глобальной структуры.
Возможный результат выполнения программы показан на рис. 15.5.
Задание 5
- В программе используйте прототипы вспомогательных функций.
- В качестве служебных слов задайте основные типы данных и их производных языка программирования С.
- Дополните программу подсчетом количества символов служебных слов с выводом на консоль как самого слова, так и его длины.
- Функцию анализа вводимых слов с клавиатуры напишите без дополнительного указателя на структуру типа key.
- В программе предусмотрите копирование консольного содержания в текстовый файл с именем 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; // Бинарный поиск while (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 while 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: "); } while ((c = getchar()) != EOF); printf("\n Press any key: "); _getch(); return 0; }
При двоичном алгоритме поиска после каждого сравнения исключается половина элементов массива, в котором производится поиск 15.5. Алгоритм находит средний элемент массива и сравнивает его с ключом поиска (в программе переменная х ). Если они равны, ключ поиска считается найденным и возвращается индекс этого элемента. Если они не равны, задача упрощается до поиска в одной половине массива.
Если ключ поиска меньше среднего элемента массива, поиск производится в первой половине массива. В противном случае поиск производится во второй половине. Если ключ поиска в указанном подмассиве не найден, алгоритм повторяется для четверти массива. Поиск продолжается до тех пор, пока ключ не окажется равен среднему элементу подмассива или пока подмассив не будет состоять из одного элемента, не равного ключу (это означает, что ключ поиска не найден).
Возможный результат выполнения программы показан на рис. 15.6.
Задание 6
- Перед началом бинарного поиска по заданному ключу отсортируйте массив случайных чисел по убыванию.
- Сформируйте случайный массив из 5*Х целых чисел. Интервал формирования случайных чисел примите от Х до 5*Х, где Х – номер компьютера, за которым выполняется лабораторная работа. Выведите отсортированный массив на консоль. Введите число (ключ поиска), соответствующее последнему элементу массива. Подсчитайте количество итераций (количество сравнений в двоичном поиске), которое потребуется для поиска заданного ключа.
- Заданную программу дополните поиском по заданному ключу последовательным перебором. Определите количество сравнений, которое потребуется при бинарном поиске и с помощью последовательного перебора.
Контрольные вопросы
- Какие операции над структурами разрешены в языке С?
- Как осуществляется передача частей структуры в качестве аргументов функции?
- Как осуществляется возврат частей структуры из функции?
- Как реализуется возвращение измененной структуры из функции?
- Как осуществляется обращение к полям структуры, переданной функции в виде аргумента?
- Допустимо ли объявление переменных глобальной структуры и переменных структуры функции одними и теми же идентификаторами?
- Как распределить структуру в динамической памяти?
- Как осуществляется возврат данных структурного типа из пользовательской функции?