Нижегородский государственный университет им. Н.И.Лобачевского
Опубликован: 25.11.2008 | Доступ: свободный | Студентов: 9320 / 1222 | Оценка: 4.06 / 3.66 | Длительность: 21:16:00
Лекция 10:

Пользовательские типы данных

< Лекция 9 || Лекция 10: 123 || Лекция 11 >
Аннотация: В данной лекции основное внимание уделено пользовательским типам данных - структурам, перечислениям и объединениям. Приводятся практические примеры и основные принципы использования пользовательских типов данных

К пользовательским типам данных относятся нестандартные данные, о структуре которых система не имеет представления, и операции над которыми стандартом языка C не определены. Структура таких данных становится известной компилятору только по описанию, содержащемуся в тексте исходной программы. К пользовательским данным такого типа относятся массивы (о них речь шла в предыдущем разделе), структуры (в других алгоритмических языках они известны под термином записи ), перечисления (в некоторых книгах по языкам C, C++ их относят к целочисленным данным) и объединения.

9.1. Структуры

Первоначальным образом для данных типа структур явились строки таблиц, с которыми знаком любой человек. Характерным для таблиц любого содержания является наличие столбцов, в каждом из которых хранятся однотипные данные. Однако в соседних столбцах типы данных могут отличаться. Если специфической особенностью массивов является использование одного и того же типа для всех элементов массива, то строки таблиц можно представлять как последовательность полей данных разного типа. Для каждого поля строки таблицы известно наименование соответствующего столбца таблицы и тип размещаемого в этом поле значения. Например, поле "Фамилия" заполняется текстовой информацией, поле "Год рождения" хранит целочисленные данные, на поле "Пол" достаточно записывать единственный символ 'М' или 'Ж' и т.д.

9.1.1. Объявление и инициализация структур

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

struct book {
    char title[40];             //наименование
    char authors[30];           //авторы
    char publishing_house[15];  //издательство
    int year;                   //год издания
    int pages;                  //количество страниц
    float price;                //цена
  }

Идентификатор book выполняет функцию имени шаблона или типа структуры. В дальнейшем им можно пользоваться для объявления конкретных переменных – структур типа book:

struct book b1,b2,b3;   //три переменных типа book

В языке C++ служебное слово struct можно опускать:

book b1,b2,b3;

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

Вообще говоря, объявление шаблона структуры и переменных, связанных с этой структурой, можно совместить:

struct book {
    char title[40];
    char authors[30];
    char publishing_house[15];
    int year;
    int pages;
    float price;
  } b1,b2,b3;

Более того, в объявлении шаблона структуры можно опустить имя шаблона:

struct {
    char title[40];
    char authors[30];
    char publishing_house[15];
    int year;
    int pages;
    float price;
  } b1,b2,b3;

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

Для доступа к соответствующим полям структур используются составные имена, образованные из имени структуры и имени поля:

strcpy(b1.title,"C++:Экспресс курс");
  strcpy(b1.authors,"В.Лаптев");
  cout << b1.title;
  b1.year=2004;

Если мы имеем дело с указателем, который настроен на адрес структуры, то составные имена записываются с использованием двух символов "->":

struct book *p=&b1;		//указатель на структуру
  strcpy(p->title,"C++:Экспресс курс");
  strcpy(p->authors,"В.Лаптев");
  cout << p->title;
  p->year=2004;

Структуры могут объединяться в массивы:

struct book c[20];    //массив структур

И тогда для доступа к полям соответствующего элемента используются индексированные составные имена:

strcpy(с[2].title,"Язык C++ ")
  strcpy(c[2].authors,"В.В.Подбельский");
  cout << c[2].title;
  c[2].year=1996;
  struct book *pс=с;
  strcpy(pс[2]->title,"C++:Экспресс курс");
  strcpy(pс[2]->authors,"В.Лаптев");
  cout << pс[2]->title;
  pс[2]->year=2004;

При объявлении переменных типа структура их поля могут быть проинициализированы довольно естественным способом:

struct book a={"Programming Languages", "Jean E.Sammet",
                 "Prentice-Hall", 1969,785,49.99};

Для структур, объявленных с использованием одного и того же шаблона, допустима операция присваивания:

b1=a;	//все поля структуры a копируются в структуру b1

К сожалению, одноименные поля строкового типа у структур так копировать нельзя – необходимо прибегать к услугам функций типа strcpy:

strcpy(b1.authors,a.authors);	//копируем поле "авторы"

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

Некоторые числовые поля структур могут быть объявлены как битовые шкалы с указанным количеством двоичных разрядов. С одной стороны, это предоставляет возможность компоновать в рамках машинных слов некоторые группы данных и располагать их более компактно в оперативной памяти. С другой стороны, такая возможность избавляет программиста от забот по выделению и вклеиванию соответствующих групп двоичных разрядов. Однако на расположение битовых полей в структурах оказывает дополнительное влияние установка компилятора – признак выравнивания данных на границу байта, слова, двойного слова. Длины битовых шкал при объявлении структур задаются следующим образом:

struct qq{ int a:10; int b:14; } xx, *px;
  xx.a=127;
  px=&xx;
  px->b=9;

В зависимости от признака выравнивания границ данных эти значения могут быть расположены в оперативной памяти по-разному:


С целью принудительного расположения битовых полей в таких структурах допускается вставка безымянных полей:

struct { int a:10;
           int  :6;
           int b:14; } yy;
< Лекция 9 || Лекция 10: 123 || Лекция 11 >
Alexey Ku
Alexey Ku

Попробуйте часть кода до слова main заменить на 

#include "stdafx.h" //1

#include <iostream> //2
#include <conio.h>

using namespace std; //3

Александр Талеев
Александр Талеев

#include <iostream.h>
#include <conio.h>
int main(void)
{
int a,b,max;
cout << "a=5";
cin >> a;
cout <<"b=3";
cin >> b;
if(a>b) max=a;
else max=b;
cout <<" max="<<max;
getch();
return 0;
}

при запуске в visual express выдает ошибки 

Ошибка    1    error C1083: Не удается открыть файл включение: iostream.h: No such file or directory    c:\users\саня\documents\visual studio 2012\projects\проект3\проект3\исходный код.cpp    1    1    Проект3

    2    IntelliSense: не удается открыть источник файл "iostream.h"    c:\Users\Саня\Documents\Visual Studio 2012\Projects\Проект3\Проект3\Исходный код.cpp    1    1    Проект3

    3    IntelliSense: идентификатор "cout" не определен    c:\Users\Саня\Documents\Visual Studio 2012\Projects\Проект3\Проект3\Исходный код.cpp    6    1    Проект3

    4    IntelliSense: идентификатор "cin" не определен    c:\Users\Саня\Documents\Visual Studio 2012\Projects\Проект3\Проект3\Исходный код.cpp    7    1    Проект3

при создании файла я выбрал пустой проект. Может нужно было выбрать консольное приложение?

 

 

 

Александр Шнайдман
Александр Шнайдман
Израиль, Тель Авив