- •Технология программирования Конспект лекций
- •Краткая характеристика1
- •Алфавит
- •Объявление переменных. Типы данных
- •Простые типы данных
- •Структурированные типы данных
- •Константы
- •Операции Присваивание.
- •Арифметические:
- •Логические (результат – логическое значение).
- •Функции
- •Директивы препроцессора
- •Указатели Обзор
- •Приведение типов
- •Типизированные и нетипизированные указатели
- •Операции над указателями
- •Массивы
- •Многомерные массивы
- •Указатели в качестве параметров функций
- •Функции работы с указателями и памятью
- •Строки.
- •Время жизни и область видимости переменных
- •Указатель на функции
- •Работа с файлами.
- •Форматированный ввод-вывод
- •Введение в объектно-ориентированное программирование
- •Часть 2. Введение в технологию программирования.
- •Этапы развития программирования.
- •Проблемы разработки сложных программных систем:
- •Жизненный цикл программного продукта.
- •Модели жц.
- •Экстремальное программирование
- •Оценка качества процессов создания программного обеспечения.
- •Процессы проектирования.
- •Требования, цели
- •Внешнее проектирование.
- •Проектирование модульной структуры. Модуль
- •Внешнее проектирование модулей
- •Модульная декомпозиция
- •Почему модуль должен компилироваться с первого раза?
- •Рекомендации по внесению ясности в текст программы:
- •Тестирование.
- •Документирование.
- •Пользовательский интерфейс
- •Организация двусвязанного списка.
- •Организация массива переменного размера:
- •3.2 Алгоритмы Быстрая сортировка
- •Поиск пути
- •Примеры программ
- •Список литературы
Многомерные массивы
Возможны по крайней мере три варианта реализации многомерных массивов.
1. Использование специальных типов данных. В этом случае размер по каждому измерению указывается в отдельных квадратных скобках. Обращение к элементам происходит аналогично одномерному массиву.
Пример:
int x[4][4][3];
x[0][0][0] = 5;
Массивы могут инициализироваться значениями в фигурных скобках, при этом допустимо не указывать последнюю (самую левую) размерность. Если заданная размерность меньше инициализирующих аргументов, часть элементов останется неопределенна. Обратная ситуация вызовет ошибку.
Примеры:
int x[3][2]={{1,2},{3,4},{5,6}}; //заданы и размеры массива, и инициализирующие значения
long y[] = {1,2,3,4}; // размер массива определяется фактическому по количеству // значений (4)
char t[][4] = {{1,2,3,4},{5,6}}; // последняя размерность определяется по числу значений (2) и // элементы t[1][2] и t[1][3] не определены
При таком указании данные располагаются в памяти последовательно, порядок расположения соответствует порядку указания при инициализации.
2. Использование многомерных указателей. В этом случае каждую размерность указателя требуется явно инициализировать. Таким способом можно получить, например, двумерный массив с различной длиной строк.
Пример:
int **x;
x = new int*[3];
for(int i=0;i<3;i++) x[i] = new int[i];
x[0][0] = 0; x[1][0] = 1; x[1][1] = 2; x[2][0] = 3; x[2][1]=4; x[2][2] = 5;
Получаем массив вида
0
12
345
В этом случае в памяти отдельно хранится массив указателей на строки и отдельно сами строки.
3. Хранение многомерного массива в одномерном.
Например, переход от двух индексов (i,j) можно осуществить по формуле i*m+j, где m – максимальная размерность по j (количество столбцов).
Указатели в качестве параметров функций
В списке формальных параметров функций указатели могут указываться как с использованием символа *, так и с использованием квадратных скобок. Данные определения равнозначны.
void f(char *x, double []y) {…}
Для передачи многомерных массивов удобно использовать определение типа (служебное слово typedef).
Пример.
typedef int myarray[5][5];
void f(myarray t)
{
…
}
void main()
{
myarray x;
…
f(x);
}
Для передачи в функцию константного указателя используется служебное слово const. Данные, на которые указывают такие указатели не могут быть переопределены, а также нельзя освободить память, занимаемую ими.
void f2(const char *t)
{
t[0] = ‘x’; /недопустимо
free(t); //недопустимо, но можно выполнить free((char *)t)
}
Функции работы с указателями и памятью
(заголовочные файлы alloc.h, stdlib.h, mem.h; в Visual Studio – memory.h, stdlib.h)
void* malloc(unsigned s) – выделение памяти s байт.
void* calloc(unsigned n, unsigned m) – выделение n элементов по m байт.
void* realloc(void* ptr, unsigned ns) – перевыделение памяти.
void free(void* ptr) – освобождение памяти.
int memcmp(void* s1, void* s2, unsigned n) – сравнивает две области памяти.
void* memcpy(const void* dest, const void* src, unsigned n) – копирование области памяти n байт из src в dest.
void* memset(void *ptr, int c, unsigned n) – запись числа c в память начиная с ptr.
Пример организации простейшего массива указателей на произвольные объекты.
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <stdlib.h>
struct voidarray
{
void **data;
int size, topsize, step;
};
int init(voidarray*array, int initsize)
{
array->topsize = array->step = initsize;
array->size=0;
array->data=(void**)malloc(initsize*sizeof(void*));
return array->data!=NULL;
}
int add(voidarray*array, void* element)
{
array->size++;
if (array->size>array->topsize)
{
void **data2=(void**)malloc((array->topsize+array->step)*sizeof(void*));
if (data2==NULL) return -1;
memcpy(data2,array->data,array->topsize*sizeof(void*));
array->topsize+=array->step;
free(array->data);
array->data=data2;
}
array->data[array->size-1] = element;
return 0;
}
void dispose(voidarray*array)
{
free(array->data);
array->size = array->topsize = 0;
}
void* getat(voidarray*array,int n) {return n<array->size?array->data[n]:0;}
int main()
{
voidarray array;
init(&array,10);
for(int i=0;i<100;i++)
{add(&array,new int(i));}
for(int i=0;i<100;i++)
printf("%d",*(int*)getat(&array,i));
dispose(&array);
_getch();
}