Структуры как параметры функций 


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



ЗНАЕТЕ ЛИ ВЫ?

Структуры как параметры функций



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

 

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

 

// vozv_ank_2011.cpp

#include "stdafx.h"

#include <string.h>

#include<conio.h>

#include<stdio.h>

#include <iostream>

using namespace std;

 

// Массив анкет, Функции и структуры, возврат структур

 

#define LIM 30 // число служащих

struct anketa // anketa - имя нового типа!

{ char fio[30];

int tabn;

float tarif;

int work;

float sum;

};

 

// Варианты функции summa (1-5)

 

// 1) параметры - элементы структуры

//double summa1(double x, int y)

//{

// return x*y;

//}

 

// 2) арг - указатель на структуру

//double summa2(const struct anketa *uk)

//{

// return (uk->tarif*uk->work);

//}

 

// 3) арг - сама структура

//double summa3(anketa nachisleno)

//{

// return (nachisleno.tarif*nachisleno.work);

//}

 

// 3a) арг - ссылка на структуру.

//Чаще всего параметры-структуры передаются в функции по

//ссылке (при объявлении за именем типа структуры ставят знак &).

//В этом случае фактически в функцию передается адрес структуры

//и функция работает с тем же экземпляром, что и вызывающая

//программа.

void summa3a(anketa &nachisleno)

{

nachisleno.sum = (nachisleno.tarif*nachisleno.work);

}

 

 

// 4)возврат результата через указатель

// двусторонняя передача информации

// прототип: void summa(struct anketa *)

//void summa4(struct anketa *uk)

//{

// uk->sum=(uk->tarif*uk->work);

//}

 

// 5) возврат функцией результата через возврат структуры

// здесь функция создает собственную копию структуры vedom[]

//struct anketa summa5(struct anketa rab)

//{

// rab.sum=(rab.tarif*rab.work);

// return rab;

//}

 

 

int main()

{

anketa vedom[LIM]; //массив структур типа anketa

int k=0,i; system ("chcp 1251");

cout<<"Введи до "<<LIM<<" фамилий"<<'\n';

cout<<"Для прекращения - Enter в начале строки"<<'\n';

cout<<"Фамилия "<<k+1<<" -го служащего";

while((gets(vedom[k].fio)!=NULL)&&

(vedom[k].fio[0])!='\0' &&k<LIM)

{

cout<<"табельн номер - "<<vedom[k].fio; cin>>vedom[k].tabn;

cout<<"часовой тариф - "<<vedom[k].fio; cin>>vedom[k].tarif;

cout<<"отраб часов - "<<vedom[k].fio; cin>>vedom[k].work;

// непосредсвенное вычисление поля sum без функции

// vedom[k].sum = vedom[k].tarif*vedom[k].work;

 

// 1) передача функции элементов структуры

// vedom[k].sum = summa1(vedom[k].tarif,vedom[k].work);

 

// 2) передача функции указателя на структуру

// vedom[k].sum = summa2(&vedom[k]);

 

// 3) передача функции всей структуры в качестве аргумента

// vedom[k].sum = summa3(vedom[k]);

 

// 3а) передача функции ссылки на структуру как аргумент

summa3a(vedom[k]);

 

// 4) возврат функцией результата через указатель

// summa4(&vedom[k]);

 

// 5) возврат функцией результата через возврат структуры

// vedom[k]=summa5(vedom[k]);

 

//ВНИМАНИЕ!!!

fflush(stdin); //очистить входной поток!

// Иначе 2-ю фамилию уже не введем, gets() определяет NULL

 

k++;

if(k<LIM)

cout<<"Фамилия "<<k+1<<" -го служащего ";

}

cout<<"\n\n\n\tВедомость на выплату зарплаты\n\n";

for(i=0;i<k;i++)

printf("\n%-20s \t %10.2f\t %6d %10.2f\t ", vedom[i].fio,vedom[i].tarif,vedom[i].work, vedom[i].sum);

getch();return 0;

 

}

 

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

 

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

 

struct anketa //anketa - имя нового типа!

{

char fio[30];

int tabn;

float tarif;

int work;

float sum;

};

void strsort(anketa str[],int n); //прототип

 

// функция вычисления зарплаты

//void summa (anketa *uk)//указатель на структуру

//{

// uk->sum = uk->tarif*uk->work;

//}

 

double summa(anketa rab) // параметр - сама структура

{

return rab.tarif*rab.work;

}

 

int main()

{

//массив структур типа anketa

anketa vedom[]={ { "Иванов И. И.", 1234},

{ "Петров П. П.", 2345},

{ "Бендер О. И.", 3456},

{ "Ивановский П. А.", 4567},

{ "Петров А. П.", 6789 },

{ "", 0} //признак конца списка

};

 

system("chcp 1251"); //переключаем в кодировку win1251

int k=0,i; //setlocale(NULL, ".1251");-без ввода строки

//LIM - реальное (!) число записей

int LIM = sizeof(vedom)/sizeof(anketa);

for(i=0; i< LIM-1; i++)

printf("\n%-20s %8d \n",

vedom[i].fio,vedom[i].tabn);

//getch();

cout<<"Введи до "<<LIM-1<<" записей"<<'\n';

while((vedom[k].fio[0])!='\0'&& k<LIM)

{

cout<<"часовой тариф - "<<vedom[k].fio<<" ";cin>>vedom[k].tarif;

if(!vedom[k].tarif) break;

cout<<"отраб часов - "<<vedom[k].fio<<" ";cin>>vedom[k].work;

//vedom[k].sum = vedom[k].tarif*vedom[k].work; //без функции

 

//summa(&vedom[k]); //к функции с указателем на структуру

vedom[k].sum=summa(vedom[k]);//к функции аргумент - сама структура

k++;

}

//getch();

 

// обратиться к сортировке

strsort(vedom,k);

 

cout<<"\n\n\n\t\tВедомость на выплату зарплаты\n\n";

for(i=0; i<k; i++)

printf("\n%20s %10.2f %8d %10.2f",

vedom[i].fio,vedom[i].tarif,vedom[i].work, vedom[i].sum);

 

//*************** ПОИСК ПО ФИО с 2010г.***********

char name[30]; int found=0; k=0;

cout<<"\n\n\nВВЕДИ Фамилию "; cin >> name;

while(vedom[k].fio[0]!='\0' && k<LIM)

{

if(strstr(vedom[k].fio, name))

if(vedom[k].fio[strlen(name)]==' ')//fio завершается пробелом?

// если этот оператор не вставить, то по введенной name Макогон будут

// обработаны и Макогоненко и Макогонский и...

{ printf("\n%-20s %8d %10.2f", vedom[k].fio,

vedom[k].tabn, vedom[k].sum);

found++;

}

k++;

}

if(found>0)

cout<<"\nНАЙДЕНО "<<found << " фамилии "<<name<<'\n';

else

cout << name<< "-Фамилия отсутствует в справочнике\n";

 

getch();return 0;

}

 

// для массива структур - сортировка

void strsort(anketa str[],int n)

{

anketa rab; int i,j;

for(i=0;i<n-1;i++)

for(j=i+1;j<n;j++)

if(strcmp(str[i].fio,str[j].fio)>0)

{ rab=str[i];

str[i]=str[j];

str[j]=rab;

}

}

 

 


ФАЙЛЫ. ПОТОКОВЫЙ ВВОД-ВЫВОД

Файл–физический объект, который содержит данные. Работа с файлами в С++ реализуется либо средствами методов ООП, либо с помощью функций, унаследованных от стандартной библиотеки С для работы с потоками. Каждый способ имеет свои преимущества. В программах, не использующих механизм классов и объектов, удобнее использовать потоковый ввод-вывод в стиле языка С.

В С/С++ все файлы рассматриваются как неструктурированный поток (последовательность) байтов (т.е. никакой логической структуры не предполагается). Физически поток представляет файл или устройство (клавиатура, дисплей, принтер), снабженный средствами буферизации.

 

Буферизация.

Потоковый ввод-вывод позволяет обрабатывать данные различных размеров и форматов, обеспечивая при этом буферизированный ввод и вывод. Таким образом, поток – это файл снабженный средствами буферизации. Буферы операционной системы реализуются в виде участков основной памяти фиксированного размера (чаще всего 512 и 1024 байта), который определен как константа стандартной библиотеки BUFSIZ.
Буферизация используется для уменьшения числа операций с магнитным диском.

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

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

Стандартная библиотека

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

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

В заголовочном файле <stdio.h> определен весьма важный тип данных – структура FILE.

 

/* Definition of the control structure for streams

*/

typedef struct {

short level; /* fill/empty level of buffer */

unsigned flags; /* File status flags */

char fd; /* File descriptor */

unsigned char hold; /* Ungetc char if no buffer */

short bsize; /* Buffer size */

unsigned char _FAR *buffer; /* Data transfer buffer */

unsigned char _FAR *curp; /* Current active pointer */

unsigned istemp; /* Temporary file indicator */

short token; /* Used for validity checking */

} FILE; /* This is the FILE object */

 

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

Замечание. Указатель текущей позиции в файле (текущий указатель файла) определяет то место в файле, откуда начинается чтение или запись потока.

 

 

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

· stdin – указатель на FILE, указывающий на стандартный поток ввода (обычно клавиатура)

· stdout – указатель на FILE, указывающий на стандартный поток вывода (обычно дисплей терминала)

· stderr – указатель на FILE, указывающий на стандартный поток ошибок (обычно дисплей терминала)

Также определены еще два специализированных потока, это stdprn и stdaux, для работы с принтером и стандартным последовательным портом. Эти потоки употребляются реже.

 

Константы

В заголовочном файле <stdio.h> определен ряд констант, некоторые из них представлены ниже.

 

#define NULL 0

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

 

#define EOF (-1) /* End of file indicator */

отрицательное целое число типа int, используемое для обозначения конца файла.

 

#define BUFSIZ 512 /* Buffer size for stdio */

целое число, равное размеру буфера, используемое функцией setbuf()

 

#define SEEK_CUR 1

#define SEEK_END 2

#define SEEK_SET 0

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

 



Поделиться:


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

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