int days[12]; days[0] = 31; // январь days[1] = 28; // февраль days[2] = 31; // март days[3] = 30; // апрель days[4] = 31; // май days[5] = 30; // июнь days[6] = 31; // июль days[7] = 31; // август days[8] = 30; // сентябрь days[9] = 31; // октябрь days[10] = 30; // ноябрь days[11] = 31; // декабрь
В первой строчке мы объявили 12 элементов типа int и дали ему имя days. Остальные []. Как видно из примера, первый элемент 0, соответственно, последний – 11.
При объявлении
Предположим, мы хотим распечатать все элементы days. Для этого удобно воспользоваться циклом for.
for (int i = 0; i < 12; i++) {
cout << days[i];
}
Следует отметить, что при выполнении программы границы 12 в приведенном выше цикле написали 13, то компилятор не выдаст ошибку. При выполнении программа попытается напечатать 13 -е число. Что при этом случится, вообще говоря, не определено. Быть может, произойдет сбой программы. Более вероятно, что будет напечатано какое-то случайное 13 -е число. Выход индексов за границы [] и добавить контроль за индексами.
Отсутствие контроля индексов налагает на программиста большую ответственность. С другой стороны, индексация – настолько часто используемая операция, что наличие контроля, несомненно, повлияло бы на производительность программ.
Рассмотрим еще один пример. Предположим, что имеется 100 целых чисел, и его необходимо отсортировать, т.е. расположить в порядке возрастания. Сортировка методом "пузырька" – наиболее простая и распространенная – будет выглядеть следующим образом:
int array[100];
. . .
for (int i = 0; i < 99; i++ ) {
for (int j = i + 1; j < 100; j++) {
if (array[j] < array[i] ) {
int tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
}
В приведенных примерах у
int m[10][5];
представляет матрицу целых чисел размером 10 на 5. По-другому интерпретировать приведенное выше объявление можно как 10 элементов, каждый из которых – вектор целых чисел длиной 5. Общее количество целых чисел в m равно 50.
Обращение к элементам многомерных m[1][2] обращается к третьему элементу второй m.
Количество размерностей в
При объявлении
int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
При инициализации многомерных
double temp[2][3] = {
{ 3.2, 3.3, 3.4 },
{ 4.1, 3.9, 3.9 } };
Интересной особенностью инициализации многомерных
double temp[][3] = {
{ 3.2, 3.3, 3.4 },
{ 4.1, 3.9, 3.9 } };
// Вычислить размер пропущенной размерности
const int size_first = sizeof (temp) / sizeof
(double[3]);
struct Record {
int number;
char name[20];
};
Так же, как и для классов, операция " ." обозначает обращение к элементу
В отличие от классов, можно определить переменную-
struct {
double x;
double y;
} coord;
Обратиться к атрибутам переменной coord можно coord.x и coord.y.
В char ), который занимает 8 битов. До сих пор, несмотря на мегабайты и даже гигабайты оперативной памяти, используемые в современных компьютерах, существует немало задач, где каждый бит на счету.
struct TimeAndDate
{
unsigned hours :5; // часы от 0 до 24
unsigned mins :6; // минуты
unsigned secs :6; // секунды от 0 до 60
unsigned weekDay :3; // день недели
unsigned monthDay :6; // день месяца от 1 до 31
unsigned month :5; // месяц от 1 до 12
unsigned year :8; // год от 0 до 100
};
Одна TimeAndDate требует всего 39 битов, т.е. 5 байтов (один байт — 8 битов). Если бы мы использовали для каждого атрибута этой char, нам бы потребовалось 7 байтов.
Особым видом struct используется union:
union number {
short sx;
long lx;
double dx;
};
В отличие от
struct Value {
enum NumberType { ShortType, LongType,
DoubleType };
NumberType type;
short sx; // если type равен ShortType
long lx; // если type равен LongType
double dx; // если type равен DoubleType
};
Атрибут type содержит тип хранимого числа, а соответствующий атрибут
Value shortVal; shortVal.type = Value::ShortType; shortVal.sx = 15;
Хотя память выделяется под все три атрибута sx, lx и dx, реально используется только один из них. Сэкономить память можно, используя
struct Value {
enum NumberType { ShortType, LongType,
DoubleType };
NumberType type;
union number {
short sx; // если type равен ShortType
long lx; // если type равен LongType
double dx; // если type равен DoubleType
} val;
};
Теперь память выделена только для максимального из этих трех атрибутов (в данном случае dx ). Однако и обращаться с
(рис 8.1) Использование памяти в объединениях.Замечание.
int:
int x;
Можно определить переменную типа "
int* xptr;
и присвоить переменной xptr x:
xptr = x;
Операция , примененная к переменной, – это операция взятия *, примененная к
int y = x; // присвоить переменной y значение x int y = *xptr; // присвоить переменной y значение, // находящееся по адресу xptr
С помощью операции
*xptr = 10; // записать число 10 по адресу xptr
После выполнения этого оператора значение переменной x станет равным 10, поскольку xptr указывает на переменную x.
xptr –
unsigned long* lPtr; // указатель на целое число без знака char* cp; // указатель на байт Complex* p; // указатель на объект класса Complex
Если -> ", например p->real. Если вспомнить один из предыдущих примеров:
void
Complex::Add(Complex x)
{
this->real = this->real + x.real;
this->imaginary = this->imaginary +
x.imaginary;
}
то this – это Add. Запись this-> означает обращение к атрибуту текущего объекта.
Можно определить
int foo(long x); int bar(long x);
можно определить переменную типа
int (*functptr)(long x); functptr = foo; (*functptr)(2); functptr = bar; (*functptr)(4);
Для чего нужны
int* hardwareRegister =0x80000; *hardwareRegister =12;
Однако использование
struct TempResults {
double x1;
double x2;
} tempArea;
// Функция calc возвращает истину, если
// вычисления были успешны, и ложь – при
// наличии ошибки. Вычисленные результаты
// записываются на место аргументов по
// адресу, переданному в указателе trPtr
bool
calc(TempResults* trPtr)
{
// вычисления
if (noerrors) {
trPtr->x1 = res1;
trPtr->x2 = res2;
return true;
} else {
return false;
}
}
void
fun1(void)
{
. . .
TempResults tr;
tr.x1 = 3.4;
tr.x2 = 5.4;
if (calc(tr) == false) {
// обработка ошибки
}
. . .
}
В приведенном примере проиллюстрированы сразу две возможности использования TempResults используется для хранения данных. Вместо того чтобы передавать эти данные по отдельности, в функцию calc передается calc возвращает булево значение – признак успешного завершения вычислений. Сами же результаты вычислений записываются в
Упомянутые примеры использования
С
int x = 10;
int y = 10;
int* xptr = x;
int* yptr = y;
// сравниваем указатели
if (xptr == yptr) {
cout << "Указатели равны" << endl;
} else {
cout << "Указатели не равны" << endl;
}
// сравниваем значения, на которые указывают
// указатели
if (*xptr == *yptr) {
cout << "Значения равны" << endl;
} else {
cout << "Значения не равны" << endl;
}
Однако результат второй операции сравнения будет истинным, поскольку переменные x и y имеют одно и то же значение.
Кроме того, над xPtr – long, а cp – char. Начиная с 1000, в памяти расположены два целых числа. 1004 (в большинстве реализаций Си++ под тип long выделяется четыре байта). Начиная с 2000, в памяти расположены объекты типа char.
(рис 8.2) Адресная арифметика.Размер памяти, выделяемой для числа типа long и для char, различен. Поэтому xPtr и cp тоже изменяется по-разному. Однако и в том, и в другом случае увеличение ptr всегда изменяется на число, кратное sizeof(*ptr).
Между 100 целых чисел. Запишем двумя способами программу суммирования элементов этого
long array[100];
long sum = 0;
for (int i = 0; i < 100; i++)
sum += array[i];
То же самое можно сделать с помощью
long array[100];
long sum = 0;
for (long* ptr = array[0];
ptr < array[99] + 1; ptr++)
sum += *ptr;
Элементы
for (long* ptr = array;
ptr < array[99] + 1; ptr++)
sum += *ptr;
Хотя смешивать
При использовании многомерных exmpl:
long exmpl[5][6][7]
то выражение вида exmpl[1][1][2] – это целое число, exmpl[1][1] – вектор целых чисел ( *long ), exmpl[1] – двухмерная матрица или (*long)[7] ). Таким образом, задавая не все индексы
Особым случаем void используется для того, чтобы показать, что
void* ptr;
Для void не определена операция ->, не определена операция *, не определена
В программе на языке Си++ безтиповый
void
printbytes(void* ptr, int nbytes)
{
if (nbytes == 1) {
char* cptr = (char*)ptr;
cout << *cptr;
} else if (nbytes == 2) {
short* sptr = (short*)ptr;
cout << *sptr;
} else if (nbytes == 4) {
long* lptr = (long*)ptr;
cout << *lptr;
} else {
cout << "Неверное значение аргумента";
}
}
В примере используется операция явного преобразования типа. Имя типа, заключенное в круглые скобки, стоящее перед выражением, преобразует значение этого выражения к указанному типу. Разумеется, эта операция может применяться к любым
В программах на языке Си++ значение
long* foo(void);
. . .
long* resPtr;
if ((resPtr = foo()) != 0) {
// использовать результат
} else {
// ошибка
}
В языке Си++ определена символическая NULL для обозначения нулевого значения
Такое использование нулевого 0 данные программы располагаться не могут, он зарезервирован операционной системой для своих нужд. Однако во многом нулевой
Для того чтобы работать с текстом, в языке Си++ не существует особого встроенного типа данных. Текст представляется в виде последовательности знаков (байтов), заканчивающейся нулевым байтом. Иногда такое представление называют Си-строки, поскольку оно появилось в языке Си. Кроме того, в Си++ можно создать классы для более удобной работы с текстами (готовые классы для представления
char string[20]; string[0] = 'H'; string[1] = 'e'; string[2] = 'l'; string[3] = 'l'; string[4] = 'o'; string[5] = 0;
В string записана
Для записи строковых
"Это строка" "0123456789" "*"
Заметим, что символ, заключенный в двойные кавычки, отличается от символа, заключенного в апострофы.
С помощью
char alldigits[] = "0123456789";
Размер
При работе со char:
const char* message = "Сообщение программы";
Значение CopyString копирует первую
void
CopyString(char* src, char* dst)
{
while (*dst++ = *src++)
;
*dst = 0;
}
int
main()
{
char first[] = "Первая строка";
char second[100];
CopyString(first, second);
return 1;
}
char* ) указывает на начало str:
#include <ctype.h>
int count = 0;
while (*str != 0) {
// признак конца строки – ноль
if (isdigit(*str++))
count++;
// проверить байт, на который
// указывает str, и сдвинуть
// указатель на следующий байт
}
При выходе из цикла while переменная count содержит количество цифр в str, а сам str указывает на конец isdigit. Это одна из многих стандартных функций языка, предназначенных для работы с символами и
С помощью функций стандартной библиотеки языка реализованы многие часто используемые операции над символьными #include <string.h> и #include <ctype.h>.
char* strcpy(char* target,
const char* source);
Копировать source по target, включая завершающий нулевой байт. Функция предполагает, что памяти, выделенной по target, достаточно для копируемой
char* strcat(char* target,
const char* source);
Присоединить вторую target получается
int strcmp(const char* string1,
const char* string2);
Сравнить две
size_t strlen(const char* string);
Определить длину
В следующем примере, использующем приведенные функции, в result будет образована
char result[100]; char* date = "1 января 1998 года"; char* time = "12 часов"; strcpy(result, date); strcat(result, ", "); strcat(result, time);
Как видно из этого примера,
Определить
char* StrArray[5] =
{ "one", "two", "three", "four", "five" };
int days[12]; days[0] = 31; // январь days[1] = 28; // февраль days[2] = 31; // март days[3] = 30; // апрель days[4] = 31; // май days[5] = 30; // июнь days[6] = 31; // июль days[7] = 31; // август days[8] = 30; // сентябрь days[9] = 31; // октябрь days[10] = 30; // ноябрь days[11] = 31; // декабрь
В первой строчке мы объявили 12 элементов типа int и дали ему имя days. Остальные []. Как видно из примера, первый элемент 0, соответственно, последний – 11.
При объявлении
Предположим, мы хотим распечатать все элементы days. Для этого удобно воспользоваться циклом for.
for (int i = 0; i < 12; i++) {
cout << days[i];
}
Следует отметить, что при выполнении программы границы 12 в приведенном выше цикле написали 13, то компилятор не выдаст ошибку. При выполнении программа попытается напечатать 13 -е число. Что при этом случится, вообще говоря, не определено. Быть может, произойдет сбой программы. Более вероятно, что будет напечатано какое-то случайное 13 -е число. Выход индексов за границы [] и добавить контроль за индексами.
Отсутствие контроля индексов налагает на программиста большую ответственность. С другой стороны, индексация – настолько часто используемая операция, что наличие контроля, несомненно, повлияло бы на производительность программ.
Рассмотрим еще один пример. Предположим, что имеется 100 целых чисел, и его необходимо отсортировать, т.е. расположить в порядке возрастания. Сортировка методом "пузырька" – наиболее простая и распространенная – будет выглядеть следующим образом:
int array[100];
. . .
for (int i = 0; i < 99; i++ ) {
for (int j = i + 1; j < 100; j++) {
if (array[j] < array[i] ) {
int tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
}
В приведенных примерах у
int m[10][5];
представляет матрицу целых чисел размером 10 на 5. По-другому интерпретировать приведенное выше объявление можно как 10 элементов, каждый из которых – вектор целых чисел длиной 5. Общее количество целых чисел в m равно 50.
Обращение к элементам многомерных m[1][2] обращается к третьему элементу второй m.
Количество размерностей в
При объявлении
int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
При инициализации многомерных
double temp[2][3] = {
{ 3.2, 3.3, 3.4 },
{ 4.1, 3.9, 3.9 } };
Интересной особенностью инициализации многомерных
double temp[][3] = {
{ 3.2, 3.3, 3.4 },
{ 4.1, 3.9, 3.9 } };
// Вычислить размер пропущенной размерности
const int size_first = sizeof (temp) / sizeof
(double[3]);
struct Record {
int number;
char name[20];
};
Так же, как и для классов, операция " ." обозначает обращение к элементу
В отличие от классов, можно определить переменную-
struct {
double x;
double y;
} coord;
Обратиться к атрибутам переменной coord можно coord.x и coord.y.
В char ), который занимает 8 битов. До сих пор, несмотря на мегабайты и даже гигабайты оперативной памяти, используемые в современных компьютерах, существует немало задач, где каждый бит на счету.
struct TimeAndDate
{
unsigned hours :5; // часы от 0 до 24
unsigned mins :6; // минуты
unsigned secs :6; // секунды от 0 до 60
unsigned weekDay :3; // день недели
unsigned monthDay :6; // день месяца от 1 до 31
unsigned month :5; // месяц от 1 до 12
unsigned year :8; // год от 0 до 100
};
Одна TimeAndDate требует всего 39 битов, т.е. 5 байтов (один байт — 8 битов). Если бы мы использовали для каждого атрибута этой char, нам бы потребовалось 7 байтов.
Особым видом struct используется union:
union number {
short sx;
long lx;
double dx;
};
В отличие от
struct Value {
enum NumberType { ShortType, LongType,
DoubleType };
NumberType type;
short sx; // если type равен ShortType
long lx; // если type равен LongType
double dx; // если type равен DoubleType
};
Атрибут type содержит тип хранимого числа, а соответствующий атрибут
Value shortVal; shortVal.type = Value::ShortType; shortVal.sx = 15;
Хотя память выделяется под все три атрибута sx, lx и dx, реально используется только один из них. Сэкономить память можно, используя
struct Value {
enum NumberType { ShortType, LongType,
DoubleType };
NumberType type;
union number {
short sx; // если type равен ShortType
long lx; // если type равен LongType
double dx; // если type равен DoubleType
} val;
};
Теперь память выделена только для максимального из этих трех атрибутов (в данном случае dx ). Однако и обращаться с
(рис 8.1) Использование памяти в объединениях.Замечание.
int:
int x;
Можно определить переменную типа "
int* xptr;
и присвоить переменной xptr x:
xptr = x;
Операция , примененная к переменной, – это операция взятия *, примененная к
int y = x; // присвоить переменной y значение x int y = *xptr; // присвоить переменной y значение, // находящееся по адресу xptr
С помощью операции
*xptr = 10; // записать число 10 по адресу xptr
После выполнения этого оператора значение переменной x станет равным 10, поскольку xptr указывает на переменную x.
xptr –
unsigned long* lPtr; // указатель на целое число без знака char* cp; // указатель на байт Complex* p; // указатель на объект класса Complex
Если -> ", например p->real. Если вспомнить один из предыдущих примеров:
void
Complex::Add(Complex x)
{
this->real = this->real + x.real;
this->imaginary = this->imaginary +
x.imaginary;
}
то this – это Add. Запись this-> означает обращение к атрибуту текущего объекта.
Можно определить
int foo(long x); int bar(long x);
можно определить переменную типа
int (*functptr)(long x); functptr = foo; (*functptr)(2); functptr = bar; (*functptr)(4);
Для чего нужны
int* hardwareRegister =0x80000; *hardwareRegister =12;
Однако использование
struct TempResults {
double x1;
double x2;
} tempArea;
// Функция calc возвращает истину, если
// вычисления были успешны, и ложь – при
// наличии ошибки. Вычисленные результаты
// записываются на место аргументов по
// адресу, переданному в указателе trPtr
bool
calc(TempResults* trPtr)
{
// вычисления
if (noerrors) {
trPtr->x1 = res1;
trPtr->x2 = res2;
return true;
} else {
return false;
}
}
void
fun1(void)
{
. . .
TempResults tr;
tr.x1 = 3.4;
tr.x2 = 5.4;
if (calc(tr) == false) {
// обработка ошибки
}
. . .
}
В приведенном примере проиллюстрированы сразу две возможности использования TempResults используется для хранения данных. Вместо того чтобы передавать эти данные по отдельности, в функцию calc передается calc возвращает булево значение – признак успешного завершения вычислений. Сами же результаты вычислений записываются в
Упомянутые примеры использования
С
int x = 10;
int y = 10;
int* xptr = x;
int* yptr = y;
// сравниваем указатели
if (xptr == yptr) {
cout << "Указатели равны" << endl;
} else {
cout << "Указатели не равны" << endl;
}
// сравниваем значения, на которые указывают
// указатели
if (*xptr == *yptr) {
cout << "Значения равны" << endl;
} else {
cout << "Значения не равны" << endl;
}
Однако результат второй операции сравнения будет истинным, поскольку переменные x и y имеют одно и то же значение.
Кроме того, над xPtr – long, а cp – char. Начиная с 1000, в памяти расположены два целых числа. 1004 (в большинстве реализаций Си++ под тип long выделяется четыре байта). Начиная с 2000, в памяти расположены объекты типа char.
(рис 8.2) Адресная арифметика.Размер памяти, выделяемой для числа типа long и для char, различен. Поэтому xPtr и cp тоже изменяется по-разному. Однако и в том, и в другом случае увеличение ptr всегда изменяется на число, кратное sizeof(*ptr).
Между 100 целых чисел. Запишем двумя способами программу суммирования элементов этого
long array[100];
long sum = 0;
for (int i = 0; i < 100; i++)
sum += array[i];
То же самое можно сделать с помощью
long array[100];
long sum = 0;
for (long* ptr = array[0];
ptr < array[99] + 1; ptr++)
sum += *ptr;
Элементы
for (long* ptr = array;
ptr < array[99] + 1; ptr++)
sum += *ptr;
Хотя смешивать
При использовании многомерных exmpl:
long exmpl[5][6][7]
то выражение вида exmpl[1][1][2] – это целое число, exmpl[1][1] – вектор целых чисел ( *long ), exmpl[1] – двухмерная матрица или (*long)[7] ). Таким образом, задавая не все индексы
Особым случаем void используется для того, чтобы показать, что
void* ptr;
Для void не определена операция ->, не определена операция *, не определена
В программе на языке Си++ безтиповый
void
printbytes(void* ptr, int nbytes)
{
if (nbytes == 1) {
char* cptr = (char*)ptr;
cout << *cptr;
} else if (nbytes == 2) {
short* sptr = (short*)ptr;
cout << *sptr;
} else if (nbytes == 4) {
long* lptr = (long*)ptr;
cout << *lptr;
} else {
cout << "Неверное значение аргумента";
}
}
В примере используется операция явного преобразования типа. Имя типа, заключенное в круглые скобки, стоящее перед выражением, преобразует значение этого выражения к указанному типу. Разумеется, эта операция может применяться к любым
В программах на языке Си++ значение
long* foo(void);
. . .
long* resPtr;
if ((resPtr = foo()) != 0) {
// использовать результат
} else {
// ошибка
}
В языке Си++ определена символическая NULL для обозначения нулевого значения
Такое использование нулевого 0 данные программы располагаться не могут, он зарезервирован операционной системой для своих нужд. Однако во многом нулевой
Для того чтобы работать с текстом, в языке Си++ не существует особого встроенного типа данных. Текст представляется в виде последовательности знаков (байтов), заканчивающейся нулевым байтом. Иногда такое представление называют Си-строки, поскольку оно появилось в языке Си. Кроме того, в Си++ можно создать классы для более удобной работы с текстами (готовые классы для представления
char string[20]; string[0] = 'H'; string[1] = 'e'; string[2] = 'l'; string[3] = 'l'; string[4] = 'o'; string[5] = 0;
В string записана
Для записи строковых
"Это строка" "0123456789" "*"
Заметим, что символ, заключенный в двойные кавычки, отличается от символа, заключенного в апострофы.
С помощью
char alldigits[] = "0123456789";
Размер
При работе со char:
const char* message = "Сообщение программы";
Значение CopyString копирует первую
void
CopyString(char* src, char* dst)
{
while (*dst++ = *src++)
;
*dst = 0;
}
int
main()
{
char first[] = "Первая строка";
char second[100];
CopyString(first, second);
return 1;
}
char* ) указывает на начало str:
#include <ctype.h>
int count = 0;
while (*str != 0) {
// признак конца строки – ноль
if (isdigit(*str++))
count++;
// проверить байт, на который
// указывает str, и сдвинуть
// указатель на следующий байт
}
При выходе из цикла while переменная count содержит количество цифр в str, а сам str указывает на конец isdigit. Это одна из многих стандартных функций языка, предназначенных для работы с символами и
С помощью функций стандартной библиотеки языка реализованы многие часто используемые операции над символьными #include <string.h> и #include <ctype.h>.
char* strcpy(char* target,
const char* source);
Копировать source по target, включая завершающий нулевой байт. Функция предполагает, что памяти, выделенной по target, достаточно для копируемой
char* strcat(char* target,
const char* source);
Присоединить вторую target получается
int strcmp(const char* string1,
const char* string2);
Сравнить две
size_t strlen(const char* string);
Определить длину
В следующем примере, использующем приведенные функции, в result будет образована
char result[100]; char* date = "1 января 1998 года"; char* time = "12 часов"; strcpy(result, date); strcat(result, ", "); strcat(result, time);
Как видно из этого примера,
Определить
char* StrArray[5] =
{ "one", "two", "three", "four", "five" };
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.