Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Максимов_электронный_учебник_текст.doc
Скачиваний:
2
Добавлен:
12.11.2019
Размер:
3.26 Mб
Скачать

5.4. Свойства объекта cout

С помощью объекта cout класса iostream и перегруженной операции << на экран монитора выводится значение выражения стоящего справа от <<, причем формат вывода на экран значения выражения зависит от его типа. Особо следует выделить случай, когда значение выражения имеет тип char, unsigned char, char*, unsigned char*.

Например

char st1 = ‘S’, st2 = 83;/*Определение и инициализация переменных st1 и st2. Причём st1 и st2 равны друг другу, так как символьная константа ‘S’ в соответствии с таблицей ASCII имеет код 83.*/

int i = 83;

cout<<”\n st1 = “<<st1<<”\t st2 = “<<st2<<”\t i = “<<i; /*Вывод на экран значений st1, st2 и i. Поскольку st1 и st2 имеют тип char, то печатается не их значение, а соответствующий этому значению по таблице ASCII символ, т е. будет напечатано st1 = S, st2 = S. Переменная i имеет тип int, поэтому печатается просто её значение i = 83.*/

char *pc = “Язык Си++”; /*Строковая константа, состоящая из 9 байт. Первые восемь байт содержат числовые коды соответствующих символов, а последний девятый байт содержит код 00 и является признаком конца строковой константы. Указатель pc инициализируется адресом первого байта. */

int i = 83, *pi=NULL;

pi = &i;

cout<<”\n pc = “<< pc<<”\t pi = “<<pi; /* На экране печатается pc = Язык Си++ pi = 532465*/

Объект cout по-разному ведет себя c указателями типов char*, unsigned char* и указателями других типов. Так, вместо значения pc (адреса), объект cout начиная с адреса, записанного в pc и до байта с кодом 00, воспринимает фрагмент памяти как фрагмент, содержащий строковую константу, и печатает её на экране. Если по каким-либо причинам строковая константа не была завершена кодом 00, то объект cout выведет строковую константу и будет выводить далее содержимое всех байтов в символьном виде до тех пор, пока не наткнется на байт с кодом 00, т.е. за строковой константой будет выведен какой-то мусор. При выводе значения указателя pi типа int на экран будет выведено просто значение pi, т. е. число являющееся адресом переменной i. Пример:

char p[5] = {‘М’, ‘и’, ‘р’}; /*определен массив и инициализированы первые три его элемента */

cout<<p; //Печатает Мир и далее мусор

p[3] = ‘\0’; //Управляющий символ ‘\0’, который записывает в p[3] код 0x00

cout<<p; //Печатает просто Мир без мусора

5.5. Массивы и указатели

Определение массива

type имя_массива [константное_выражение] инициализатор;

где type – тип элементов массива; имя_массива – идентификатор массива; инициализатор – не обязательное инициализирующее выражение; константное_выражение – выражение, значение которого вычисляется во время компиляции, а не во время выполнения программы. Это значит, что во время выполнения программы нельзя увеличивать размерность массива. Поэтому такие массивы называются статическими.

Инициализировать элементы массива можно следующим образом:

int f[] = {2, 5, ‘S’}; /*Вместо символа S компилятор подставит соответствующее ему по таблице ASCII число. Размер массива равен трем, задаётся неявно с помощью инициализатора.*/

char a[5] = {2, 5, ‘S’}; /* Размер массива равен 5 задаётся явно. Первые три элемента массива инициализируются соответствующими значениями. */

char a[2] = {2, 5, ‘S’};// Ошибка инициализации

Для массивов типа char принят ещё один способ инициализации:

char pc[] = “Привет всем”;/*Размер массива равен 12, задаётся неявно и определяется количеством символов, заключенных в кавычки, плюс невидимый, так называемый нулевой символ ‘\0’. Полным аналогом такого способа инициализации является строка char pc[] = {‘П’, ‘р ’, ’и’, ’в’, ’е’, ’т’,’ ’,’в’,’с’,’е’,’м’,’\0’};*/

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

extern type имя_массива[];

где type и имя_массива должны совпадать с типом и именем массива определенного где-то в программе. Type можно опустить, в этом случае по умолчанию будет предполагаться, что type имеет тип int. Пример:

extern f[]; //Описание массива типа int, определенного где-то в программе.

extern char pc[];/*Описание массива типа char, определенного где-то в программе.*/

Если массив был описан, но не определен, то на этапе компоновки будет выдано сообщение об ошибке.

Над именем массива определена операция sizeof(имя_массива). Результатом этой операции является количество байт, выделенных под массив. Используя эту операцию можно определить, сколько элементов имеется в массиве, например:

double k[5];

cout<<”\n Количество элементов в массиве k = “;

cout<<sizeof(k)/sizeof(double); //

Результат работы программы:

Количество элементов в массиве k = 5

int ar []= { 4, 6,7,8,7};

for(int i = 0; i<sizeof(ar)/sizeof(int); i ++) cout<<”\t ar[ “<< i<<”]= ”<<ar[i];

Доступ к конкретному элементу массива можно выполнить с помощью операции имя_массива[ индекс], причём программа должна быть написана так, чтобы изменение индекса лежало в пределах интервала [0, константного_выражения–1]. При выходе индекса за пределы интервала программа начинает обращаться к памяти, которая не была выделена под массив и, следовательно, результаты работы такой программы непредсказуемы. Ни компилятор, ни компоновщик не проверяют диапазон изменения индекса, программист сам должен обеспечивать выполнение правила обращения к элементам массива.

Имя массива – это константный указатель, значение которого равно адресу первого элемента массива. Единственное отличие, которое есть, например, между именем массива ai и константным указателем pi, определенным ниже как

long ai[5];

const long * pi = &ai[0];/* или const long * pi = ai; т.е. &ai[0] = = ai заключается в результате выполнения операции sizeof(), так при выполнении операции sizeof(ai) результат будет равен 20, а sizeof(pi) результат будет равен 4. Поскольку ai это имя массива, которое является константным указателем, а pi – константный указатель, настроенный на первый элемент массива. */

Во всем остальном они подобны. Это означает, что к указателям можно применять операцию [ ], а к именам массивов все правила адресной арифметики, связанной с указателями. Более того, запись имя_массива[ индекс] является выражением с двумя операндами. Первый из них, т.е. имя_массива – это константный указатель – адрес начала массива в основной памяти; индекс  это выражение целого типа, определяющее смещение от начала массива. Используя операцию обращения по адресу *, действие бинарной операции [] можно объяснить так: *(имя_массива + индекс). Поскольку операция сложения коммутативна, то можно записать и так *(индекс+ имя_массива), а, следовательно, операцию [], можно представить в виде индекс[имя_массива]. Например, обращение к элементам массива ai через имя массива или указатель pi, которые были определены выше, можно записать

ai[0] == pi[0] == *ai == *pi == 0[ai] == 0[pi],

ai[1] == pi[1] == *(ai+1) == *(pi+1)== 1[ai] == 1[pi],

ai[4] == pi[4] == *(ai+4) == *(pi+4)== 4[ai] == 4[pi].

Но ошибкой будет запись *(ai++), или *(pi++), или *(pi = pi+4), или *(ai = ai+4), так как ai и pi  константные указатели. Необходимо также помнить, что при прибавлении целого числа (индекса) к указателю на самом деле прибавляется число равное индекс*sizeof(type), где type  тип объекта, к которому отнесен указатель.

Использовать операцию [] c указателями очень удобно. Она коротка с точки зрения записи, интуитивно понятна, не изменяет значение указателя и может использоваться и с неконстантными указателями. Например, напишем функцию, которая в обратном порядке выводит на экран содержимое строки.

//Программа 5.4

#include "stdafx.h"

#include <iostream>

void fstr(char* pst){

int strlen = 0;

for(; pst[strlen] != '\0'; strlen++); /*Определяем длину строки. Телом цикла является пустой оператор. */

for(int i = strlen-1; i >= 0; i--) std::cout<< pst[i]; /*Выводим строку посимвольно в обратном порядке на экран, используя указатель pst и операцию []. */

}

void main(){

char p [] = "Example work of operation []";

fstr(p);/*При вызове функции формальному параметру pst присваивается значение фактического параметра p. Таким образом, указатель pst настраивается на первый элемент массива р.*/

getchar();

}