Мегаобучалка Главная | О нас | Обратная связь


РЕШЕНИЕ ЗАДАЧ С ИСПОЛЬЗОВАНИЕМ ДАННЫХ ТИПА СТРУКТУРА



2019-08-13 361 Обсуждений (0)
РЕШЕНИЕ ЗАДАЧ С ИСПОЛЬЗОВАНИЕМ ДАННЫХ ТИПА СТРУКТУРА 0.00 из 5.00 0 оценок




Структура — это совокупность разнотипных элементов, которым присваивается одно имя ( оно может и отсутствовать), занимающая одну область памяти. Элементы структуры называются полями.

Как и любая переменная, структурная переменная должна быть описана. Это описание состоит из двух шагов: описание шаблона (т.е. состава ) или типа структуры и описания переменных структурного типа.

Синтаксис описания структуры имеет вид:

 

struct < имя структуры >

{ <тип 1 > имя поля 1;

< тип 2 > имя поля 2. . . . . . . .;

}  р1, р2. . . .;

 

где struct — служебное слово;

< имя структуры > — имя типа структуры ;

<тип 1>, <тип 2> — имена стандартных или предопределенных типов;

имя поля 1, имя поля 2, … — имена полей структуры;

р1, р2. . . .; — имена переменных типа структура.

 

Пример 4.1. Обработать данные о сдаче студентами сессии по предметам: математике, физике и программировании, подсчитать средний балл, полученный студентами по этим курсам.

Определим структуру:

           struct stud

     { char fam [25];     // фамилия и инициалы        

int mat, fiz, prg; // предметы

float sb;              // средний балл

} st1,st2;

Переменные st1 и st2 можно объявить отдельным оператором, например:

struc stud st1 st2;

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

Struct stud

                                 { char fam [25];

int mat,fiz, prg;

float sb;

}

st1 = { " Кравченко И .С .", 4, 5, 5};

st2 = { "Тесленко А .М .", 3, 4, 5};

Если инициализация полей производится в теле программы, то для обращения к именам полей надо сначала записать имя структурной переменной, а потом имя поля, которое отделяется точкой ( составные поля). Следовательно, в случае , когда переменная st1 объявляется в программе, для ее инициализации можно записать stud . st1 = {"Кравченко И.С.",4 ,5 ,5); или инициализация осуществляется с помощью составных полей, как представлено в следующей программе:

// Р 4_1. СPP — определение среднего балла

// использование составных полей

#include < iostream.h >

#include < string.h >

#include < stdio.h >

   void main ( )

          {

          struct stud

          { char fam [20];

              int mat, fiz, prg;

              float sb;

           } st1, st2;

     strcpy (st1. fam, "Кравченко И .С .");

     st1 . mat = 4;

     st1. fiz = 5;

     st1. prg = 5;

     st1. sb = (st1. fiz + st1. mat + st1. prg) / 3;

     st2 = st1;

     puts (st2. fam); // Вывод фамилии st2;

     cout << st2. mat << st2. fiz << st2. prg << st2. sb << endl;

                   }

В этой программе всем полям структуры st1 присвоены соответствующие значения. Надо обратить внимание, что поле st1. fam получает значение путем использования функции strcpy (st1.fam, "Кравченко И.С.");. Структурная переменная st2  имеет ту же структуру, что и st1, поэтому справедлива операция st2 = st1; .

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

 

    struct

            { char fam [25];

int mat, fiz, prg;

float sb;

                                                 } st1, st2;

 

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

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

Struct stud

{ char fio [25];

int den,god;

char mes [10];

char grup;

float sb;

}

и

 

Struct prep

{ char fio [25];

int den, god;

char mes [10];

char kaf, dolg;

                                                }

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

общая структура:

Struct spd

{ char fio [25];

int den,god;

char mas[10];

}

структура для описания информации о студентах:

Struct stud

{ spd dr;

char grup;

float sb

} st1,st2;

структура для описания информации о преподавателях:

Struct prep

{ spd dr;

char kaf [10] ;

  char dolg [15];

} pr1,pr2;

В структурах stud и prep для объявления поля, содержащего данные о фамилии и дате рождения используется ранее описанный тип spd. Теперь к полю fio, den, god, mes можно обратиться, используя запись следующего вида:

                                   st1 . dr . fio

Например, при записи функции ввода — gets (st1 . dr . fio); или pr1 . dr . fio .

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

                                 struct stud

                     { char fam [25];

                int mat, fiz, prg;

                float sb;

           } st1, * pst;

 

Теперь доступ к полям может осуществляться двумя способами :

используя оператор разыменования (*) , например,

           gets ((* pst) . fam);    (* pst) . fiz = 5;

используя специальный указатель на структуру "->", например,

   gets ( pst -> fam); pst -> fiz = 5; и т.д.

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

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

 

    struct stud

                                             { char fam [25];

                                                  int mat, fiz, prg;

                                                  float sb;

                                              } spis[15], *sp = &spis[0];

 

либо, если массив описывается не при описании структуры, то его можно объявить в виде:

                                       stud spis [15];        .

Доступ к элементам массива может выполнятся с использованием индекса или через указатель — константу, которым является имя массива:

 

strcpy( spis [1] . fam, " ");

spis [1] . fiz = 5;

или

 

strcpy ((sp +1) -> fam, " ");

(sp + 1) -> fiz = 5;

Это можно записать также в виде:

 

strcpy ((* (spis +1 )) . fam, " ");

(*(spis+1)) . fiz = 5;

 

Здесь требуется внешняя пара скобок, потому что операция (.) " точка" имеет приоритет выше, чем операция по адресу (*).

Рассмотрим использование данных структурного типа гна следующем примере.

 

Пример 4.2. Ввести в компьютер ведомость успеваемости студентов группы из 25 человек при сдаче сессии по предметам: физике, математике, и программированию и подсчитать:

средний балл, полученный каждым студентом;

средний балл группы по каждому предмету;

вывести на экран отличников по программированию.

Программа будет иметь вид:

   // P4_2. CPP ¾ обработка ведомости успеваемости

// Использование данных типа структура 

#include < iostream.h >

#include < string.h >

#include < stdio.h >

#include < iomanip.h >

void main()

{

const k = 5;

int n = 1, i;

float sm, sf, sp;

struct stud

{ char fam[25];

  int mat, fiz, prg;

  float sb;

} ved[k];

 sm = sf = sp = 0;

cout << "Введите фио и оценки mat, fiz, prg \n " ;

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

{

        gets ( ved[i]. fam );

        cin >> ved[i]. mat >> ved[i]. fiz >> ved[i]. prg ;

        ved[i]. sb = ( ved[i]. mat + ved[i]. fiz + ved[i]. prg) / 3;

        sm += ved[i]. mat;

        sf += ved[i]. fiz;

        sp += ved[ i]. prg;

  }

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

cout << "\t";

for ( i = 0; i < 47; i++) cout << "-"; // Верхняя черта

cout << "\n";

cout << "\t \t ФИО \t мат физ прогр ср .балл \n";

for ( i = 0; i < 47; i++) cout << "-"; // Верхняя черта

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

  {

        cout << "\t" << i + 1 << " " << setw(17)

            << setiosflags ( ios :: left ) << ved[i]. fam;

         cout << ved[i]. mat << " " << ved[i]. fiz <<

         " " << ved[i]. prg << " " << ved[i]. sb << "\n";

           }

cout << "\t";

for ( i = 0; i < 47; i++) cout << "-"; // Нижняя черта

cout << "\n\t" << setw(16) << setiosflags ( ios :: right )

        << "Ср . балл ";

cout << " " << sm / k << " " << sf / k << " " << sp / k << "\n\n";

 cout << "\t Отличники по программированию: \n\n";

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

if ( ved[i]. Prg == 5)

  {

  cout << "\t" << n << " " << ved[i]. fam << "\n";

   n++;

   }

    }

Результат работы программы будет иметь вид:

 

          Ведомость успеваемости студентов

_______________________________________________ 

фио             мат физ прогр ср.балл

_______________________________________________

Авдеев И.М. 3     4     4       3.7

Быков Т.Б.    5     5     4       4.6

Волков А.П.  4     5     5       4.6

_______________________________________________

Ср. балл     3.8   4.6 4.8

 

Отличники по программированию:

 

Волков А.П.

 

 

Поля структуры могут также быть массивами, например, в ранее рассмотренной структуре stud можно оценки по различным предметам объединить в массив. Тогда такую структуру можно описать в виде:

 

Struct stud1

{ char fam [25];

int pr [3];

float sb

} st1 [10], *pst = &st1 [0];             ,

теперь к полям можно обращаться одним из следующих способов:

 

((*pst). fam)         // gets (( *pst) .fam);

( pst -> pr [0] )     // cin >> pst -> pr[0] >> pst -> pr[1];

                                // или cin >> pst -> * ( pr +1).

В библиотеке <stdlib.h> для поиска и сортировки структурных переменных имеются специальные функции. Так , функция быстрой сортировки структурных элементов массива по заданному полю имеет вид :

 

                          #include < stdlib.h >

                            void qsort (void *base , n , width,

                            int (* fcmp ) (const void *elem 1, const void -> elem2))  ,

   где base — указатель на первый элемент массива;

   n  — количество элементов массива;

width —длина элементов массива в битах.

 

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

Функция задается указателем на функцию:

 

int (*fcmp) ( const void *elem1, const void *elem2)      .

 

Функция, на которую указывает fcmp , выполняет сравнение двух элементов массива, на которые указывает elem1 и elem2.

Функция должна возвращать значения:

 

             < 0, если * elem1 < * elem2;

             = 0, если *elem1 = *elem2;

             > 0, если *elem1 > *elem2;

 

Если *elem1 > *elem2 , то элемент, на который указывает elem1 располагается в массиве раньше; "бывший" элемент располагается в упорядоченном массиве позже.

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

В библиотеке <stdlib.h> имеется также функция поиска переменных структурного типа в массиве этих переменных.

 

4.3 Контрольные вопросы

1. Что такое данные типа структура и какие типы данных они содержат?

2. Как описываются данные типа структура?

3. Какие существуют способы инициализации полей структуры?

4. Что такое “вложенность“ структур?

5 ИСПОЛЬЗОВАНИЕ ФУНКЦИЙ ПРИ РАЗРАБОТКЕ ПРОГРАММ

 

 

Функция ¾ это логически завершенная совокупность описаний и операторов, предназначенных для выполнения определенной задачи.

В языке С++ нет деления на основную программу и подпрограммы, на процедуры и функции и т.д. Однако среди функций должна быть одна с именем main , которая может находиться в любом месте программы. Эта функция выполняется всегда первой и заканчивается последней. Любая функция имеет одинаковую структуру, которая имеет вид :

 

[тип результата ] имя функции ([список формальных аргументов])

 {

 // тело функции 

      описания данных ;

                                               операторы ;

      [return] [выражение];

                                      }

здесь квадратные скобки ( [ ] ) , как обычно указывают, что заключенная в них конструкция может отсутствовать ;

тип результата  ¾ любой базовый или ранее описанный тип значения возвращаемого функцией (необязательный параметр), если он отсутствует, то тип результата будет целый (int); этот параметр может быть описан ключевым словом (void), в этом случае функция не возвращает никакого значения (результата). Если параметр задан со звездочкой (*) ¾ функция возвращает указатель на объект, либо на получения адреса объекта (& ) (в операторе return);

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

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

Список формальных аргументов должен иметь следующий вид:

 

( [const] тип 1 [параметр 1] , [const] тип 2 [параметр 2],. . . )

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

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

Void fun ( int p)

{

 ++ p;

 cout << " p=" << p << endl;

   }

 void main ( )

{

int x = 10;

 fun (x);       // вызовфункции

cout << " x=" << x << endl;

 }

В результате работы этого фрагмента программы будет выведено: р=11, х = 10, поскольку для вызова функции fun(x) в нее передается копия значения равного 10, при выполнении этой функции внутри нее значение увеличивается на 1, т.е. (++р) и, поэтому выводится р = 11, но за пределами функции указанное значение не  изменяется.

Если надо изменить переменную оригинал, т.е. передать изменение параметра за пределами тела функции, то можно передать значение параметра по ссылке или использовать параметр–указатель. Тогда, используя параметр- ссылку, получим :

// Использование параметра - ссылки

void fun (int &р) 

{ ++p;

cout << "p = " << р << endl;

 }

void main ( )

 {

int x = 10;

fun( x );

cout << " x=" << x << endl;

}

 

В результате будет выведена информация: р=11 и х=11.

 

При использования аргумента-указателя программа будет иметь вид:

 

// Использование параметра - указателя

void fun2 (int *p)

{

++*р ;

cout << "*p = " << *p << endl;

 }

     void main ( )

 {

int x = 10;

fun2 ( &x );

cout << " x = " << x << endl;

 }

В этом случае получаем тот же результат, т.е. р = 11 и х = 11.

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

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

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

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

 

static int x, y;   или  static float p = 3.25;

 

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

Таким образом, можно сделать заключения:

¾ параметры функции передаются в нее по значению, поэтому за пределами функции они не изменяются, т.е. их нельзя использовать для передачи  результата работы функции;

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

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

¾ если возникает необходимость сохранения значений локальных переменных между вызовами функции, то они должны быть объявлены как статические, т.е. с описанием static, например:

 

static char st[ ]  = " Тесленко А .М .";

 

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

 

       int minmas (int mas [ 50]);         // Массив фиксированной длины

       int minmas (int mas [ ], int n);   //Массив переменной длины

 

¾ все массивы ¾ формальные аргументы передаются по адресу, т.е. как указатели;

¾ в начале программы записывается заголовок используемой функции, называемый прототипом , например:

double sgr (double);      // Прототип функции sqr

. . . . . . . . .

Int main ( )

{

cout << "5**2 = " << sgr (5) << endl;  // Вызов функции

}      

 

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

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

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

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

 

void funct1 ( float x, int y, int z =80 )

{

cout << "x = " << x << " y= " << y << "z=" << z << endl;

}

void funct2 ( float x, int y = 25 , int z = 100 )

{

 cout << "x=" << x << "y=" << y << "z=" << z << endl;

}

void funct3 ( float x=3.5 , int y= 40, int z =200 )

{

cout << "x = " << x << "y = " << y << "z = " << z << endl;

}

   main ( )

{

funct1 ( 5.1 , 10 );      // по умолчанию один аргумент ¾ z

      funct2 ( 10.2 );           // по умолчанию два аргумента ¾ y ,z

funct3 ( );                   // по умолчанию все аргументы

}

   

На экране будет выведено: x =5.1     y = 10    z = 80

                                             x =10.2   y = 25    z = 100

                                         x =3.5     y = 40    z = 200           

                                                  

Из этих иллюстрационных программ видно , что аргумент по умолчанию ¾ это тот, значение которого задано при описании заголовка функции, а при ее вызове этот аргумент можно не указывать.

Если вместо параметра, заданного по умолчанию при обращении к функции, записывается другое значение фактического параметра, то значение по умолчанию подавляется заданным фактическим значением. Так, например, в последнем программном фрагменте при вызове функции funct (13.5, 75);  на экране будет выведено :

 

x = 13.5 y =75 z = 80   , т.е. z - принято по умолчанию.



2019-08-13 361 Обсуждений (0)
РЕШЕНИЕ ЗАДАЧ С ИСПОЛЬЗОВАНИЕМ ДАННЫХ ТИПА СТРУКТУРА 0.00 из 5.00 0 оценок









Обсуждение в статье: РЕШЕНИЕ ЗАДАЧ С ИСПОЛЬЗОВАНИЕМ ДАННЫХ ТИПА СТРУКТУРА

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:
Генезис конфликтологии как науки в древней Греции: Для уяснения предыстории конфликтологии существенное значение имеет обращение к античной...
Личность ребенка как объект и субъект в образовательной технологии: В настоящее время в России идет становление новой системы образования, ориентированного на вхождение...
Почему человек чувствует себя несчастным?: Для начала определим, что такое несчастье. Несчастьем мы будем считать психологическое состояние...
Как выбрать специалиста по управлению гостиницей: Понятно, что управление гостиницей невозможно без специальных знаний. Соответственно, важна квалификация...



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (361)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.007 сек.)