Основные элементы языка программирования Си алфавит, идентификаторы, ключевые слова, константы
Скачать 0.78 Mb.
|
Оператор выхода из цикла или переключателя break Оператор имеет простой формат: break; Может использоваться только внутри цикла или переключателя, управление передается оператору, который следует за циклом или переключателем. Пример с переключателем был представлен. Что касается циклов, то с помощью данного оператора условие завершения цикла (противоположное условию продолжения) может проверяться не только в начале или в конце тела цикла, но и где-нибудь в середине. Пример: while (1) // Бесконечный цикл { ..... if (x<0) break; // Условие проверяется в середине цикла .... } Оператор перехода к следующей итерации цикла continue Оператор имеет следующий простой формат: continue; Может использоваться только внутри цикла. При выполнении оператора завершается выполнение оператора тела цикла и в зависимости от типа цикла или выполняется проверка условия – для циклов с предусловием и постусловием, или выполняются модификации для цикла for. Пример: for(int i=0; i<10; i++) { if (i==5) continue; // Пропускаем итерацию, далее i увеличивается на 1 // и начинает выполняться следующая итерация ...... } 11.Указатели: определение, инициализация, динамическое выделение памяти. Все переменные и другие объекты хранятся в оперативной памяти. Оперативную память можно представить в виде некоторой последовательности байтов, куда можно записывать данные и код. Когда работает программа, то ей доступна не вся оперативная память, а выделяется некоторый сегмент или область в оперативной памяти. Байты внутри сегмента пронумерованы. Если для некоторой переменной, например типа int, выделяется 4 байта, то можно к этой переменной обращаться, зная номер первого байта внутри сегмента, с которого размещается эта переменная. Этот номер байта внутри сегмента интерпретируется как адрес объекта или переменной, для хранения адресов существуют специальные переменные – указатели. Указатель – это переменная, которая хранит адрес участка памяти, выделенного для объектов определенных типов. Указатель не является самостоятельным типом, он всегда связан с каким-либо другим конкретным типом, на который он указывает. (Существует правда указатель на тип void, который не связан с конкретным типом). Формат определения указателя соответствует формату определения переменных стандартных типов (указатель тоже переменная, размещенная в оперативной памяти), но перед именем переменной указателя ставится знак «*». Примеры: int x=5; // Обычная переменная типа int int *pX=&x, // Переменная указатель с инициализацией – хранит адрес переменной x *p1, // Указатель на тип int определенный без инициализации *p2; // Указатель на тип int определенный без инициализации float * pF; // Указатель на тип float определенный без инициализации При работе с указателями используются две основные унарные операции: «&» - операция получения адреса объекта, применяется к объекту (переменной), результат операции – значение адреса объекта; «*» - операция обращения по адресу (разыменования указателя), применяется к указателю, результат – значение объекта (переменной), на который указывает указатель, без особых ограничений типа модификатора const результат является леводопустимым выражением, т.е. может использоваться слева от операции присваивания. Примеры: int x=5; // Обычная переменная типа int int *p; // Переменная указатель на тип int p=&x; // Указатель теперь содержит адрес переменной x printf(“x=%d”, *p); // Будет напечатано значение переменной x *p=100; // Значение переменной x будет изменено printf(“x=%d”, x); // Будет напечатано x=100 При объявлении указателя ему может быть присвоено начальное значение (инициализация указателя). В качестве инициализатора может быть: – явно заданный адрес участка памяти (требуется явное преобразование к типу указателя); – указатель, уже имеющий значение; – выражение, позволяющее получить адрес объекта с помощью операции &; – выражение для динамического выделения памяти с помощью специальных функций – malloc, calloc, realloc (в Си++ появился специальный оператор для выделения памяти – new). int x=5; // Обычная переменная типа int int *p1=&x; // Инициализация указателя с помощью операции & int *p2=p1; // Инициализация указателя с помощью другого указателя char * p3=(char *)0xB800; // Присвоение указателю явного значения int *p4=NULL; // Указатель, имеющий 0 значение 3 int *p5=malloc(100*sizeof(int)); // Выделение памяти для массива из 100 элементов 12.Одномерные массивы. Символьные массивы и строки. Одномерные массивы Формат определения одномерного массива: Примеры: int A[100]; // Объявление массива из 100 элементов типа int char C1[20], C2[150]; // Объявляются 2 массива элементов типа char из // 20 и 150 элементов Описание массива может не содержать число элементов. extern float y[]; // Описание ....... float y[20]; // Определение Обращение к элементам массива осуществляется с помощью специальной операции [] – обращение по индексу. int m[10]; m[0]=1; // Элементу массива с индексом 0 присваивается значение 1 m[1]=2; // Элементу массива с индексом 1 присваивается значение 2 ... ; m[9]=10; // Элементу массива с индексом 9 присваивается значение 10 Индексация всегда начитается с 0, последний элемент имеет индекс n-1. Элемент массива может участвовать в любом выражении, где допустимо использование переменной соответствующего типа. m[5]=m[3]+m[4]*100; Инициализация массива Массив может иметь инициализацию, если массив имеет инициализацию, то размерность можно не указывать, она определяется по умолчанию. int a1[4]={ 2, 5, 9, 10 }; // Массив из 4-х элементов int a2[7]={ 3, 4, 5 }; // Массив из 7 элементов, проинициализированы первые 3 char c1[]={ ‘A’, ‘g’, ‘1’, ‘y’, ‘I’ }; // Массив из 5 элементов, // размерность определяется по умолчанию Если массив объявлен за пределами блоков, то по умолчанию его элементы инициализируются 0. Строка – это символьный массив, заканчивающийся символом с кодом 0 (символ NULL) – это служебный символ, являющийся признаком конца строки. Практически все стандартные функции, работающие со строками, используют это свойство для определения конца строки. Примеры: char str[]=“ABCD”; // Это строка, выделяется память под 5 символов (последний 0) char c[]={‘A’, ‘B’, ‘C’, ‘D’ }; // Это просто массив из 4-х символов char *s=“Пример строки”; // Допустимо такое определение строки Зная признак конца строки можно, например, вычислить длину строки. int len=0; // Длина строки for(; s[len]; len++) ; 13.Массивы и указатели. Динамические массивы Массивы и указатели Имя массива, используемое внутри выражения без [], является указателем на первый элемент массива (элемент с индексом 0). Данный указатель является константным, т.е. его значение нельзя изменять. Для некоторого массива, например int A[10]; выполняется равенство A==&A[0] Доступ к элементу массива возможен или через индексное выражение или через операцию обращения по адресу. for (int i=0; i<10; i++) A[i]=2*i; for (int i=0; i<10; i++) *(A+i)=2*i; // Наличие скобок обязательно, // так как приоритет операции * выше, // чем операции + Кроме того имя массива без скобок является указателем, тип которого соответствует указателю на тип элемента массива. Допустим следующий порядок работы с массивом: int a[10]; int *p; p=a; for(int i=0; i<10; i++) p[i]=i*i; или for(int i=0; i<10; i++) *(p+i)=i*i; Динамические массивы Память для массива может выделяться и уничтожаться динамически с помощью специальных функций, например, для выделения памяти могут использоваться функции: malloc, calloc, realloc, а для освобождения памяти функция free (в Си++ существуют специальные операторы new и delete). Особенно это удобно в том случае, когда число элементов заранее не известно, а становится известным только во время выполнения программы, например, число элементов может вычисляться при работе программы, вводиться с клавиатуры и т.д. Функция malloc имеет заголовок, определенный в заголовочном файле stdlib.h: void * malloc(unsigned int _Size); Данная форма заголовка является упрощенной, функция имеет один параметр, определяющий размер выделяемой динамически области памяти в байтах, функция возвращает указатель на выделяемую область памяти, тип указателя void *, что обеспечивает его неявное приведение к указателям на любые стандартные типы. Возвращает выделенную память обратно операционной системе функция с упрощенным заголовком (заголовочный файл stdlib.h): void free(void * _Memory); Функция имеет один параметр – указатель на блок освобождаемой памяти. 14.Многомерные массивы. Многомерные динамические массивы Многомерный массив – это массив массивов. Пример определения: int A[2][3]; Данное определение можно раскрыть следующим образом: А – массив из двух элементов, элементами массива являются массивы из трех элементов типа int. Элементы следуют в памяти в следующем порядке: A[0][0], A[0][1], A[0][2], A[1][0], A[1][1], A[1][2] Обращаться к элементам массива можно с помощью индексного выражения или с помощью указателей A[0][1]=5; A[i][j]=i+j; // или *(*(A+i)+j)=i+j; Инициализация многомерных массивов Инициализация многомерных массивов может проводиться по аналогии с одномерными массивами. Например: int A[2][3][2]={ 1, 2, 3, 4, 5}; Инициализируются первые 5 элементов по их расположению в оперативной памяти, т.е. элементы с индексами: 000, 001, 010, 011, 020 Но удобнее использовать вложенные фигурные скобки, при этом самая левая размерность может не указываться, а определяться по умолчанию: int B[][5]={{ 1, 2, 3} , { 6, 7} , { 1, 2, 3, 4, 5 }}; В примере создается массив размерности 3 × 5 (аналог матрицы 3 × 5, при этом в первой строке инициализируются 3 элемента, во второй – 2 элемента, в третьей – все 5 элементов). Динамические многомерные массивы По аналогии с одномерными массивами многомерные массивы могут создаваться динамически. Рассмотрим пример создания двухмерного массива n × m (матрица n × m), при этом значения n и m заранее неизвестны – вводятся с клавиатуры. В примере создается матрица n × m, заполняется случайными числами, выводится на печать, в конце программы память освобождается. #include #include void main() { int **p; // Указатель на указатель может быть использован для выделения памяти под // 2-х мерный массив динамически int n, m; // Заранее неизвестные размерности массива int i, j; // Индексные переменные 8 printf_s("n="); scanf_s("%d", &n); // Ввод с клавиатуры числа строк матрицы printf_s("m="); scanf_s("%d", &m); // Ввод с клавиатуры числа столбцов матрицы p = malloc(n * sizeof(int *)); // Выделяем память под массив указателей только в Си // p=(int **)malloc(n*sizeof(int *)); В Си++ требуется преобразование типа // Выделяем память для каждого указателя в массиве указателей for (i = 0; i < n; i++) p[i] = malloc(m * sizeof(int)); // Только в Си // for(i=0; i for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { p[i][j] = rand() % 100; // Получаем псевдослучайное целое число printf_s("%d ", p[i][j]); } printf_s("\n"); // После печать строки матрицы переход на новую строчку } // Освобождаем память, порядок освобождения обратен порядку выделения for (i = 0; i < n; i++) free(p[i]); // Освобождаем память для строк матрицы free(p);// освобождаем память для массива указателей system("pause"); } 15.Шаблон класса std::array (Массив). Основные методы, пример использования. Шаблон класса std::array (Массив) Задает обычной массив, при создании при вызове конструктора шаблона, требуется задать размерность массива. Действия реализуются с помощью функций шаблона класса или обычных функций: Некоторые методы шаблона класса: at Предоставляет доступ к указанному элементу с проверкой индекса operator[] Предоставляет доступ к указанному элементу front Предоставляет доступ к первому элементу back Предоставляет доступ к последнему элементу data Предоставляет прямой доступ к внутреннему содержимому (С++ 2011) empty Проверяет отсутствие элементов в контейнере size Возвращает количество элементов в контейнере max_size Возвращает максимально допустимое количество элементов в контейнере fill заполнить контейнер указанным значением swap Обменивает содержимое operator== operator!= operator< operator<= operator> operator>= Лексикографически сравнивает значения в array Пример: #include #include using namespace std; int main() { array // При печати последние 5 элементов равны 0 for (auto ar_i: arr1) cout << ar_i << endl; } Пример: #include #include using namespace std; int main() { array cout << "size=" << arr1.size(); // Напечатано 5 cout << endl << "max_size=" << arr1.max_size() << endl; // Напечатано 5 int i = 1; // Вводим элементы массива с клавиатуры for (auto &it: arr1) // Надо использовать ссылку auto &, если хотим изменить элемент { cout << "Item " << i << "="; cin >> it; i++; } // Печатаем все элементы for (auto it: arr1) cout << endl << it; array arr2.swap(arr1); // Меняем местами 2 массива // Другой способ обращения к элементам в цикле for (int i = 0; i < arr1.size(); i++) cout << endl << arr1[i]; for (int i = 0; i < arr2.size(); i++) cout << endl << arr2.at(i); // Можно так for (int i = 0; i < arr2.size(); i++) arr2.at(i) = i + 1; // Можно так изменить элемент for (auto it: arr2) cout << endl << it; } 16.Шаблон класса std::vector (Вектор). Основные методы, пример использования. Шаблон класса std::vector (Вектор) Вектор управляет элементами, хранящимися в динамическом массиве. Он обеспечивает произвольный доступ к элементам, т.е. к каждому элементу можно обратиться напрямую по соответствующему индексу. Добавление и удаление элементов происходит в конце массива и выполняется, как правило, быстро. Вставка элемента в середину или в начало массива занимает достаточно много времени, т.к. требуется перемещать остальные элементы. Некоторые методы класса: capacity - Возвращает число элементов, которое вектор может содержать без выделения дополнительного пространства. insert - Вставляет элемент или некоторое число элементов в вектор с заданной позиции. pop_back - Удаляет элемент в конце вектора. push_back - Добавляет элемент в конец вектора. at - Предоставляет доступ к указанному элементу с проверкой индекса operator[] Предоставляет доступ к указанному элементу front Предоставляет доступ к первому элементу back Предоставляет доступ к последнему элементу size Возвращает количество элементов в контейнере Пример 1: #include #include using namespace std; int main() { vector cout << "capacity=" << vec1.capacity() << endl; for (int i = 1; i <= 10; ++i) { vec1.push_back(i); } cout << "capacity=" << vec1.capacity() << endl; // Печать всех элементов вектора for (int i = 0; i < vec1.size(); ++i) { cout << vec1[i] << ' '; } cout << endl; vector vector vector // Печать всех элементов вектора for (int i = 0; i < vec2.size(); ++i) { cout << vec2[i] << ' '; } cout << endl; vector // Печать всех элементов вектора for (int i = 0; i < vec3.size(); ++i) { cout << vec3.at(i) << ' '; } cout << endl; if (vec2 == vec3) cout << "vec2 == vec3"; else cout << "vec2 != vec3"; cout << endl; vec3[0] = 33.44444; if (vec2 == vec3) cout << "vec2 == vec3"; else cout << "vec2 != vec3"; cout << endl << endl; // Печать всех элементов вектора for (int i = 0; i < vec2.size(); ++i) { cout << vec2[i] << ' '; } cout << endl; // Печать всех элементов вектора //for (int i = 0; i { vi = 111.111; } for (auto vi: vec3) { cout << vi << ' '; } cout << endl; if (vec2 >= vec3) cout << "vec2 >= vec3"; else cout << "vec2 < vec3"; vector cout << endl << "size(vec3)=" << vec3.size() << " size(vec4)=" << vec4.size(); cout << endl << endl; } |