
- •Технология программирования Конспект лекций
- •1.1. Краткая характеристика языка Си1
- •1.2. Алфавит
- •1.3. Объявление переменных. Типы данных
- •1.4. Простые типы данных
- •1.5. Структурированные типы данных
- •1.6. Константы
- •1.7. Операции Присваивание
- •Арифметические
- •1.9. Функции
- •1.10. Директивы препроцессора
- •1.11. Метки
- •1.12. Указатели Обзор
- •Приведение типов
- •Типизированные и нетипизированные указатели
- •Операции над указателями
- •Массивы
- •Многомерные массивы
- •Указатели в качестве параметров функций
- •Функции работы с указателями и памятью
- •1.13. Строки.
- •1.14. Время жизни и область видимости переменных
- •1.15. Указатель на функцию
- •1.16. Работа с файлами.
- •1.17. Форматированный ввод-вывод
- •1.18. Введение в объектно-ориентированное программирование
- •Часть 2. Введение в технологию программирования.
- •2.1 Понятие технологии программирования
- •2.2. Этапы развития программирования
- •2.3. Проблемы разработки сложных программных систем
- •2.4. Жизненный цикл программного продукта
- •Модели жц.
- •Экстремальное программирование
- •2.5. Оценка качества процессов создания программного обеспечения
- •2.6. Проектирование надёжного программного средства
- •2.7. Процессы проектирования
- •2.8. Требования, цели
- •2.9. Внешнее проектирование
- •Диаграммы потоков данных (Data Flow Diagrams).
- •Диаграммы переходов состояний (State Transition Diagrams). Функциональные диаграммы.
- •Описание структур данных
- •2.10. Проектирование архитектуры
- •2.11. Проектирование модульной структуры. Модуль
- •Внешнее проектирование модулей
- •Модульная декомпозиция
- •2.12. Кодирование.
- •2.13. Тестирование
- •2.14. Документирование
- •2.15. Проектирование пользовательского интерфейса
- •Реализация многомерных массивов
- •Очередь и стек
- •Ассоциативные массивы
- •3.3. Упорядоченные структуры данных.
- •Сортировка методом пузырька
- •Быстрая сортировка
- •3.4. Деревья
- •Бинарное дерево
- •Обход дерева
- •3.5. Множества, графы Множества
- •3.6. Строки Константные строки
- •Списковое представление строк
- •Представление массива строк
- •3.7. Библиотека stl
- •3.8. Реализация некоторых структур данных Реализация двусвязанного списка.
- •Реализация массива переменного размера:
- •Примеры программ
- •Список литературы
Многомерные массивы
Возможны по крайней мере три варианта реализации многомерных массивов.
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();
}