Материал: LR_7_Massivy_i_fayly

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

У тверждаю

Ректор университета

_______________ О.Н. Федонин

« ___ » _____________2017 г.

Алгоритмические языки массивы и файлы

Методические указания

к выполнению лабораторной работы

Брянск 2017

У ДК 004.432.2

Алгоритмические языки. Массивы и файлы [Электронный ресурс]: методические указания к выполнению лабораторной работы. – Брянск: БГТУ, 2017. –13с.

Разработали:

А.П. Горлов, канд.техн.наук., доц.

М.Л. Гулак, канд.техн.наук., доц.

Рекомендовано кафедрой «Системы информационной безопасности» БГТУ (протокол № 11 от 28.08.2017).

Научный редактор М.Ю. Рытов

Компьютерный набор А.П. Горлов

Методические указания публикуются в авторской редакции

Подписано в печать 28.08.17 г. Формат 60х84 1/16.

Усл. печ.л. 0,75 Уч.-изд.л. 0,75

Брянский государственный технический университет

Кафедра «Системы информационной безопасности», 58-83-54

241035, Брянск, бульвар 50 лет Октября, 7.

1. Цель работы

Цель работы – получение навыков работы с массивами при решении задач, а также реализация ввода и вывода данных при помощи файлов.

Продолжительность работы: 4 ч.

2. Теоретическая часть

При решении задач с большим количеством данных одинакового типа использование переменных с различными именами, не упорядоченных по адресам памяти, затрудняет программирование. В подобных случаях в языке Си используют объекты, называемые массивами.

Массив - это непрерывный участок памяти, содержащий последовательность объектов одинакового типа, обозначаемый одним именем.

Элемент массива (значение элемента массива) – значение, хранящееся в определенной ячейке памяти, расположенной в пределах массива, а также адрес этой ячейки памяти.

Каждый элемент массива характеризуется тремя величинами:

  • адресом элемента - адресом начальной ячейки памяти, в которой расположен этот элемент;

  • индексом элемента (порядковым номером элемента в массиве);

  • значением элемента.

Адрес массива – адрес начального элемента массива.

Имя массива – идентификатор, используемый для обращения к элементам массива.

Размер массива – количество элементов массива

Размер элемента – количество байт, занимаемых одним элементом массива.

    1. Объявление и инициализация массивов

Для объявления массива в языке Си используется следующий синтаксис:

тип имя[размерность]={инициализация};

Инициализация представляет собой набор начальных значений элементов массива, разделенных запятыми.

int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9};  // массив a из 10 целых чисел

int a[10] = {0}; // массив a из 10 элементов, инициализированных 0

Если массив проинициализирован при объявлении, то константные начальные значения его элементов указываются через запятую в фигурных скобках. В этом случае количество элементов в квадратных скобках может быть опущено.

int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

При обращении к элементам массива индекс требуемого элемента указывается в квадратных скобках[].

Однако часто требуется задавать значения элементов массива в процессе выполнения программы. При этом используется объявление массива без инициализации. В таком случае указание количества элементов в квадратных скобках обязательно.

int a[10];

Для задания начальных значений элементов массива очень часто используется параметрический цикл:

  // Ввод элементов массива

  for(i=0; i<5; i++)  {

     printf("a[%d] = ", i);

     scanf("%d", &a[i]); // &a[i] - адрес i-го элемента массива

    }

  // Вывод элементов массива

  for(i=0;i<5;i++)  {

      printf("%d ",a[i]); // пробел в формате печати обязателен

    1. Передача массива в функцию

Обработку массивов удобно организовывать с помощью специальных функций. Для обработки массива в качестве аргументов функции необходимо передать

  • адрес массива,

  • размер массива.

Исключение составляют функции обработки строк, в которые достаточно передать только адрес.

При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение внутри вызывающей функции.

Если в функцию передается адрес переменной (или адрес массива), то все операции, выполняемые в функции с данными, находящимися в пределах видимости указанного адреса, производятся над оригиналом данных, поэтому исходный массив (или значение переменной) может быть изменено вызываемой функцией.

Пример . Функция вывода элементов массива.

void f(int *x, int n) {

// x - указатель на массив (адрес массива)

// n - размер массива

for(int i=0; i<n; i++)

printf(“%d”,x[i]);

}

    1. Заполнение массива случайными числами

Заполнить массив случайными числами в Си довольно просто. В этом случае нам потребуются функции rand(); и srand (m); из библиотеки stdlib.h.

Пусть мы имеем одномерный массив из десяти целочисленных элементов, тогда заполнение такого массива случайными числами будет выглядеть вот так:

for ( int i = 0; i < 10; i ++)

Arr [i] = rand ()%100;

Этот цикл заполняет массив Arr случайными числами от 0 до 100. При этом число 100 не включается в диапазон.

Использование функции srand (time (NULL)); позволяет получить при каждом запуске программы различные числа, поскольку устанавливает для функции rand(); в качестве начального значения текущее время. В противном случае мы получим одинаковые значения элементов массива при каждом запуске программы.

Для использования функций в заголовок требуется подключить следующие библиотеки:

#include <stdlib.h>

#include <ctime>

Пример:

// функция генерации случайного числа из диапазона от range_min до range_max включительно

int rrand(int range_min, int range_max) {

return rand() % (range_max - range_min + 1) + range_min;

}

    1. Работа с файлами

В стандартной библиотеке языка Си предусмотрены функции для работы с файлами. Для работы с ними необходимо подключить заголовочный файл <stdio.h>.

Работа с файлами складывается из трех шагов:

• открыть файл;

• работать с файлом;

• закрыть файл.

Рассмотрим эти шаги подробнее.

1. Файл открывается. Это означает, что программа "захватывает" заданный по имени файл, сообщает операционной системе, что далее она будет с ним работать. Данный шаг нужен, чтобы не возникало конфликтов, когда несколько программ одновременно хотят записывать информацию в один и тот же файл. Правда, считывать данные из файла, очевидно, допустимо одновременно множеством программ, поэтому в операции открытия файла обычно уточняется, что файл открывается "на чтение" (считывание информации, которая не меняется) либо "на запись" (данные в файле модифицируются).

Функция открытия файла имеет следующий прототип (здесь и далее пропущены некоторые платформенные особенности прототипов):

FILE * fopen (const char *filename, const char *opentype)

Эта функция передаёт запрос на открытие файла операционной системе. Операционная система при открытии файла для некоторой программы сообщает ей (программе) идентификатор (как правило, целое число), которое идентифицирует в программе в дальнейшем нужный открытый файл. Этот идентификатор запоминается в переменной; обычно такая переменная называется файловой переменной. Файловая переменная в стандартной библиотеке языка Си представляет собой структуру типа FILE и помимо идентификатора файла хранит также дополнительные данные о текущем состоянии работы с файлом. Её часто называют дескриптором файла. Функция fopen возвращает указатель на динамически созданную структуру типа FILE.

Параметров у функции fopen() два. Первый – это путь к файлу (строка), второй - параметры открытия файла. Используются следующие способы открытия файла:

режим

описание

начинает с …

r

rb

открывает для чтения

начала

w

wb

открывает для записи (создаёт файл в случае его отсутствия). Удаляет содержимое и перезаписывает файл.

начала

a

ab

открывает для добавления (создаёт файл в случае его отсутствия)

конца

r+

rb+

r+b

открывает для чтения и записи

начала

w+

wb+

w+b

открывает для чтения и записи. Удаляет содержимое и перезаписывает файл.

начала

a+

ab+

a+b

открывает для чтения и записи (добавляет в случае существования файла)

конца

2. Ведется работа с файлом. Из него данные либо считываются, либо в него записываются. Приёмы работы с файлом зависят от типа контента файла и будут рассмотрены далее.

3. Файл закрывается. После этой операции он снова доступен другим программам для обработки.

Функция закрытия файла имеет следующий прототип:

int fclose (FILE *stream);

При вызове функции fclose нужно передать указатель на дескриптор ранее открытого файла. Вызов функции fclose приводит к закрытию потока данных, на который указывает аргумент stream, сбросу остаточного содержимого буфера данных в файл (если в буфере оставались данные), освобождению памяти выделенной под буфера чтения и записи (если буфера создавались) и закрытию файла связанного с потоком данных. В случае успешной работы функция возвращает 0. Если во время работы функции возникла ошибка, то она возвращает EOF (-1), при этом в дескриптор файла будет присвоен код ошибки, которую затем можно определить, используя функцию ferror.

Вот список некоторых дополнительных полезных функций для работы с файлами:

int feof (FILE *stream); //проверка достижения конца файла

int fseek(FILE *stream, long offset, int origin); //позиционирование

int ferror(FILE *stream); // возвращает текущий код ошибки

void clearerr (FILE* stream); // сбрасывает признак ошибки в 0

// записывает в pposition текущую позицию курсора в файле

int fgetpos(FILE* stream, fpos_t* pposition);

// устанавливает курсор в файле в позицию из pposition

int fsetpos (FILE*stream, const fpos_t* pposition);

Для работы с текстовыми файлами предназначены функции, аналогичные функциям для работы со стандартным устройством ввода/вывода, и отличаются от них наличием дополнительного аргумента: указателя на дескриптор файла. Вот список основных функций для работы с текстовыми файлами:

int fprintf (FILE *stream, const char *template, ...);

int fscanf (FILE *stream, const char *template, ...);

int fgetc (FILE*);

char*fgets (char*, int, FILE*);

int fputc (int, FILE*);

int fputs (const char*, FILE*);

Источник: https://studfile.net/preview/16485830/