Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Вопрос 30. Структурный тип данных.Содержание книги
Похожие статьи вашей тематики
Поиск на нашем сайте
Структура, в отличие от массива и строки, может содержать элементы различных типов. Описание структур может выполняться двумя способами. Первый - унаследован от С: struct [<имя структуры>] {<описание полей>} [<список переменных>]; Как следует из формы, при описании структур в этом случае возможны два варианта: а) описание структуры выполняется отдельно от объявления списка переменных, например: struct student { char name[22]; char family[22]; int old; }; // описание структуры struct student stud1, stud2, *ptrstud; // объявление переменных б) описание структуры выполняется совместно с объявлением переменных (в этом случае имя структуре можно не присваивать), например: struct { char name[22]; char family[22]; int old; } stud1, stud2, *ptrstud; Второй способ описания структур появился позднее, когда в язык был введен оператор объявления нового типа typedef. С использованием этого оператора создается новый тип данных - структура, например: typedef struct { char name[22]; char family[22]; int old; } student; // в данном случае студент - это имя нового типа данных. Соответственно возможно объявление переменных данного типа, например: student stud1, stud2, *ptrstud; // объявляются две переменные типа student и один указатель на поле данного типа. В последнем случае память под размещение структуры надо запрашивать специально, например: ptrstud=new student; Обращение к элементам структуры выполняется с указанием имени переменной и имени поля: <имя переменной>.<имя поля> Например: stud1.family или (в том случае, если переменная задается своим адресом) (*ptrstud).family Примечание. В том случае, если переменная задается адресом, удобнее использовать сокращенную форму записи обращения к элементу структуры: ptrstud->family вместо (*ptrstud).family Статические и внешние структуры при объявлении можно сразу инициализировать. При этом значения полей указываются после знака равенства в фигурных скобках через запятую, например: static student stud1={“Петр”,”Петров”,18}, *ptrstud={“Иван”,”Иванов”,19}; Возможно объявление массивов структур и структур, элементами которых являются вложенные структуры. При разработке программ важным является выбор эффективного способа представления данных. Во многих случаях недостаточно объявить простую переменную или массив, а нужна более гибкая форма представления данных. Таким элементом может быть структура, которая позволяет включать в себя разные типы данных, а также другие структуры. Приведем пример, в котором использование структуры позволяет эффективно представить данные. Таким примером будет инвентарный перечень книг, в котором для каждой книги необходимо указывать ее наименование, автора и год издания. Причем количество книг может быть разным, но будем полгать, что не более 100. Для хранения информации об одной книге целесообразно использовать структуру, которая задается в языке С++ с помощью ключевого слова struct, за которым следует ее имя. Само определение структуры, т.е. то, что она будет содержать, записывается в фигурных скобках {}. В данном случае структура будет иметь следующий вид: struct book { Такая конструкция задает своего рода шаблон представления данных, но не сам объект, которым можно было бы оперировать подобно переменной или массиву. Для того чтобы объявить переменную для структуры с именем book используется такая запись: struct book lib; //объявляется переменная типа book После объявления переменной lib имеется возможность работать со структурой как с единым объектом данных, который имеет три поля: title, author и year. Обращение к тому или иному полю структуры осуществляется через точку: lib.title, lib.author и lib.year. Таким образом, для записи в структуру информации можно использовать следующий фрагмент программы: printf(“Введите наименование книги: “); После этого в соответствующие поля будет записана введенная с клавиатуры информация и хранится в единой переменной lib. Однако по условиям задачи необходимо осуществлять запись не по одной, а по 100 книгам. В этом случае целесообразно использовать массив структур типа book, который можно задать следующим образом: struct book lib[100]; В этом случае программу ввода и хранения информации по книгам можно записать в виде: Листинг 3.5. Инвентарный перечень книг. #include int main() Данный пример показывает удобство хранения информации по книгам. Тот же алгоритм в общем случае можно реализовать и без структуры, но тогда пришлось бы использовать два двумерных массива символов и один одномерный массив для хранения года издания. Несмотря на то, что формально такая запись была бы корректной с точки зрения языка С++, но менее удобна в обращении. Структуры можно автоматически инициализировать при их объявлении подобно массивам, используя следующий синтаксис: struct bool lib = { При выполнении данного фрагмента программы в переменные структуры title, author и year будет записана соответственно информация: “Евгений Онегин”, “Пушкин А.С.”, 1995. Здесь следует обратить внимание, что последовательность данных при инициализации должна соответствовать последовательности полей в структуре. Это накладывает определенные ограничения, т.к. при инициализации необходимо помнить последовательность полей в структуре. Стандарт C99 допускает более гибкий механизм инициализации полей структуры: struct book lib = {.year = 1995, или struct book lib = {.year = 1995, или struct book lib = {.author = “Пушкин А.С.”, В первом и во втором примерах при инициализации указываются наименования полей через точку. При этом их порядок и число не имеет значения. В третьем примере первые два поля указаны через имена, а последнее инициализируется по порядковому номеру – третьему, который соответствует полю year. В некоторых случаях имеет смысл создавать структуры, которые содержат в себе другие (вложенные) структуры. Например, при создании простого банка данных о сотрудниках предприятия целесообразно ввести, по крайней мере, две структуры. Одна из них будет содержать информацию о фамилии, имени и отчестве сотрудника, а вторая будет включать в себя первую с добавлением полей о профессии и возрасте: struct tag_fio { Рассмотрим способ инициализации и доступ к полям структуры people на следующем примере. Листинг 3.6. Работа с вложенными структурами. int main() В данном примере показано, что для инициализации структуры внутри другой структуры следует использовать дополнительные фигурные скобки, в которых содержится информация для инициализации полей фамилии, имени и отчества сотрудника. Для того чтобы получить доступ к полям вложенной структуры выполняется сначала обращение к ней по имени man.fio, а затем к ее полям: man.fio.last, man.fio.first и man.fio.otch. Используя данное правило, можно создавать многоуровневые вложения для эффективного хранения и извлечения данных. Структуры, как и обычные типы данных, можно передавать функции в качестве аргумента. Следующий пример демонстрирует работу функции отображения полей структуры на экран. Листинг 3.7. Передача структур через аргументы функции. #include
Структура – тип данных, задаваемый пользователем. В общем случае при работе со структурами следует выделить четыре момента: - объявление и определение типа структуры, - объявление структурной переменной, - инициализация структурной переменной, - использование структурной переменной. Определение типа структуры представляется в виде struct ID { <тип> <имя 1-го элемента>; <тип> <имя 2-го элемента>; ………… <тип> <имя последнего элемента>; }; Определение типа структуры начинается с ключевого слова struct и содержит список объявлений, заключенных в фигурные скобки. За словом struct следует имя типа, называемое тегом структуры (tag – ярлык, этикетка). Элементы списка объявлений называются членами структуры или полями. Каждый элемент списка имеет уникальное для данного структурного типа имя. Однако следует заметить, что одни и те же имена полей могут быть использованы в различных структурных типах. Определение типа структуры представляет собой шаблон (template), предназначенный для создания структурных переменных
Создание структурной переменной возможно двумя способами: с использованием шаблона (типа) или без него. Создание структурной переменной pt на основе шаблона выполняется следующим образом: struct point //Определение типа структуры { int x;int y; }; …… struct point pt; //Создание структурной переменной Структурная переменная может быть задана уникальным образом: struct //Определение анонимного типа структуры { char name[20]; char f_name[40]; char s_name[20]; } copymy; //Создание структурной переменной.
Вопрос 31. Массивы в языке С++. Связь массивов и указателей. Массив- конечная последовательность элементов одного и того же типа. Каждый элемент массива имеет селектор (индекс, номер). С его помощью можно определить любой элемент. double t[48]; В С++ индексы всегда начинаются с 0, поэтому в данном случае последний индекс- 47. double t[48]; double *tt= &t или =&t[0] Имя массива система понимает как указатель на этот массив. cout << *tt; //значение 1-го элемента массива cout << *t << t[0]; Чтобы получить доступ к 3-му элементу массива, можно: t[3] или *(t+3) int a []= {3,4,5,6,7,8,9); Можно объявить массив, не указывая явно, сколько в нем элементов. При этом система должна знать, сколько места в памяти будет этот массив занимать. Каждому массиву при обработке нужно задать еще один параметр: сколько элементов в нем в действительности находится. Исключение: массивы символов. char t [ ]= { ‘7’, ‘6’, ‘5’ }; Каждый символ занимает 1 байт. Символьные массивы отличаются от всех остальных тем, что после символов стоит значок- символ, означающий, что перечисление символов закончено. char t [ ]= { ‘7’, ‘6’, ‘5’ }; \0 -1 символ Поэтому в памяти выделяется 4 байта. Если задать char [3]= {‘7’, ‘6’, ‘5’};,мы допустим ошибку, т.к. 1 место уже занято \0. Поэтому в символьных массивах лучше не указывать [x] Т.е. лучше оставлять[ ]. Последовательность символов – строка. { ‘7’, ‘6’, ‘5’}= “765” char t[ ] = “765”; 0. Массив представляет собой переменную, которая может хранить одно или несколько значений одного и того же типа. 1. Для объявления массива вам следует указать тип, имя массива, а также количество значений, хранящихся в массиве. 2. Значения внутри массива называются элементами массива. 3. Первый элемент массива хранится как элемент 0 (array[OJ), индекс последнего элемента массива на единицу меньше размера массива. 4. Программы часто используют индексные переменные для обращения к элементам массива. 5. Если функция воспринимает массив как параметр, она должна указать тип и имя, но не размер массива. 6. Если программа передает массив в функцию, она, как правило, передает и параметр, который сообщает функции количество элементов содержащихся в массиве. Так как C++ передает массив в функцию с помощью адреса массива функция может изменять значения, содержащиеся в массиве. Несколько переменных одного типа можно объединить под одним именем. Такая переменная будет представлять собой массив. Массив – это тип данных, представляющий собой ограниченный набор упорядоченных элементов одного и того же типа, имеющих одно и то же имя. Элементом массива является переменная. Количество элементов массива определено заранее при объявлении массива. Все элементы упорядочены – каждому присвоен порядковый номер, который называется индексом. Доступ к конкретному элементу массива осуществляется с помощью индекса. В языке C все массивы располагаются в отдельной непрерывной области памяти. Первый элемент массива имеет наименьший адрес, а последний – наибольший. Элементы массива могут быть как простыми переменными, так и составными. Элемент массива может иметь несколько индексов. Количество индексов переменной определяет размерность массива. Размерность массивов в языке C не ограничена, но чаще используются одномерные и двумерные массивы. Начальное значение индекса элемента массива для каждого измерения в C – нуль. Одномерные массивы Как и другие переменные, массив должен быть объявлен. Существует несколько способов объявления массива. Общая форма объявления одномерного массива имеет следующий вид: <класс> тип имя [размер] где класс – необязательный элемент, определяющий класс памяти (extern, static, register); тип – базовый тип элемента массива; имя – идентификатор массива; размер – количество элементов в массиве. Доступ к элементу массива осуществляется с помощью имени массива и индекса. Индекс элемента массива помещается в квадратных скобках после имени. Нижнее значение индекса всегда нуль. Таким образом, элементами массива, состоящего из Nэлементов, являются переменные с индексами a[0],a[1],…,a[N–1]. В качестве N в описании должна стоять целая положительная константа. Объем памяти, необходимый для хранения массива, определяется типом элемента массива и количеством элементов, входящих в массив. Для одномерного массива требуемый объем памяти вычисляется следующим образом: Объем памяти в байтах = sizeof(базовый тип элемента)× длина массива. Во время выполнения программы не проверяется ни соблюдение границ массива, ни его содержимое. Задача проверки и соответственно корректности выполнения программы возложена на программиста. В языке C массивы при объявлении можно инициализировать. Общая форма инициализации массива аналогична инициализации переменной: <класс> тип имя [размер] = {список значений}; Список значений представляет собой список констант, перечисленных в фигурных скобках через запятую. Типы констант должны быть совместимы с типом массива. Первая константа присваивается первому элементу массива, имеющему индекс нуль, вторая – второму и так далее. После закрывающей фигурной скобки точка с запятой обязательна: static float x[5]={7.5,0,–3.2,0,4}; В этом случае будет создан массив на 5 элементов. Если в списке инициализации задать количество элементов меньше, чем задано в объявлении массива, то остальные элементы принимаются равными нулю. Если в списке инициализации задать количество элементов больше, чем задано в объявлении массива, это вызовет ошибку при компиляции программы. При инициализации допустима и следующая форма объявления: <класс> тип имя [] = {a0,a1,…,aМ–1}; Компилятор сам создает массив из М элементов, присваивая им значения a0, a1,…, aМ–1. Двумерные массивы Стандартом C определены многомерные массивы. Простейшая форма многомерного массива – двумерный массив, т. е. массив одномерных массивов. Описание двумерного массива выглядит следующим образом: <класс> тип имя [N1] [N2]; где N1,N2 – количество строк и столбцов. Массив в памяти располагается по строкам: ID[0][0],…,ID[0][N2–1], … ID[N1–[0],…,ID[N1–1][N2–1], где ID – имя массива. Как и в случае одномерных массивов, возможна инициализация двумерных массивов: int a[2][3]= { {1,–2,7}, {2,–3,9} }; Пример программы Что напечатает ЭВМ? # include <stdio.h> int main() { int a[2][3]= { {6,–1}, {–3,2} }; int i,j; for (i=0;i<2;++i) for (j=0;j<3;++j) printf("\n a[%d,%d]=%d",i,j,a[i][j]); } Ответ: a[0,0]=6, a[0,1]=–1, a[0,2] = 0, a[1,0]=–3, a[1,1]=2, a[1,2]=0. Массивы и указатели В языке C массивы и указатели тесно связаны друг с другом. Например, когда объявляется массив в виде int a[25], то при этом не только выделяется память для 25 элементов массива, но и формируется указатель с именем a, значение которого равно адресу первого по счету (нулевого) элемента массива. Доступ к элементам массива может осуществляться через указатель с именем a. С точки зрения синтаксиса языка указатель a является константой, значение которой можно использовать в выражениях, но изменить это значение нельзя. Поскольку имя массива является указателем-константой, допустимо, например, такое присваивание: int a[25]; int *ptr; ptr=a; В этом примере в переменную-указатель ptr записывается адрес начала массива a, т. е. адрес первого элемента массива. Также справедливы следующие соотношения: например, имеется массив a[N], тогда истинными будут следующие сравнения: a==&a[0]; *a==a[0]. Указатели можно увеличивать или уменьшать на целое число: ptr=a+1; Теперь указатель ptr будет указывать на второй элемент массива a, что эквивалентно &a[1]. При увеличении указателя на единицу адрес, который он представляет, увеличивается на размер объекта связанного с ним типа, например: int a[25]; int *ptr=a; ptr+=3; Первоначально указатель ptr указывал на начало массива a. После прибавления к переменной ptr числа 3 значение указателя увеличилось на 3*sizeof(int), а указатель ptr теперь будет указывать на четвертый элемент массива a. Указатель можно индексировать точно так же, как и массив. На самом деле компилятор преобразует индексацию в арифметику указателей, например,ptr[3]=10 представляется как *(ptr+3)=10. К указателям типа void арифметические операции применять нельзя, так как им не ставится в соответствие размер области памяти. Таким образом, в языке C для доступа к элементам массива существует два различных способа. Первый способ связан с использованием обычных индексных выражений в квадратных скобках, например, a[7]=3 или a[i+2]=5. При таком способе доступа записываются два выражения, причем второе выражение заключается в квадратные скобки. Первое из этих выражений должно быть указателем, а второе – выражением целого типа. Указатель, используемый в индексном выражении, не обязательно должен быть константой, указывающей на какой-либо массив, это может быть и переменная-указатель. В частности, после выполнения присваивания ptr=a доступ к седьмому элементу массива можно получить как с помощью константы-указателя a в форме a[7], таки переменной-указателя ptr в форме ptr[7]. Второй способ доступа к элементам массива связан с использованием адресных выражений и операции косвенной адресации в форме *(a+3)=10 или *(a+i+2)=5. При реализации на компьютере первый способ приводится ко второму, т. е. индексное выражение приводится к адресному. Для приведенных примеров обращение к элементу массива a[3]преобразуется в *(a+3). Для доступа к начальному элементу массива, т. е. к элементу с нулевым индексом, можно использовать просто значение указателя a или ptr, поэтому любое из присваиваний *a=2; a[0]=2; *(a+0)=2; *ptr=2; ptr[0]=2; *(ptr+0)=2; присваивает начальному элементу массива значение 2. Многомерные массивы в языке C – это массивы массивов, т. е. массивы, элементами которых, в свою очередь, являются массивы. При объявлении таких массивов в памяти компьютера создается несколько различных объектов. Например, при выполнении объявления двумерного массива int a2[4][3] в программе создается указатель a2, который определяет в памяти местоположение первого элемента массива и, кроме того, является указателем на массив из четырех указателей. Каждый из этих четырех указателей содержит адрес одномерного массива, представляющего собой строку двумерного массива и состоящего из трех элементов типа int, и позволяет обратиться к соответствующей строке массива. Таким образом, объявление a2[4][3] порождает в программе три разных объекта: указатель с идентификатором a2, безымянный массив из четырех указателей и безымянный массив из двенадцати чисел типа int. Для доступа к безымянным массивам используются адресные выражения с указателем a2. Доступ к элементам массива указателей осуществляется с указанием одного индексного выражения в форме a2[2] или *(a2+2). Для доступа к элементам двумерного массива чисел типа int должны быть использованы два индексных выражения в формеa2[1][2] или эквивалентных ей *(*(a2+1)+2) и (*(a2+1))[2]. Следует учитывать, что с точки зрения синтаксиса языка C указатель a2 и указатели a2[0], a2[1], a2[2], a2[3]являются константами, и их значения нельзя изменять во время выполнения программы. Размещение трехмерного массива происходит аналогично. Так, например, объявление float a3[3][4][5] порождает в программе, кроме самого трехмерного массива из 60 чисел типаfloat, массив из четырех указателей на тип float, массив из трех указателей на массив указателей на float и указатель на массив массивов указателей на float. При размещении элементов многомерных массивов они располагаются в памяти подряд по строкам, т. е. быстрее всего изменяется последний индекс, а медленнее – первый. Такой порядок дает возможность обращаться к любому элементу многомерного массива, используя адрес его начального элемента и только одно индексное выражение. Например, обращение к элементу a2[1][2] можно осуществить при помощи указателяptr2, объявленного в форме int *ptr2=a2[0], как обращение ptr2[1×3+2] (здесь 1 и 2 – это индексы используемого элемента, а 3 – число элементов в строке) или какptr2[5]. Заметим, что внешне похожее обращение a2[6] выполнить невозможно, так как указателя с индексом 6 не существует. Для обращения к элементу a3[2][3][4] из трехмерного массива тоже можно использовать указатель, описанный как float *ptr3=a3[0][0], с одним индексным выражением в формеptr3[2×20+3×5+4] или ptr3[59].
Массивы и функции Использование указателей в качестве формальных параметров функции дает возможность передавать из вызывающей подпрограммы в функцию не само значение или массив значений, а адрес переменной (адреса фактических аргументов). В частности, при работе с массивами не требуется использовать в качестве формальных аргументов массив. Это может быть указатель того же типа, что и тип элемента массива. В подпрограмму в этом случае можно передавать адрес начального элемента массива. Пример программы Задан одномерный массив из N элементов. Найти значение максимального элемента массива. Поиск максимума оформить в виде функции max: # include <stdio.h> # define N 3 int max(int k,int* b) //b – указательна целое, //k – количество элементов в массиве { int i,m1; m1=*b; //*b – значение 1-го эл-та массива (с индексом 0) for(i=1;i<k;i++) { b++;//Переход к следующему элементу массива if (m1<*b)m1=*b; //*b – значение текущего эл-та массива } return(m1); } int main() { static int A[N]={1,7,3}; printf("\n max=%d",max(N,&A[0])); return 0; } Рассмотрим теперь пример программы с двумерным массивом. Дан двумерный массив, состоящий из трех строк и четырех столбцов. Найти максимальный элемент каждой строки, используя ранее созданную функцию max: int main() { static int B[3][4]={3,5,1,6,8,3,7,3,2,6,9,3}; printf("\n 1 row: max=%d",max(4,B[0])); printf("\n 2 row: max=%d",max(4,B[1])); printf("\n 3 row: max=%d",max(4,B[2])); return 0; } При вызове функции max использовались указатели на начало строк массива, каждая строка массива содержит 4 значения. Результат работы программы: 1 row: max=6 Рассмотрим передачу двумерного массива в функцию. В качестве параметров функции передается адрес начала массива и количество элементов в строке массива, соответствующее объявлению массива в вызывающей функции (int A2[][N]), а также два целых числа m и n, имеющие смысл фактического количества строк и столбцов, используемых в массиве. Они не должны превышать значения количества строк и столбцов соответственно, заданные при объявлении массива. В примере используются следующие функции: ввод двумерного массива input_mas(), вывод на экран двумерного массива в виде таблицы output_mas(), вычисление суммы элементов массива, имеющих одинаковые номера столбцов и строк int diagonal(): #include <stdio.h> #define N 4 #define M 3 void input_mas(int A2[][N],int m,int n); void output_mas(int A2[][N],int m,int n); int diagonal(int A2[][N],int m,int n); void main() { int mas[M][N]; input_mas(mas,M,N); output_mas(mas,M,N); printf("Summa elementov diagonali = %d\n", diagonal(mas,M,N)); return 0; } void input_mas(int A2[][N],int m,int n) { int i,j; printf("Wwedite chisla->"); for(i=0;i<M;i++) for(j=0;j<N;j++) scanf("%d",&A2[i][j]); } void output_mas(int A2[][N],int m,int n) { int i,j; printf("Wwedeno:\n"); for(i=0;i<M;i++) { for(j=0;j<N;j++) printf("%7d",A2[i][j]); printf("\n"); } } int diagonal(int A2[][N],int m,int n) { int i,j,summa=0; for(i=0;i<M;i++) for(j=0;j<N;j++) if (i==j) summa+=A2[i][j]; return summa; }
|
||||
Последнее изменение этой страницы: 2016-08-15; просмотров: 984; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.220.200.197 (0.015 с.) |