- •Содержание
- •Лабораторная работа №1 Линейные и разветвляющиеся вычислительные процессы
- •Краткие теоретические сведения
- •Алфавит языка с
- •Классификация данных
- •Декларирование объектов
- •Структура программы
- •Функции вывода информации
- •Функции ввода информации
- •Стандартные математические функции
- •Операция присваивания
- •Операторы перехода
- •If (условие ) оператор1;
- •Оператор выбора switch
- •Пример линейного алгоритма
- •Пример использования оператора if
- •Варианты индивидуальных заданий
- •Контрольные вопросы
- •Циклы типа while и do–while
- •Вложенные циклы
- •Контрольные вопросы
- •Строки, как одномерные массивы символов
- •Примеры использования стандартных функций работы со строками
- •Варианты индивидуальных заданий
- •Контрольные вопросы
- •Лабораторная работа №4 Многомерные массивы, указатели, динамическое распределение памяти
- •Указатели и операции над адресами
- •Операции над указателями (адресная арифметика)
- •Указатели на указатели
- •Таким образом, указатели на указатели – это имена многомерных массивов.
- •Массивы указателей
- •Динамическое размещенея данных
- •Контрольные вопросы
- •Лабораторная работа №5 Функции пользователя
- •Краткие теоретические сведения
- •Область действия переменных
- •Пример работы с функциями Ввести массив NxN (не больше 50) целых чисел и в функции посчитать сумму его положительных значений.
- •Контрольные вопросы
- •Лабораторная работа № 6 Программирование алгоритмов с использованием структур
- •Краткие теоретические сведения
- •Пример на использование структур
- •Контрольные вопросы
- •Лабораторная работа №7 Файлы в языке с.
- •Контрольные вопросы
- •Лабораторная работа №8 Графический режим работы в языке с.
- •Функции для подготовки графической системы
- •Основные функции для получения изображения
- •Контрольные вопросы
- •Команды работы с блоками:
- •Задание опций интегрированной среды.
- •Набор текста программы.
- •Компиляция, редактирование связей, запуск программы на выполнение.
- •Многофайловая компиляция
- •Отладка программы.
- •Использование глобальных переменных, объявленных вне файла.
- •Литература
- •Лабораторный практикум
- •Редактор
- •Белорусский государственный университет
- •Отпечатано на ротапринте бгуир, 22000, Минск, п.Бровки, 6
Контрольные вопросы
Укажите типы массивов, применяемых в языке С.
Формы (способы) работы с элементами массива.
Как описываются строки в языке С?
Чем отличаются функции scanf() и gets(), printf() и puts()?
Лабораторная работа №4 Многомерные массивы, указатели, динамическое распределение памяти
Цель работы:
Изучить работу с многомерными массивами, освоить возможности динамического размещения данных.
Краткие теоретические сведения
Кроме одномерных массивов возможна работа с многомерными массивами. Объявление многомерного массива:
<тип><имя>[<размер 1 >][<размер 2 >]…[<размер N>]={{список начальных значений}, {список начальных значений},…};
Наиболее быстро изменяется последний индекс элементов массива, поскольку многомерные массивы размещаются в памяти компьютера в последовательности столбцов.
Например, элементы двухмерного массива b[2][1] размещаются в памяти в следующем порядке:
b[0][0], b[0][1], b[1][0], b[1][1], b[2][0], b[2][1].
Следующий пример иллюстрирует определение массива целого типа, состоящего из трех строк и четырех столбцов, с инициализацией начальных значений:
int a[3][4] = {{0,1,2,0},{9,-2,0,0},{-7,1,6,8}};
Если в какой-то группе {…} отсутствует значение, то соответствующему элементу присваивается 0. Предыдущий оператор будет эквивалентен следующему определению:
int a[3][4] = {{0,1,2},{9,-2},{-7,1,6,8}};
Пример программы
Создать двумерный массив целых чисел NxM (N и M не более 50), используя функцию rand и вывести на экран в форме матрицы, N,M ввести с клавиатуры:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define rnd (rand()/ 32768.0) // rand - генератор случайных чисел от 0 до
int, rnd – от 0 до 1
void main(void)
{ int i,j,n,m,a[50][50];
puts(“\n Input n, m:”); scanf(“%d %d”,&n,&m);
printf(“\n Array a \n”);
for(i=0; i<n; i++)
for(j=0; j<m; j++) {
a[i][j]=rnd*10-5; // диапазон от –5 до 5
printf(“%d%c“, a[i][j], (j= =m-1)?’\n’:’ ‘);
}
getch();
}
Указатели и операции над адресами
Обращение к объектам любого типа как операндам операций в языке C может проводиться:
- по имени, как мы до сих пор делали;
- по указателю (косвенная адресация).
Указатель – это переменная, которая может содержать адрес некоторого объекта в памяти компьютера, например адрес другой переменной. И через указатель, установленный на переменную можно обращаться к участку оперативной памяти, отведенной компилятором под ее значения.
Указатель объявляется следующим образом:
тип *идентификатор;
Например: int *a, *d;
float *f;
Здесь объявлены указатели a, d, которые можно инициализировать адресами целочисленных переменных и указатель f, который можно инициализировать адресами вещественных переменных.
С указателями связаны две унарные операции: & и *. Операция & означает «взять адрес» операнда (т.е. установить указатель на операнд). Данная операция допустима только над переменными. Операция * имеет смысл: «значение, расположенное по указанному адресу» и работает следующим образом:
- Определяется местоположение в оперативной памяти переменной типа указатель.
- Извлекается информация из этого участка памяти и трактуется как адрес переменной с типом, указанным в объявлении указателя.
- Производится обращение к участку памяти по выделенному адресу для проведения некоторых действий.
Пример 1:
int x, /* переменная типа int */
*y; /* указатель на элемент данных типа int */
y=&x; /* y - адрес переменной x */
*y=1; /* косвенная адресация указателем поля x
/* “по указанному адресу записать 1”, т.е. x=1; */
Пример 2:
int i, j=8, k=5, *y;
y=&i;
*y=2; /* i=2 */
y=&j; /* переустановили указатель на переменную j */
*y+=i; /* j+=i , т.е. j=j+1 -> j=j+2=10 */
y=&k; /*переустановили указатель на переменную k */
k+=*y; /* k+=k, k=k+k = 10 */
(*y)++; /* k++, k=k+1 = 10+1 = 11 */
Говорят, что использование указателя означает отказ от именования (разыменование) адресуемого им объекта.
Отказ от именования объектов при наличии возможности доступа по указателю приближает язык С по гибкости отображения «объект-память» к языку ассемблера.
При вычислении адресов объектов следует учитывать, что идентификатор массива и функции именует переместимую адресную константу (термин ассемблера), или константу типа указатель (термин языка C). Такую константу можно присвоить переменной типа указатель, но нельзя подвергать преобразованиям:
int x[100], *y;
y=x; // присваивание константы переменной
...
x=y; // Ошибка: в левой части - указатель-константа
Указателю-переменной можно присвоить значение другого указателя либо выражения типа указатель с использованием, при необходимости операции приведения типа (приведение необязательно, если один из указателей имеет тип "void *").
int i, *x;
char *y;
x=&i; /* x -> поле объекта int */
y=(char *)x; /* y -> поле объекта char */
y=(char *)&i; /* y -> поле объекта char */
Рассмотрим фрагмент программы:
int a=5, *p, *p1, *p2;
p=&a; p2=p1=p;
++p1; p2+=2;
printf(“a=%d, p=%d, p=%p, p1=%p, p2=%p.\n”,a,p,p,p1,p2);
Результат выполнения:
a=5, *p=5, p=FFC8, p1=FFCC, p2=FFD0.
Конкретные значения адресов зависят от ряда причин: архитектура компьютера, тип и размер оперативной памяти и т.д.