Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Язык Си

..pdf
Скачиваний:
6
Добавлен:
20.11.2023
Размер:
7.64 Mб
Скачать

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

#include <stdio.h> #include cconio.h> #include <stdlib.h>

#include <math.h>

int n; //число точек - глобальная переменная

struct Point {int x,y,z;

};

void f(Point *a)

{int i,i_min,i_max; float s=0,min,max, r;

//начальные значения i_min=0;

i_max=0;

r = sqrt(pow(a[0].x,2) + pow(a[0].y,2) + pow(a[0]. z,2));

min = r; max = r;

for(i=l;i<n;i++)

{r = sqrt(pow(a[i] .x,2) + pow(a[i].y,2) + pow(a[i].z,2));

s+=r; //сумма расстояний до начала координат

if(r<min) //минимальное расстояние {min=r;

i_min=i;

}

if(r>max) //максимальное расстояние {max=r;

i_max=i;

}

}

// печать результатов printf("Max point:%3d%3d%3d\n",

a [i_max].x,a [i_max].у,a [i_max].z);

printf("Min point:%3d%3d%3d\n", a[i_min].x,a[i_min].y,a[i_min].z);

printf("R_sr = %f",s/n);

}

main()

{Point *a; int i;

puts("Введите число точек:"); scanf("%d",&n);

//выделяем динамическую память под //структурный массив

а = (Point*)malloc(n*sizeof(Point));

//задаем координаты точек for(i=0;i<n;i++)

{printf("Координаты x у z для a[%d]: ",i); scanf("%d%d%d" ,&a[i].xf&a[i].y,&a[i] .z);

}

f(a); //вызываем функцию

free(а); //освобождаем динамическую память

getch(); return 0;

}

Задача 3. Создать структуру «дата рождения» со следую­ щими полями: день, месяц, год. Создать структуру «автомобиль» со следующими полями: марка, цвет. Использовать их для созда­ ния структуры «владелец автомобиля» со следующими полями: имя, дата роэ/сдения, автомобиль.

#include<stdio.h>

#include<conio.h>

#include<string.h>

//структура «дата рождения» struct Birthday

{int d,m, y;

};

//структура «автомобиль» struct Avtomobile

{char name[20],color[20] ; };

//структура

«автовладелец»

struct Avtovladelec

{char *name;

 

//имя

Birthday birth;

//дата рождения

Avtomobile

avto;

//автомобиль

};

 

 

int main() {Avtovladelec X;

//задаем имя автовладельца X.name = "Ivanov A.S.";

X.birth.d

=

5;

//день рождения

X.birth.m

=

6;

//месяц рождения

X.birth.у =

1970;

//год рождения

//задаем название автомобиля strcpy(X.avto.name,"BMW-X5");

//цвет автомобиля strcpy(X.avto.color,"white metallic");

//печать информации об автовладельце printf ("%s\n",X.name) ;

printf ("%d.%d. %d\n" ,X.birth. d,X.birth.m, X.birth.y);

printf("%s - %s\n",X .avto.name,X.avto.color)

getch();

return 0;

Результат на экране:

Ivanov A.S.

5.6.1970

BMW-X5 - white metallic

ДОМАШНЕЕ ЗАДАНИЕ

1.Переделать рассмотренные задачи так, чтобы к полям структур обращение выполнялось через оператор «стрелка».

2.Создать структуру «город» со следующими полями: назва­ ние, численность населения, реки. Создать переменную структур­ ного типа и передать ее в функцию, в которой происходит запол­ нение полей структуры значениями с клавиатуры. По. возвращении

вфункцию main заполненные значения полей структуры выводят­ ся на консоль.

3.Переделать предыдущую задачу под динамический массив.

ЛЕКЦИЯ 12. РАБОТА С ФАЙЛАМИ

Когда программа начинает выполняться, автоматически открываются пять потоков, из которых основными являются сле­ дующие:

-стандартный поток ввода (на него ссылаются, используя предопределенный указатель на поток stdin);

-стандартный поток вывода (stdout)\

-стандартный поток вывода сообщений об ошибках (stderr). По умолчанию потоку stdin ставится в соответствие клавиату­

ра, а потокам stdout и stderr соответствует экран дисплея.

Кроме того, открываются потоки stdprn и stdaux, ассоцииро­ ванные соответственно с принтером и последовательным портом компьютера. Эти потоки открываются и закрываются автоматически.

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

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

 

 

Т а б л и ц а 12.1

 

Основные функции работы с файлами

Функция

Назначение

п/п

fopen

Открывает файл

1

2/close Закрывает файл

3getc Читает символ из файла

4fgetc Читает символ из файла

5piltc Записывает символ в файл

6fputc Записывает символ в файл

Функция

Назначение

п/п

 

 

7feof Проверяет, достигнут ли конец файла

8lgets Читает строку из файла

9Jputs Записывает строку в файл

10fread Читает блок данных из файла

Иfwrite Пишет блок данных в файле

12Jprintf Форматная запись в файл

13fscanf Форматное чтение из файла

14

fseek

Устанавливает указатель текущей позиции файла

в заданное положение

 

 

15rewind Устанавливает указатель позиции на начало файла

16remove Удаляет файл

Рассмотрим применение данных функций подробнее. Связующим звеном между файлом и потоком в системе вво­

да-вывода является указатель на файл. Указатель файла определя­ ет имя файла на диске и его использование в потоке, ассоцииро­ ванном с ним. Указатель файла - это указатель на структуру ти­ па FILE, которая определена в файле stdio.h. Указатель файла должен быть объявлен в программе следующим образом:

FILE *имя указателя;

Например, FILE *f l ;

указатель файла приобретает значение в результате выпол-

нения фуныи™ открытия файла

FILE J o p en ico n s, char -path, co m , char •mode)

,Лайла; mode - режим открытия. Параметры

Л3ле1 д а ^ б ы т ь Фяр»ковьЮИ константами:

p a th и m ode могут

fl ^ fopen(

'

 

или символьными массдааш^

=„г „ .

Т - f open(f name, f e d . , ,

Т а б л и ц а 12 . 2

 

Режимы открытия файла

Назначение

Режим

п/п

 

1г Открытие существующего текстового файла для чтения Создание текстового файла для записи (если файл с

2W заданным именем существовал, то предыдущее содер­ жимое стирается, файл создается заново)

3

а

Открытие (или создание) текстового файла для записи

информации в конец файла

 

 

 

 

Открытие существующего текстового файла для чтения

 

г+

и записи в любом месте файла (если указатель внутри

4

файла установлен на имеющийся текст, то текст затира­

 

 

ется новым; если указатель установлен в конец файла,

 

 

то новый текст дописывается в конец имеющегося)

 

W+

Создание текстового файла для записи и чтения (если

5

файл с заданным именем существовал, то предыдущее

 

 

(содержимое стирается, файл создается заново)

 

 

<

6

я+

Открытие (или создание) текстового файла для записи

]в конец файла или чтения из любого места файла

 

 

Кроме текстового режима обмена файл можно открыть в двоичном (бинарном) режиме, который обозначается буквой Ь.

f l = f o p e n ( " t . t x t " , " r b " ) ; f l = f o p e n (" t . t x t " , " w b " ); f l = f o p e n (" t . t x t " , " a b " ); f l = f o p e n ( " t . t x t " , " r + b " ) ; f l = f o p e n (" t . t x t " , "w+b"); f l = f o p e n (" t . t x t " , " a + b " );

При открытии потока могут возникнуть следующие ошибки:

-указанный файл, связанный с потоком, не найден (для ре­

жима «чтение»);

-диск заполнен или защищен от записи;

-отсутствует необходимая динамическая память (должна вы­ деляться при выполнении функцииfopen).

Вперечисленных случаях указатель файла приобретает зна­ чение NULL. Указатель в любом режиме, отличном от аварийного, никогда не бывает равным NULL, поэтому для подстраховки мож­ но использовать следующую последовательность операторов при открытии файла:

FILE *fp;

if ((fp=fopen(,,t.txt", "г") )==NULL)

{puts("Ошибка при открытии файла");

getch();

exit(1);

}

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

Также для аварийного завершения существует функция abort с прототипом void abort(int val); (функция немедленно прекращает выполнение программы без закрытия файлов и освобождения бу­ феров). В поток stderr она направляет сообщение "abnormal pro­ gram termination" (аварийное завершение программы).

Для использования функций exit и abort необходимо подклю­ чить файл stdlib.h.

После того как файл открыт, с ним можно работать, записы­ вая в него информацию или считывая ее (в зависимости от режи­ ма). Открытые на диске файлы после окончания работы с ними

рекомендуется закрыть явно. Для этого используется библиотеч­ ная функция

int/close (FILE *fp)

Функция /close возвращает 0, если операция закрытия была успешной, и EOF в случае ошибки.

EOF (от англ. End о/ File - конец файла) - символическая константа для обозначения того, что достигнут конец файла:

FILE *fp;

fp=fopen("my_file.txtM,"r");

if(fclose(fp)==EOF)

puts("Error!");

В данном примере, если файл туJile.txt открыт не будет, то и закрывать будет нечего, следовательно, будет напечатано сообще­ ние Error!.

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

О т кры т ы й ф айл м ож н о п овт орно от кры т ь т олько по­ сле т ого, как он будет закры т ф ункцией /clo se .

Считывание символа из потока, открытого для чтения функ­ циейf open, производится функциями

int getc(FILE */р) intfgetc(FILE *Jp)

Функции возвращают символ, прочитанный из файла. Если достигнут конец файла или произошла ошибка при чтении файла, возвращается EOF.

Пример. Вывод информации из текстового файла на консоль.

При выполнении примера выполните следующие действия: