Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Объявление указателя на структуру

Поиск

Структуры

Структура - это совокупность переменных, объединенных одним именем, предоставляющая общепринятый способ совместного хранения информации.

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

Переменные, образующие структуру, называются членами структуры. (Члены структуры также часто называются элементами или полями.)

Обычно все члены структуры связаны друг с другом.

 

Стандартный вид объявления структуры следующий:

struct ярлык {
тип имя переменной;
тип имя переменной;
тип имя переменной;
} структурные переменные;

ярлык - это имя типа структуры, а не имя переменной.

Структурные переменные - это разделенный запятыми список имен переменных.

Следует помнить, что или ярлык, или структурные переменные могут отсутствовать, но не оба.

 

Шаблон структуры, определяющий имя и адрес.

Ключевое слово struct сообщает компилятору об объявлении структуры.

struct addr {
char name[30];
char street [40];

char city[20];
char state[3];
unsigned long int zip;
};

Объявление завершается точкой с запятой; объявление структуры - это оператор.

 

Имя структуры addr идентифицирует структуру данных и является спецификатором типа.

Имя структуры часто используют как ярлык.

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

struct addr addr_info;

В данной строке происходит объявление переменной addr_info типа addr.

До тех пор, пока не будет объявлена переменная данного типа, она не будет существовать.

 

Когда объявлена структурная переменная, компилятор автоматически выделяет необходимый участок памяти для размещения всех ее членов.

 

При объявлении структуры можно одновременно объявить одну или несколько переменных.

Например:

struct addr {
char name[30];
char street[40];
char city[20];
char state[3];
unsigned long int zip;
} addr_info; binfo, cinfo;

объявляет структуру addr и объявляет переменные addr_info, binfo, cinfo данного типа.

 

Если необходима только одна структурная переменная, то нет необходимости в ярлыке структуры. Это означает, что

struct {
char name[30];
char street[40];
char city[20];
char state[3];
unsigned long int zip;
} addr_info;

объявляет одну переменную addr_info с типом, определенным предшествующей ей структурой.

Доступ к членам структуры

Доступ к отдельным членам структуры осуществляется с помощью оператора. (обычно называется «точкой»)

addr_info.zip = 12345;

printf("%ld", addr_info.zip);

Данная строка выводит на экран содержимое поля zip структурной переменной addr_nfo. Таким же образом массив символов addr_info.name может использоваться в gets():

gets (addr_infо.name);

Данная команда передает указатель на символ, указывающий на начало name.

Для доступа к отдельным элементам addr_info.name можно использовать индекс name. Например, можно вывести содержимое addr_info.name посимвольно с помощью следующего кода:

register int t;
for(t=0; addr_info.name [t]; ++t) putchar (addr_info.name [t]);

Присваивание структур

Информация, содержащаяся в одной структуре, может быть присвоена другой структуре того же типа с помощью одиночного оператора присваивания,

#include <stdio.h>
int main(void)
{
struct {
int a;
int b;
} x, y;
x.a = 10;
x.b = 20;
у = x; /* присвоение одной структуры другой */
printf ("Contents of у: %d %d.", y.a, y.b);
return 0;
}


Массивы структур

Возможно, наиболее часто структуры используются в виде массивов структур.

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

Например, для объявления 100-элементного массива структур типа addr следует написать:

struct addr addr_info[100];

В результате получаем набор из 100 переменных, устроенных, как объявлено в типе структуры addr.

Для доступа к отдельным структурам массива adar_info следует проиндексировать имя массива.

printf("%ld", addr_info[2].zip);

Как и массивы переменных, массивы структур индексируются с нуля.

 

Объявление указателя на структуру

Указатели на структуру объявляются путем помещения * перед именем структурной переменной. Например, предполагая, что ранее была определена структура addr, следующая строка объявляет addr_pointer как указатель на данные этого типа:

struct addr *addr_pointer;

Использование указателей на структуру

Для получения адреса структурной переменной следует поместить оператор & перед именем структуры. Пусть имеется следующий фрагмент

struct bal {
float balance;
char name[80];
} person;

struct bal *p; /* объявление указателя на структуру */

тогда

p = &регson;

помещает адрес структуры person в указатель р.

Для доступа к членам структуры с помощью указателя на структуру следует использовать оператор "стрелка".

Оператор "стрелка", ->, образован из знака "минус" и символа "больше". Например, для доступа к члену balance с помощью p следует написать:

p->balance

 

 

Потоки и файлы

 

Поток - логическое устройство

 

Существует два типа потоков: текстовые и двоичные.

 

Текстовые потоки

 

Текстовые потоки - это последовательность символов.

 

В текстовых потоках некоторые символы могут преобразовываться.

Например, символ новой строки может преобразовываться в пару «возврат каретки - перевод строки».

 

 

Двоичные потоки

 

Двоичный поток - это последовательность байт, имеющих однозначное соответствие с байтами во внешнем устройстве (нет преобразования символов)

 

Файлы

файлы - это логическая концепция

 

Поток связывается с конкретным файлом с помощью операции открытия.

Если файл открыт, может осуществляться обмен между файлом и программой

 

Связь потока с файлом уничтожается с помощью операции закрытия.

 

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

1. Подключить файл заголовков, используя следующую директиву препроцессора #include <stdio.h>.

2. Объявить указатель на структуру FILE для каждого файла.

3. Открыть файл, используя функцию fopen().

4. Использовать функции чтения-записи стандартного ввода-вывода.

5. Закрыть файл, используя функцию fclose().

 

 

В начале работы программы открыты пять предопределенных текстовых потоков: stdin, stdout, stderr, stdaux и stdprn.

Поток Устройство
stdin stdout stderr stdaux stdprn Клавиатура Экран Экран Первый последовательный порт Принтер

 

Первые три определены стандартом ANSI С

 

Каждый поток, ассоциированный с файлом, имеет структуру управления файлом типа FILE.

 

Данная структура определена в заголовочном файле stdio.h.

 

Поименованные константы из файла stdio.h. Значения указанных констант зависят от реализации.

 

Константа Смысл константы
EOF признак конца файла
NULL  
BUFSIZ размер буфера ввода-вывода
FILE структура, определенная с помощью typedef, содержащая информацию об открытом файле
stdin указатель на FILE, открытый для стандартного ввода
stdout указатель на FILE, открытый для стандартного вывода
stderr указатель на FILE, открытый для стандартного вывода сообщений об ошибках

Пример 1

/*Образец определения типа FILE*/typedef struct{ int _cnt; /*количество оставшихся в буфере символов*/ unsigned char *_ptr; /*следующая позиция в буфере*/ unsigned char *_base; /*размещение буфера*/ unsigned char _flag; /*признак ошибки чтения-записи или конца файла*/ unsigned char _file; /*дескриптор файла ситемы UNIX*/} FILE;

 

Для уменьшения количества обращений к устройствам (например, к диску) стандартный ввод-вывод выполняется с буферизацией.

Буфер ввода-вывода — это временная область в основной памяти, которая содержит считываемые или записываемые данные.

Данные пересылаются на устройства (с устройств) большими порциями, размер которых определяется поименованной константой BUFSIZ.

Функция fopen() — функция открытия файла.

FILE *fopen(const char *имя_файла, const char *тип)

 

Первым аргументом функции fopen() является адрес строки, содержащей путевое имя файла.

const char *имя_файла

 

Второй аргумент — это адрес строки, определяющей тип работы с открываемым файлом.

 

Тип может принимать следующие значения:

  • "r" — текстовый файл открывается для чтения (read);
  • "w"- текстовый файл создается для записи; старое содержимое, если оно было, выбрасывается (write);
  • "a" — текстовый файл открывается или создается для записи в конец файла (add);
  • "r+" — текстовый файл открывается для исправления, т.е. для чтения и записи;
  • "w+"- текстовый файл создается для исправления, старое содержимое, если оно было, выбрасывается;
  • "a+" — текстовый файл открывается или создается для исправления уже существующей информации и добавления новой в в конец файла.

 

 

Объявление прототипа функции fopen() находится в файле заголовков stdio.h,

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

 

fopen("с:\\temp0\\20.04\\1.txt","w");

 

Пример 1

#include <stdio.h>int main(){ FILE *fp; fp = fopen("logfile", "w"); if (fp == NULL) printf("Open failed\n");...}

Функция fclose()

Функция fclose() используется для закрытия потока, ранее открытого с помощью fopen().

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

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

Функция fclose() имеет прототип:

int fclose(FILE *fp);

где fp - это указатель на файл, возвращенный fopen().

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

 

Объявление прототипа функции fclose() находится в файле заголовков stdio.h

#include <stdio.h>int main(){ FILE *fp; fp = fopen("logfile", "w"); if (fp == NULL) printf("Open failed\n"); fclose(fp);...}

Функции чтения-записи

int fprintf(FILE *stream, const char *format,... /*аргументы*/)

 

Функция преобразует и пишет вывод в поток под управлением формата.

 

Возвращаемое значение — число записанных символов или, в случае ошибки, отрицательное значение.

 

Правила построения форматной строки такие же, как для функции printf().

 

#include <conio.h>

#include <stdio.h>

int main()

{

int bal;

char name[15];

FILE *file;

 

if ((file = fopen("с:\\temp0\\20.04\\1.txt","w")) == NULL)

printf("Файл невозможно открыть или создать\n");

else{

for(;;){

scanf ("%d%s", &bal, name);

if (bal == 0)

break;

fprintf(file,"%d %s\n", bal, name);

}

}

fclose(file);

return 0;

}

 

Функция

int fscanf(FILE *stream, const char *format,... /*аргументы*/)

 

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

#include <conio.h>

#include <stdio.h>

 

int main()

{

int bal;

char name[15];

FILE *file;

 

if ((file = fopen("1.txt","r")) == NULL)

printf("Файл невозможно открыть или создать\n");

else{

for(;;){

if (feof(file))

break;

fscanf(file,"%d %s", &bal, name);

printf ("%d %s\n", bal, name);

}

}

fclose(file);

getch();

return 0;

}

 

Функции fread() и fwrite()

Файловая система ANSI С предоставляет две функции, позволяющие читать и писать блоки данных - fread() и fwrite(). Они имеют следующие прототипы:

size_t fread(void *буфер, size_t число_байту size_t объем, FILE *fp);

size_t fwrite(const void *буфер, size_t число_байт, size_t объем, FILE *fp);

В случае fread() буфер - это указатель на область памяти, которая получает данные из файла.

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

Аргумент объем определяет, сколько элементов (каждый длиной число_байт) будет прочитано или записано. Наконец, fp - это файловый указатель на ранее открытый поток.

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

Функция fwrite() возвращает число записанных элементов. Данное значение равно объем, если не возникла ошибка.

 

 

#include <conio.h>

#include <stdio.h>

 

int main()

{

int bal;

FILE *file;

 

if ((file = fopen("3.txt","w")) == NULL)

printf("Файл невозможно открыть или создать\n");

else{

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

scanf("%d", &bal);

fwrite (&bal, sizeof(int),1, file);

}

}

fclose(file);

getch();

return 0;

}

 

 

#include <conio.h>

#include <stdio.h>

 

int main()

{

int bal;

FILE *file = fopen("3.txt","r");

 

if (file == NULL)

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

else {

while (!feof(file)){

fread(&bal, sizeof(int),1, file);

printf ("%d ", bal);

}

}

 

fclose(file);

getch();

return 0;

}

 

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

/* запись вещественных чисел в файл */
#include <stdio.h>
int main(void)
{
FILE *fp;
float f = 12.23;
if((fp=fopen("test", "wb"))==NULL) {
printf("Cannot open file.");
return 1;
}
fwrite(&f, sizeof (float), 1, fp);
fclose (fp);
return 0;
}

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

Одно из наиболее полезных применений fread() и fwrite() - это чтение и запись блоков данных типа массивов или структур. Например, следующий фрагмент записывает содержимое массива вещественных чисел balance в файл balance, используя один оператор fwrite(). Далее она читает массив, используя один оператор fread(), и выводит его содержимое.

#include <stdio.h>
int main(void)
{
register int i;
FILE *fp;
float balance[100];

/* открытие на запись */
if((fp=fopen("balance", "wb"))==NULL) {
printf("Cannot open file.");
return 1;
}
for(i=0; i<100; i++) balance[i] = (float) i;

/* сохранение за раз всего массива balance */
fwrite(balance, sizeof balance, 1, fp);
fclose(fp);

/* обнуление массива */
for(i=0; i<100; i++) balance[i] = 0.0;

/* открытие для чтения */
if((fp=fopen("balance","rb"))==NULL) {
printf("cannot open file");
return 1;
}

/* чтение за раз всего массива balance */
fread(balance, sizeof balance, 1, fp);

/* вывод содержимого массива */
for(i=0; i<100; i++) printf("%f ", balance [i]);
fclose(fp);
return 0;
}

Использование fread() и fwrite() для чтения или записи сложных данных более эффективно, чем использование повторяющихся вызовов getc() и putc().

 

Запись символа

Система ввода/вывода ANSI С определяет две эквивалентные функции, выводящие символ - putc() и fputc(). (На самом деле putc() реализована в виде макроопределения.) Поддержка двух идентичных функций необходима для сохранения совместимости со старыми версиями С.

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

int putc(int ch, FILE *fp);

где fp — это указатель на файл, возвращенный fopen(), a ch - выводимый символ. Указатель на файл указывает putc(), в какой файл следует писать. По историческим причинам ch определена как int, но используется только младший бит.

Если putc() выполнена успешно, она возвращает выведенный символ. В противном случае возвращает EOF.

Чтение символа

Имеется две эквивалентные функции, предназначенные для ввода символа - getc() и fgetc(). Поддержка двух идентичных функций необходима для сохранения совместимости со старыми версиями С.

Функция getc() используется для чтения символов из потока, открытого на чтение с помощью fopen(). Прототип getc() следующий:

int getc(FILE *fp);

где fp - это указатель на файл типа FILE *, возвращенный fopen(). По традиции getc() возвращает целое, но старший байт установлен в 0.

Функция getc() возвращает EOF при достижении конца файла. Для чтения текстового файла до конца следует использовать следующий код:

ch = getc(fp);
while(ch!=EOF) {
ch = getc(fp);
}

 

Создать текстовый файл "new1.txt" записав в него строку из 50 символов. Все символы, отличные от пробела, переписать в новый файл "new2.txt":

 

#include <stdio.h>

#include <conio.h>

#include <string.h>

Main()

{ char ch, sl[50];

char text[]="one to tree four";

FILE *pf, *pr; // Указатели на файлы

pf=fopen("new1.txt","w"); // Создание нового файла new1.txt

Clrscr(); //Экран

fprintf(pf,"%s\n",text); // Запись в файл строки text

Использование feof()

Как утверждалось ранее, файловая система С может оперировать двоичными данными. Когда файл открыт для двоичного ввода, может быть прочитано целочисленное значение, равное EOF. В результате getc() будет отображать состояние наличия конца файла, хотя физический конец еще не достигнут. Для разрешения данной проблемы в С имеется функция feof(), используемая для определения конца файла при чтении двоичных данных. Она имеет следующий прототип:

int feof(FILE *fp);

где fp идентифицирует файл. Функция feof() возвращает не 0, если достигнут конец файла, в противном случае она возвращает 0. Следовательно, следующий код читает двоичный файл, пока не встретится метка конца файла:

while(!feof(fp)) ch = getc(fp);

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

Чтение и запись символов

 

Функции ввода

Getchar()

Getche()

Getch()

читают символ с клавиатуры

 

 

Функция вывода

Putchar()

печатает символ на экран в текущей позиции курсора

Прототипы функций getche() и putchar():

int getche(void);

int putchar(int cb);

 

Функция getche() возвращает нажатый символ.

getche() возвращает только младший байт (символ, введенный с клавиатуры).

 

Функция getche() требует заголовочный файл conio.h.

 

Функция putchar() возвращает cb в случае успеха или EOF - в случае ошибки.

 

 

cb - целое, на экран выводится только младший байт.

 

(EOF - это макроопределение, находящееся в stdio.h, означающее конец файла.)

 

 

/* переключатель регистра */ 10
#include <conio.h> // getche
#include <stdio.h> //
#include <ctype.h> // tolower


int main(void)

{
char ch;
do

{
ch = getche();
if(islower(ch)) putchar(toupper(ch));
else putchar (tolower(ch));
} while (ch!='.'); /* использование точки для остановки */
return 0;
}

 

 

Альтернативы getche() - getchar() и getch()

 

getchar() буферизирует ввод, пока не встретится возврат каретки.

 

getch() не выводит символ на экран.

 

 

Указатель на файл

 

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

 

 

FILE *fp;

 

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

 

Прототип


FILE *fopen(const char *имя_файла, const char *режим);

 

Структуры

Структура - это совокупность переменных, объединенных одним именем, предоставляющая общепринятый способ совместного хранения информации.

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

Переменные, образующие структуру, называются членами структуры. (Члены структуры также часто называются элементами или полями.)

Обычно все члены структуры связаны друг с другом.

 

Стандартный вид объявления структуры следующий:

struct ярлык {
тип имя переменной;
тип имя переменной;
тип имя переменной;
} структурные переменные;

ярлык - это имя типа структуры, а не имя переменной.

Структурные переменные - это разделенный запятыми список имен переменных.

Следует помнить, что или ярлык, или структурные переменные могут отсутствовать, но не оба.

 

Шаблон структуры, определяющий имя и адрес.

Ключевое слово struct сообщает компилятору об объявлении структуры.

struct addr {
char name[30];
char street [40];

char city[20];
char state[3];
unsigned long int zip;
};

Объявление завершается точкой с запятой; объявление структуры - это оператор.

 

Имя структуры addr идентифицирует структуру данных и является спецификатором типа.

Имя структуры часто используют как ярлык.

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

struct addr addr_info;

В данной строке происходит объявление переменной addr_info типа addr.

До тех пор, пока не будет объявлена переменная данного типа, она не будет существовать.

 

Когда объявлена структурная переменная, компилятор автоматически выделяет необходимый участок памяти для размещения всех ее членов.

 

При объявлении структуры можно одновременно объявить одну или несколько переменных.

Например:

struct addr {
char name[30];
char street[40];
char city[20];
char state[3];
unsigned long int zip;
} addr_info; binfo, cinfo;

объявляет структуру addr и объявляет переменные addr_info, binfo, cinfo данного типа.

 

Если необходима только одна структурная переменная, то нет необходимости в ярлыке структуры. Это означает, что

struct {
char name[30];
char street[40];
char city[20];
char state[3];
unsigned long int zip;
} addr_info;

объявляет одну переменную addr_info с типом, определенным предшествующей ей структурой.

Доступ к членам структуры

Доступ к отдельным членам структуры осуществляется с помощью оператора. (обычно называется «точкой»)

addr_info.zip = 12345;

printf("%ld", addr_info.zip);

Данная строка выводит на экран содержимое поля zip структурной переменной addr_nfo. Таким же образом массив символов addr_info.name может использоваться в gets():

gets (addr_infо.name);

Данная команда передает указатель на символ, указывающий на начало name.

Для доступа к отдельным элементам addr_info.name можно использовать индекс name. Например, можно вывести содержимое addr_info.name посимвольно с помощью следующего кода:

register int t;
for(t=0; addr_info.name [t]; ++t) putchar (addr_info.name [t]);

Присваивание структур

Информация, содержащаяся в одной структуре, может быть присвоена другой структуре того же типа с помощью одиночного оператора присваивания,

#include <stdio.h>
int main(void)
{
struct {
int a;
int b;
} x, y;
x.a = 10;
x.b = 20;
у = x; /* присвоение одной структуры другой */
printf ("Contents of у: %d %d.", y.a, y.b);
return 0;
}


Массивы структур

Возможно, наиболее часто структуры используются в виде массивов структур.

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

Например, для объявления 100-элементного массива структур типа addr следует написать:

struct addr addr_info[100];

В результате получаем набор из 100 переменных, устроенных, как объявлено в типе структуры addr.

Для доступа к отдельным структурам массива adar_info следует проиндексировать имя массива.

printf("%ld", addr_info[2].zip);

Как и массивы переменных, массивы структур индексируются с нуля.

 

Объявление указателя на структуру

Указатели на структуру объявляются путем помещения * перед именем структурной переменной. Например, предполагая, что ранее была определена структура addr, следующая строка объявляет addr_pointer как указатель на данные этого типа:

struct addr *addr_pointer;



Поделиться:


Последнее изменение этой страницы: 2016-07-16; просмотров: 264; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.227.190.231 (0.014 с.)