Задачи системного программирования часто связаны с обработкой символьных массивов неопределенной длины. именно для их обработки чаще и используются указатели
. Пример обработки массива строкчерез массив указателей
char *p ; int I, j ; // временные указатель и переменные
while ( true ) // цикл ввода не менее пяти строк
{
cout << “Enter not less than 5 lines “
<< “or empty line for an exit\n” ;
for ( I = 0; I < SIZE ; i++ ) // цикл ввода строк
{
cin.getline ( str, LEN ) ;
if ( ! *str ) // если строка пустая,
break ; // то выйти из цикла ввода for
// выделение блока памяти
pa [ I ] = new char [ strlen ( str ) + 1 ] ;
// дублирование str в выделенный блок
strcpy_s ( pa [ I ], LEN, str ) ;
}
if ( I < 5 ) // если введено < 5 строк,
for ( j = 0; j < I; j++ )
delete pa [ j ] ; // то освободить память
else break ; // иначе выйти из цикла while
} // окончание цикла while
n = I ; // сохранение числа введенных строк
// вывод введенных строк
cout << “\nENTERED ARRAY\n” ;
for ( I = 0 ; I < n ; i++ ) cout << pa [ I ] << endl ;
// поиск самой короткой строки
int iMin = 0 ; // индекс строки с минимальной длиной
for ( I = 1; I < n; i++ )
if ( strlen ( pa [ I ] ) < strlen ( pa [ iMin ] ) )
iMin = I ;
// Обработка массива
if ( iMin ) // если строка не первая ( iMin != 0 ),
{
p = pa [ iMin ] ; // то запомнить ее адрес
// определить новый порядок строк: с адреса pa [iMin] до адреса pa [1]
// на место текущего адреса pa [i] записывать предыдущий адрес pa [i-1]
for ( I = iMin; I > 0; i-- ) pa [ I ] = pa [ I – 1 ] ;
// переопределить адрес первой строки
pa [ 0 ] = p ;
}
cout << “\nARRAY – RESULT\n” ;
for ( I = 0; I < n; i++ )
{ cout << pa [ I ] << endl ; delete pa [ I ] ; }
delete str ;
return 0 ;
}
Стандарт ISO/ANSI C++ расширил библиотеку C++, добавив класс string. Поэтому вместо применения символьных массивов для хранения строк можно применить переменные типа string. Чтобы использовать класс, в программе должен быть включен заголовочный файл string. Класс string являются частью пространства имен std, поэтому необходимо указать директиву using иначе обращаться к классу по имени std::string. Определение класса скрывает природу строки как массива символов и позволяет трактовать ее как обычную переменную.
cout<<”Длина строки str1 после ввода: ”<<str1.size()<<endl;
cout<<” Длина строки charr1 после ввода:”<<strlen(charr1)<<endl;
}
Структура – составной тип данных, состоящий из фиксированного числа разнотипных компонентов, обеспечивающий иерархию данных.. Тип компонентов может быть любым. Структура объединяет логически связанные данные разных типов и представляет собой набор переменных, которые объединены общим именем.
Например, необходимо иметь сведения о студенте: его Ф. И. О., номер группы, средний бал успеваемости:
struct tinfstud
{
char name[20];
char grup[6];
int bal;
}
Ключевое слово struct указывает на то, что этот код определяет план структуры. Идентификатор tinfstud- дескриптор этой формы, то есть идентификатор нового типа и им можно пользоваться как стандартными типами. Далее между фигурными скобками находится список переменных, которые будут содержаться в переменной типа структуры. Элементы структуры называют переменными-членами или полями данных.Полями данныхмогут быть и структуры. Они называются вложенные. Объявление структуры не резервирует пространство в ОП, оно лишь создает новый тип данных. Память выделяется при объявлении переменной типа структура (tinfstud).
Пример объявления переменной типа tinfstud:
tinfstud zap;
После данного объявления в ОП по символьному адресу zap выделится участок памяти равный сумме длин полей структуры. Каждый элемент структуры обрабатывается отдельно. Доступ к полям структуры осуществляется в соответствии с иерархией вложения. Для доступа к отдельным членам структуры используют операцию принадлежности, или членства (.).
Пример обращения к элементам структуры:
zap.bal; zap. grup: zap.name;
Переменная типа структура может быть как статическая, так и динамическая. При организации динамической структуры оператор new захватывает ОП в соответствии с базовым типом.
Пример организации динамической структуры:
tinfstud *pz = new tinfstud;
Для доступа к элементам структуры через указатель на переменную служит операция стрелка (->).Обе операции (. и ->) помещаются между именем переменной типа структуры и идентификатором элемента структурного типа.
Пример программы с простой структурой
#include <iostream>
using namespace std ;
int main ( )
{
// объявление типа структуры
struct Address {
char city [ 20 ] ; // город
char street [ 30 ] ; // улица
int house ; // номер дома
} ;
// объявление переменной
Address a ;
// ввод значений элементов
cin >> a . city ; cin >> a . street ; cin >> a . house ;
// объявление указателя с инициализацией
Address *p = new Address ;
// ввод значений элементов
cin >> p -> city ; cin >> p -> street ; cin >> p -> house ;
// присваивание структур
Address copy ; copy = a ; copy = * p ;
return 0 ;
}
Пример иерархической структуры
#include <iostream>
using namespace std ;
int main ( )
{
// простые структуры
struct Address {
char city [ 20 ]; char street [ 30 ]; int house ;
} ;
struct Person {
char Fname [ 15 ] ; char Lname [ 20 ] ;
} ;
// иерархическая структура
struct Employee {
Person p ; // вложенная структура
Address addr ; // вложенная структура
} ;
// объявление переменной указателя
Employee *p = new Employee ;
// ввод значений элементов
cin >> p -> p . Fname ; cin >> p -> p . Lname ;
cin >> p -> addr . city ;
cin >> p -> addr . street ;
cin >> p -> addr . house ;
return 0 ;
}
Операции отношения (==, !=, >, <, и т.д.)над структурами недопустимы. Оператор присвоения (=) выполняется над однотипными структурами. Эта операция устанавливает значение каждого члена одной структуры равным каждому соответствующему члену другой структуры, доже если член является массивом Такой тип присвоения называется почтовым присвоением. Структуру целиком читают или записывают в файл. Структуру можно передавать в качества аргумента функции, и функция может использовать структуру в качестве возвращаемого значения. Во всех остальных случаях в структуре обрабатывается каждое поле отдельно операциями его типа. Ввод переменных-членов структур производится также в соответствии с типом.
Инициализация структур может быть выполнена в момент объявления переменной. Для этого в операторе объявления переменной необходимо после операции присвоения в фигурных скобках указать значения элементов в порядке их объявлении. Если структура является иерархической, то значения каждой вложенной переменной структуры заключаются в отдельные фигурные скобки. Если членом структуры является массив, то значения всех элементов массива должны быть последовательно указаны.
Пример инициализации переменных структурного типа
#include <iostream>
using namespace std ;
int main ( )
{
struct Time { int hour ; int minute ; int second ; } ;
struct Interval { Time top ; Time end ; } ;
// инициализация простой структуры
Time top = { 5, 30, 0 } ; Time end = { 15, 30, 45 } ;
// инициализация иерархической структуры
Interval i1 = { { 5, 30, 0 }, { 15, 30, 45 } } ;
// вывод структурной переменной i1
cout << i1.top.hour << ':' ;
cout << i1.top.minute << ':' ;
cout << i1.top.second << " - " ;
cout << i1.end.hour << ':' ;
cout << i1.end.minute << ':' ;
cout << i1.end.second << endl ;
// структура с элементом двумерный массив
struct Book { char author [ 2 ] [ 50 ] ; char title [ 100 ] ; } ;
// иерархическая структура
struct BookCard { int number ; Book book ; } ;
// инициализация структурной переменной
BookCard c = { 12, "Harvey M. Deitel", "Payl J. Deitel",
"C++ How to Program" } ;
// вывод структурной переменной
cout << c.number << " - " ;
cout << c.book.author [ 0 ] << ", " ;
cout << c.book.author [ 1 ] << "/ " ;
cout << c.book.title << endl ;
return 0 ;
}
Массивы структур ничем не отличаются от массивов встроенных типов данных и обрабатываются как обычно.
strcpy_s ( roadArray [ i ] . name, 30, pName [ i ] ) ;
roadArray [ i ] . length = len [ i++ ] ;
}
// объявление указателя на массив типа структуры
Road* pRailRoad = new Road [ size ] ;
// приравнивание массивов
for ( i = 0; i < size; i++ )
* ( pRailRoad + i ) = roadArray [ i ] ;
// вывод значений из массива с адресом pRailRoad
Road* p = pRailRoad ;
do
{
cout << p -> name << '\t' << p -> length << '\n' ;
p++ ;
} while ( p < pRailRoad + size ) ;
// вычисление общей длины дорог
double total = 0 ;
for ( i = 0, p = pRailRoad ; i < size; i++ )
total += p++ -> length ;
cout << "\nSummary length = " << total << endl ;
return 0 ;
}
Microsoft Visual C++, после версии 7.1, поддерживает инициализацию структур членами типа класса string. Для этого необходимо обеспечить доступ к пространству имен std.
Пример использования в структуре членов типа класса string:
# include <string>
struct inflatable
{
std :: string name;
float volume;
double price;
} zap;
Битовые поля в структурах на языке С++ - это такая организация структуры, которая позволяет специфицировать члены структур, таким образом что они могут занимать определенное число битов в ОП. Каждый член называется битовым полем.
Формат определения битового поля:
имя_типа имя_поля : количество бит;
# include <stdio.h>
void main ()
{
struct bits
{
int I : 2;
unsigned j : 6;
int k : 3;
unsigned l : 5;
} a; //a – переменная типа bits занимает 2 байта
}
Инициализация полей выполняется в обычной манере и использовать стандартную нотацию структур для доступа к битовым полям: a.i = 2; a.j = 9; a.k = 7; a.l = 5;
Эта организация применяется для создания структур данных, которые подходят для регистрации на некотором аппаратном устройстве.
Объединение– это формат данных, который может хранить разные типы данных в пределах одной области памяти, но в каждую единицу времени только один из них. Объединение используется в случае, если значения переменных объединения не используются одновременно, а поочередно, атак же для преобразования типов. Размер ОП определяется размером наибольшего поля.
Формат организации объединения:
union имя_типа
{
члены объединения
}има_переменной;
Пример организации переменной:
union tob
{
int vin;
long vlon;
double vdb;
} pail;
pail.vin =15;
Объединение может применяться в структуре как поле, которое в одной ситуации одного типа, а в другой – другого типа.