![]() Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь 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; просмотров: 994; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.129.67.120 (0.017 с.) |