Вы на НеОфициальном сайте факультета ЭиП

На нашем портале ежедневно выкладываются материалы способные помочь студентам. Курсовые, шпаргалки, ответы и еще куча всего что может понадобиться в учебе!
Главная Контакты Карта сайта
 
Где мы?
» » » Введение в использование механизма функций в C++

Реклама


Введение в использование механизма функций в C++

Просмотров: 6951 Автор: admin

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

1. Что такое функция.

2. Как написать собственную функцию.

3. Как обратиться к функции.

4. Как правильно передать данные в функцию и как вернуть их.

Что такое функция

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

имеет имя;

имеет тип;

может иметь параметры (аргументы функции), которые обеспечивают связь функции с внешним окружением;

имеет тело, в котором разработан алгоритм решаемой задачи.

Описание функции

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

тип_возвращаемого_значения имя_функции (тип_параметров имена_параметров)

{

описания локальных переменных;

           описание алгоритма;

return  возвращаемое_значение;    //Отсутствует, если функция void.

}

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

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

2) Имя функции. Это имя main для главной функции программы, или любое, не совпадающее с ключевыми словами и именами других объектов программы.

3) Формальные параметры функции. Это перечисленные через запятую имена аргументов функции вместе с их типами, или void, если параметров нет.

Тело функции содержит:

1. Описания локальных переменных. Их область действия, это тело функции.

2. Описание алгоритма.

3. Возврат в точку вызова. Используется оператор return.

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

Обращение к функции

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

1. Если функция возвращает значение, то им является одно значение базового типа или указатель. Оно может быть использовано в выражениях или печати в виде обращения к функции, которое имеет специальное название «оператор-выражение»:

переменная = имя (фактические параметры);

printf ("форматная_строка ", имя_функции (фактические_параметры));

Например, при обращении к библиотечной функции sin:

y = sin(x);                             // Значение функции вычислено и присвоено y.

printf ("%6.2f", sin(x);                   // Значение функции напечатано.

sin(x);                                   // Значение функции вычислено, но

// что происходит с вычисленным значением?

2. Если функция не возвращает значения (функция типа void), то обращение к ней выглядит как обычный оператор программы, и имеет специальное название «оператор-функция»:

имя_функции (фактические параметры);

Например, при обращении к библиотечной функции printf:

printf ("%d,%d", a, b);

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

Формальные и фактические параметры функции

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

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

В Си++ существуют два способа передачи параметров в функцию:

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

2) По ссылке. Изменение механизма передачи данного в функцию формально выглядит добавлением знака & к имени формального параметра:

имя_функции (тип_параметра & имя_параметра)

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

Пример №1. Функция с одним параметром, возвращающая значение. Функция имеет тип, имя, один параметр. Приведем пример описания функции, которая вычисляет значение некоторой функции в указанной точке, например, y = x2:

floatsqr (floatx)                              // Имя функции sqr .

{

           returnx*x;                            // Одно возвращаемое значение.

}

При обращении к функции используется оператор-выражение. Фактическим параметром может быть константа, переменная или выражение.

#include <stdio.h>

void main (void)

{

float    a, b;

           a = 2.;

           b = sqr (a);                            // Фактический параметр – переменная.

           printf ("\n%f", b);

           b = sqr (3.5);                        // Фактический параметр – константа.

           printf ("\n%f", b);

            b = (a+1.1);                         // Фактический параметр – выражение.

           printf ("\n%f", b);

// Запись обращения сокращается, если использовать обращение в функции вывода.

           printf ("\n%f", sqr (b);

           printf ("\n%f", sqr (3.5);

           printf ("\n%f", sqr (a+b*5.);

}

Пример №2. Функция со многими параметрами, возвращающая значение. Функция имеет тип, имя, несколько параметров. Приведем пример описания функции, которая находит среднее арифметическое трех чисел. Имя функции Avg . Тип функции и ее параметров float.

 

float Avg (float a, float b, float c)

{

float S;                                    // Локальная переменная.

           S = (a + b + c) / 3.;

           return S;                      // Тип совпадает с типом функции.

}

Можно привести пример простой записи той же функции.

float Avg (float a, float b, float c)

{         

           return (a+ b + c) / 3.;           // Тип совпадает с типом функции.

}

При обращении к функции используется оператор-выражение. Фактическим параметром может быть константа, переменная или выражение.

#include <stdio.h>

void main (void)

{

// Фактические параметры – переменные. Результат присвоен переменной y.

float x1=2.5, x2=7. , x3=3.5;

           float y = Avg (x1,x2,x3);

// Фактические параметры – константы. Результат присвоен переменной y.

           y = Avg (2., 4., 7.);

printf ("x1=%f, x2=%f, x3=%f y= %f\n" ,2.,4.,7.,y);

// Фактические параметры – выражения. Результат выводится на печать.

           printf ("x1=%f, x2=%f, x3=%f y= %f\n" ,x1,x2,x3,y);

}

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

int Sum (int n)

{

int       S = 0;                         // Переменная для накопления значения суммы.

int       i;                                // Управляющая переменная для цикла суммирования.

           for (i = 1;i<= n; i++)  // Условие i<= n завершит выполнение цикла при i>n

                       S += i;

return  S;

}

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

int Sum (int n)

{

           for (intS = 0; n > 0; n – –)   // При n = = 0 цикл будет завершен.

                       S += n;

return  S;

}                                                       // Функция не изменит значения n.

Обращение к функции особенностей не имеет.

#include <stdio.h>

void main (void)

{

intCou;

           printf ("\n Введите число слагаемых\n ");

           scanf ("%d", &Cou);

           printf ("Сумма=%d", Sum(Cou));

}

Имя любого локального данного не должно совпадать с именем функции. Вот пример распространенной ошибки, когда имя функции совпадает с именем ее локального данного. Результат в этом случае непредсказуем.

int Sum (int n)

{

int       Sum = 0;

int       i;

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

                       Sum += i;

return  Sum;

}

Пример №4. Функция, не возвращающая значения, и не имеющая параметров. Приведем пример описания функции, которая выводит на экран 50 символов «звездочка». Имя функции print. Список формальных параметров пуст. Функция, не возвращающая значения, не имеет в своем теле оператора return.

#include <stdio.h>

voidprint (void)                              // Функция типа void, не возвращает значения.

{

int       i;                                           // Внутренняя рабочая переменная.

           for (i = 1;i <= 50; i++)

                       printf ("%c", '*');       // Вывод символа «звездочка».

printf ("\n");

}

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

void main (void)

{

           print ();                       // Обращение к print ().

           printf ("          \tПример вызова функции.\n");

           print ();

}

Вывод на экран будет иметь вид:

 

*****************************************************

                          Пример вызова функции.

*****************************************************

 

Пример №5. Функция с параметрами, не возвращающая значения. Приведем пример описания функции, которая выводит на экран произвольное количество символов «звездочка». Поскольку количество произвольно, его значение может быть определено только на момент обращения к функции, значит, его следует сделать параметром функции. Функция, не возвращающая значения, не имеет в своем теле оператора return.

#include <stdio.h>

#include <conio.h>

void print (int count)                       // Печать строки «*» длиной count.

{

int       i;

           for (i = 1; i <= count; i++)    // count – количество символов в строке.

                       printf ("%c", '*');

           printf("\n");

}

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

void print (int count, char symbol)           // Печать строки символов symbol

                                                                  // длины count .

{

int       i;

           for (i = 1; i <= count; i++)              // count – количество символов в строке.

                       printf ("%c", symbol);

           printf("\n");

}

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

void main (void)

{

int cou;

clrscr();

           for (cou = 1; cou <= 12; cou++)

                       print(cou);                 // Здесь соu – количество при обращении.

getch();

}

При обращении к функции с двумя параметрами, первый фактический параметр означает число выводимых символов, второй вид символа. Оператор-функция выводит при первом обращении 80 символов тире ('–'), при втором 25 символов плюс ('+'). При первом обращении фактические параметры константы, при втором переменные.

void main (void)

{

char     ch;

ch = '+';

int       cou = 25;

clrscr();

           print (80, '–');                       // 80 символов тире ('–').

           print (cou, ch);                               // 25 символов плюс ('+').

getch();

}

Пример №6. Логические функции. Логические функции используются во многих случаях, когда нужно выполнить проверку условия, как правило, сложного, или в алгоритмах поиска. Особенностью их является то, что функция возвращает одно значение логического типа, которого в Си++ нет. Логический тип заменяется целочисленным, интерпретация которого соответствует принятой идеологии: ложно то, что равно 0, истинно то, что отлично от 0 (не обязательно 1). Это правило используется при вычислении значений логических выражений, а также при проверке условий в операторе if и в операторах цикла.

Примером логической функции с простым алгоритмом может служить функция определения четности числа. Функция должна вернуть значение логического выражения «остаток от деления числа на два равен 0».

intChet (intnum)                            // Функция возвращает логическое значение.

{

           returnnum%2 == 0;             // Остаток от деления на два.

}

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

intEasy (intnum)                            // Функция возвращает логическое значение.

{

int       mod;                                     // Делитель числа, управляющая переменная.

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

           for (mod = 2; mod <= num/2; mod++)   

                      if (num%mod == 0)

                                  return 0;                  // Прерывание поиска, делитель найден.

           return 1;                               // Поиск завершен по управлению.

}

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

#include <stdio.h>

#include <conio.h>

void main (void)

{

int       Number;

do

           {

           printf ("Введите число\n");

           scanf ("%d", &Number);

           if (! Chet (Number) && Easy (Number) )         // Если число нечетное и простое.

                                  printf("Число простое\n");

                       else

                                  printf("Число не простое\n");

           printf ("Продолжение – любая клавиша, выход – Esc\n");

           }while (getch() != 27)

}

Логика оператора условия звучит как перевод с русского на Си++. Однако, если эта запись вызывает трудности в понимании, используйте явные проверки соответствия возвращаемого значения логической константе: 1, это «истина», 0, это «ложь».

           if (Chet (Number) != 0)                           // Число нечетно.

                       {

                                  if (Easy (Number) == 1)   // Число простое.

                                             printf("Число простое\n");

                       }

                       else

                       printf("Число не простое\n");

Пример №7. Несколько слов о роли оператора return и о сложности алгоритма функции. Оператор return относится к операторам управления программой. Его назначение не только определить и вернуть вычисленное функцией значение, но и прервать работу алгоритма функции, выполнив выход из нее правильным образом. Синтаксис return имеет две формы:

return Выражение;

return;

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

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

 // В алгоритме этой функции три варианта выхода. float pow_1 (float x, int n)                                 // Основание float, степень int. { float    S;                                                             // Локальная переменная.            if ( n > 0 )                                                // Положительная степень.                        {                        for( S = 1.0; n > 0; n – –)                                   S *= x;                        returnS;                                       // Решение найдено при n>0.                        }                        else                        if ( n < 0 )                                     // Отрицательная степень.                                   {                                   for(S = 1.0; n < 0; n ++)                                              S *= x;                                   return 1. / S;                     // Решение найдено при n<0.                                   }                                   else                                              return 1.0;             // Решение найдено при n = 0 printf ("Кому нужны эти функции?");              // Оператор вне всех ветвей.                                                                            // Он никогда не будет выполнен. } 

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

#include <stdio.h>

void main (void)

{

int       n;

float    x;

           printf ("Введите вещественное основание и целую степень\n");

           scanf ("%f%d", &x, &n);

           printf ("\n\n\nДанные и решение:%6.2f %4d %6.2f\n", x, n, pow_1 (x,n));

}

Пример №8. Функция, возвращающая значение через параметры. Использование механизма возвращения данных через параметры необходимо всегда, когда функция должна вернуть более одного значения. Возвращаемые значения должны передаваться по ссылке. Синтаксически в заголовке функции к имени параметра добавляется &, например int & Cou. Технически радикально изменяется механизм передачи данных, в этом случае в тело функции передается адрес объекта Cou, который выделен для него в вызывающей программе. Иллюстрацией отличия двух механизмов передачи данных будет пример функции, которая должна переменить значения двух переменных.

 // Функция Swap1 с параметрами по значению. void Swap1 (int x, int y) { int       tmp;            tmp = x;            x = y;            y = tmp;                    // Переменные переменились своими значениями. } // Функция Swap2 с параметрами по ссылке. void Swap2 (int &x, int &y) { int       tmp;            tmp = x;            x = y;            y = tmp;                    // Переменные переменились своими значениями. } Как видим, функции одинаковы во всем, кроме механизма передачи параметров. Обратимся к этим функциям одинаковым образом, получим разный результат. void main (void) { int       a=5, b=10; printf ("Было: a=%d b=%dn", a, b);            Swap1 (a, b); printf ("Передача по значению: a=%db=%dn", a, b);            Swap2 (a, b); printf("Передача по ссылке: a=%d b=%dn", a, b); } 

Вывод на экран покажет, что функция Swap1 работает с локальными копиями данных, а Swap2 работает с адресами данных.

Было: a=2 b=10

Передача по значению: a=2 b=10

Передача по ссылке: a=10 b=2

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

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

 #include <stdio.h> #include <math.h> int Triangle (float a, float b, float c, float & p, float &s) {          // p и s – внешние данные, могут быть входными и выходными. floatpp;                                                    // Полупериметр, локальная переменная.            if (a + b <= c || a + c<= b || b + c <= a)                        return 0;                              // Треугольник не существует.                        else                                   {                                              p = a + b + c;                                              pp = p / 2.;                                              s = sqrt (pp*(pp – a)*(pp – b)*(pp – c));                                              return 1;       // Треугольник существует.                                   } } 

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

 void main (void) { float    A, B, C;                                // Длины сторон фактические. float    Perim, Square;                      // Периметр и площадь фактические.            printf("Введите длины сторон треугольникаn");            scanf ("%f%f%f", &A, &B, &C);            if (Triangle(A, B, C, Perim, Square)==1)          // Проверка условия.                        printf("Периметр равен %6.2f, площадь равна %6.2fn", Perim, Square);                        else                        printf("Треугольник не существуетn"); } 

Пример №10. Функция, возвращающая указатель. Такие функции используются тогда, когда тип возвращаемого данного не является простым, например, возвращается массив, или когда в теле программы получено новое динамическое значение.

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

 #include <stdio.h> #include <conio.h> #include <math.h> int * New_obj (int a, int b)     // Тип функции указатель. { int       * Obj;                                   // Новый объект будет создан или нет в функции.            if (a > b)                        {                        Obj = newint;           // Создается новый объект.                        *Obj = 1;                   // Ему присваивается значение.                        returnObj;                // Возвращается его адрес.                        }            else                        return NULL; } В вызывающей программе объявлен указатель int * ip, которому будет присвоено возвращаемое значение. void main (void) { int       p1, p2;                                           // Переменные. int       * ip;                                      // Указатель на новый объект. printf ("Введите две переменныеn"); scanf ("%d%d", &p1, &p2); // Обращение к функции обычное.            ip = New_obj (p1, p2);            if (ip != NULL)                        printf ("Новый объект имеет адрес %p, значение %dn", ip, *ip);                        else                       printf ("Новый объект не создан, использовать ip нельзя,                                               его значение %sn", ip); } 

В первом выводе на экран для вывода адреса ip использован спецификатор формата %p, во втором для вывода константы NULL использован спецификатор формата %s, чтобы увидеть текстовое представление константы. Если использовать спецификатор %p, адрес будет показан как 0000.

Варианты заданий

Задание 1.

1. Описать функцию F(x), вычисляющую значение периодической функции в произвольной точке. Период функции T = 2. На интервале [–1, 0] она совпадает с функцией y = x + 1, на интервале (0, 1] совпадает с функцией y = – x + 1. Обратиться к функции на интервале xÎ [ – 2, + 4] с не менее чем десятью точками.

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

Задание 2.

1. Описать логическую функцию Yes (x, y), которая определит, принадлежит ли точка с координатами (x, y) единичной окружности, центр которой совпадает с началом координат. Обратиться с координатами точек, лежащими на параболе y = x2 для        x Î [–2; +2], шаг =0.5.

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

Задание 3.

1. Описать логическую функцию Is_letter (c), которая определит, является ли некий произвольный символ c (параметр функции) одной из строчных или заглавных букв русского алфавита. Обратиться к функции в диалоге, передавая ей посимвольно текст, вводимый с клавиатуры.

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

Задание 4.

1. Описать функцию S(x, e), вычисляющую значение суммы ряда в точке x с указанной точностью e, если формула суммы:

Обратиться с координатами точек x Î [–0.5;+0.5], шаг = 0.1.

2. Описать консольную функцию, которая выводит на чистый экран окно с рамкой, и позиционирует курсор внутри него. Размер окна должен быть достаточен, чтобы вывести все результаты, полученные при обращении к первой функции. Вывести в это окно таблицу значений функции S(x, e).

Задание 5.

1. Описать логическую функцию Is_Tri (a, b, c), которая по значениям длин трех отрезков a, b, c определит, можно ли построить треугольник с такими сторонами. Обратиться в диалоге.

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

Задание 6.

1. Описать функцию Pi (e), вычисляющую значение числа π по формуле:

с произвольной точностью e. Значение точности передать в функцию как аргумент. Обратиться к функции в цикле, вычисляя значение с точностью 0.01, 0.001, 0.0001.

2. Описать консольную функцию, которая выводит на чистый экран окно с рамкой, и позиционирует курсор внутри него. Размер окна должен быть достаточен, чтобы вывести все три результата, полученные первой функцией. Вывести в это окно таблицу значений функции Pi (e).

Задание 7.

1. Описать функцию P(x), вычисляющую значение полинома в произвольной точке x по формуле:

 для 50 слагаемых.

Обратиться к функции со значениями x Î [–0.5;+0.5] с шагом 0.1.

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

Задание 8.

1. Описать функцию Min (x, y, z), которая вернет значение наименьшего из трех своих аргументов. Обратиться в диалоге.

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

Задание 9.

1. Описать функцию Square (a, b, c), которая найдет площадь треугольника по значениям длин сторон a, b ,c. Если треугольник не существует, функция вернет значение 0. Обратиться к функции в цикле со значениями длин сторон (1,2,3), (2,3,4), (3,4,5), (4,5,6), (5,6,7) и т.д. до (10,11,12).

2. Описать консольную функцию, которая выводит на чистый экран окно с рамкой, и позиционирует курсор внутри него. Размер окна должен быть достаточен, чтобы вывести все результаты, полученные при обращении к первой функции. Вывести в это окно таблицу значений функции Square (a, b, c).

Задание 10.

1. Описать функцию Transform (n), которая преобразует натуральное число n, «приписывая» к нему по единичке в начале и в конце. Обратиться к функции со значениями 23, 234, 2345.

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

Задание 11.

1. Описать функцию R(x1, y1, x2, y2), которая вычисляет расстояние между двумя точками на координатной плоскости. Обратиться к функции в диалоге, чтобы определить расстояния между началом координат и вершинами некоторого квадрата, заданного координатой верхнего левого угла и длиной стороны.

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

Задание 12.

1. Описать функцию Count (r), которая определит, сколько точек с целочисленными координатами попадают в круг радиуса R с центром в начале координат. Обратиться в диалоге.

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

Задание 13.

1. Описать логическую функцию P(x), которая определит, является ли ее аргумент x простым числом. Обратиться к функции со значениями чисел натурального ряда от 7 до 99.

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

Задание 14.

1. Описать функцию R(a, b, c), определяющую радиус вписанной окружности для треугольника со сторонами a, b, c. Обратиться к функции с равносторонними треугольниками со сторонами 2,3,4,5,6. Предусмотреть условие существования треугольника. Если он не существует, функция должна вернуть значение 0.

2. Описать консольную функцию, которая выводит на чистый экран окно с рамкой, и позиционирует курсор внутри него. Размер окна должен быть достаточен, чтобы вывести все результаты, полученные при обращениях к первой функции. Вывести в это окно таблицу значений функции R(a, b, c).

Задание 15.

1. Описать функцию S (a, b, h), которая найдет площадь равнобочной трапеции с заданными основаниями и высотой. Обратиться к функции в диалоге.

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

Задание 16.

1. Описать функцию Square (r1, r2), которая найдет площадь кольца с заданными радиусами. Если первый параметр меньше второго, возвращать значение 0. Обратиться к функции в диалоге.

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

Задание 17.

1. Описать функцию S_C(r, angle), которая найдет значение площади сектора круга с заданными значениями радиуса и угла (в градусах). Если угол отрицательный или больше чем 360°, возвращать значение 0. Обратиться к функции в диалоге.

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

Задание 18.

1. Описать функцию Sum_AP(a1, d, n) которая найдет сумму арифметической прогрессии. Предусмотреть проверку исходных данных, и в случае ошибки возвращать значение 0. Обратиться к функции в диалоге.

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

Задание 19.

1. Описать логическую функцию Is_in (x1, y1, x2, y2, x3, y3), которая по заданным координатам вершин треугольника определит, находится ли начало координат внутри этого треугольника. Возвращать значение –1, если треугольник не существует, 0, если снаружи, и 1, если внутри. Обратиться к функции в диалоге.

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

Задание 20.

1. Описать функцию R(long int N), которая по заданному значению произвольного натурального числа определит его разрядность. Обратиться к функции со значениями 3, 13, 130, 1300, 13000.

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

Тип данных «массив». Работа с одномерными массивами. Использование функций при работе с массивами

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

1.       Что такое массив?

2.       Как описать массив?

3.       Как размещаются в памяти элементы массива?

4.       Как обратиться к элементу массива?

5.       Как присвоить значения элементам массива?

Основные алгоритмы для работы с массивами можно условно назвать в следующем перечне:

1.       Использование массивов переменной длины.

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

3.       Поиск в массиве, то есть способы нахождения элементов массива, удовлетворяющие какому-то критерию.

4.       Определение количества элементов, удовлетворяющих какому-то критерию.

5.       Суммирование элементов массива, всех или только соответствующих каким-то условиям.

6.       Поиск максимального и минимального значения.

7.       Преобразование элементов массива по какому-либо принципу.

8.       Получение программным путем нового массива, если известен алгоритм его формирования.

9.       И так далее.

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

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

Пусть в вызывающей программе объявлен массив

int   Array[10];

Имя Array, это адрес нулевого элемента массива.

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

void Function1 (int Array[], int len)

{

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

                 // Обращение к Array[i];

}

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

void Function2 (int  * Array, int len)

{

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

                 // Обращение к Array[i];

}

Признак «*» у формального имени массива в списке параметров означает, что функция получает указатель на массив, то есть при обращении фактический передается адрес массива в памяти.

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

Function1 (Array, 10);         // Передается весь массив.

Function2 (Array, 5);  // Передается весь массив, но его длина ограничена 5.

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

Теперь поясним, как функция возвращает массив.

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

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

Синтаксически это можно записать так:

 int * Function3 (int * Array, int len) { for (int i = 0; i < len i ++)                  // Обращение к Array[i];        returnArray; } В этом примере мало смысла, так как массив в списке параметров. Имеет смысл использовать второй способ для динамических массивов, создаваемых в теле функции. Например, функция создает динамический массив указанной длины. Динамическая память для массива выделена в теле функции. int *New_mas(int len)                    // Тип функции указатель. { int   *mas = new int[len];               // Выделено len * sizeof(int) байт памяти,                                                        // адрес которой присвоен переменной mas. for (int i = 0; i < len; i++) *(mas+i)=i+1;               // Присвоены значения по возрастанию. returnmas;                                              // Адрес необходимо вернуть. } Вызывающая программа должна быть готова к получению нового данного. Для этого в ней объявлен указатель. До обращения к функции, он пустой, и примет значение только после обращения. Возвращаемое функцией значение присваивается указателю. #include <stdio.h> void main (void) { int   *Array;                                                      // Пустой указатель. int   len_A; printf ("Введите длину массиваn"); scanf ("%d", &len_A); Array = New_mas (len_A);                      // Теперь получил адрес.  for (int i = 0; i < len_A; i++) printf ("%3d",Array); printf ("n"); } 

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

#include "Task.h"

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

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

 #include <stdio.h> #include <math.h> // Пример №1. Функция вывода на экран целочисленного массива в общем виде. // Формальные параметры функции – имя массива (указатель), и длина массива. void Print_mas (int mas[], int len)            // len – длина массива. { int       i;                                                    // Рабочая переменная.            printf ("Массив:n");                      // Вывод заголовка.            for (i = 0;i < len; i++)                        printf ("%5d",mas[i]);                  // Вывод элемента массива в строку.            printf ("n");                                   // По завершении вывода переход на                                                                   // новую строку. } // Пример №2. Функция ввода целочисленного массива в общем виде. // Формальные параметры функции – имя массива (указатель), и длина массива. // Длина массива определена в теле функции. Чтобы функция могла вернуть это // значение, формальный параметр len должен передаваться по ссылке. void Input_mas (int *mas, int &len)                   // Длина изменяется, &len – ссылка. { int       *ip;                                                // Для адресации используется указатель                                                                   // на элемент массива.            printf ("Введи кол-во элементов массива n");            scanf ("%d", &len);            printf ("Введи элементы массива n");            for (ip = mas; ip < mas + len; ip++)                        scanf("%5d", ip)                 // & не нужен, . } // Пример №3. Функция преобразования целочисленного массива увеличивает // значение каждого элемента в два раза. // Поскольку массив всегда передается в функцию как указатель, то измененные в // теле функции значения элементов массива доступны и вызывающей программе. // Формальные параметры функции – имя массива (указатель), и длина массива. void Transform_mas(int *mas, int len)     // Длина не изменяется, len – значение { int       i;            for (i = 0; i < len; i++)                        mas = mas *2; } // Пример №4. Поиск в массиве. Смысл задачи в том, что для массива задан критерий // отбора, то есть условие, которому должны соответствовать элементы массива. // Задачу поиска можно решать многими способами, из них простейший, это прямой // поиск. Прямым он называется потому, что условие отбора просто примеряется по // очереди ко всем элементам массива, и для тех, кто соответствует условию, // выполняется какое-то действие, например, печать. Для примера найдем все числа, // кратные пяти. // 1. Поиск всех вхождений значения. void Find_all (int mas[], int len) { // Поиск всех вхождений чисел, кратных пяти. for (int i = 0; i <len; i + +)            if (mas % 5 == 0)                        // Здесь с этим элементом можно что-нибудь сделать, например, вывести.                        printf ("Кратен пяти элемент с номером %d", i) } // Замечание. В случае, когда в массиве нет ни одного искомого значения, функцией // будет выполнено len сравнений, но ни одной печати, соответственно, никакого // сообщения пользователь не получит. // 2. Поиск первого вхождения значения. Особенностью является то, что при первом // же удачном сравнении алгоритм должен закончить свою работу. Но если нужного // элемента не окажется вообще, выход из функции произойдет при завершении // цикла, и результатом должно быть значение, отличное от любого номера элемента // массива, например, 1. int Find_first (int mas[], int len) { // Поиск первого вхождения числа, кратного пяти.            for (int i = 0; i < len; i ++)                        if (mas % 5 = = 0)                                    returni;          // Прерывание при найденном значении.                                                         // Функция вернет номер вхождения.            return –1;                             // Неудачный поиск, функция вернет –1. } // При обращении к функции нужно учесть, что значение –1, возвращенное // функцией, означает неудачный поиск. //         Num = Find_first (A, 5); //         if (Num >= 0) //                     printf("Номер %dn", Num); //                     else //                     printf("Элемент не найден"); // Пример №5. Найти сумму элементов массива. // Функция возвращает одно значение, поэтому ее тип int. В этой задаче приведем // пример использования различных способов адресации элементов массива, прямую // и косвенную. Выбор способы адресации не зависит от способа передачи в // функцию параметра-массива // 1. Прямая адресация. Обращение к элементам массива через операцию [] int Sum1 (int *mas, int len) { int       i; int       Sum = 0;            for (i =0; i < len; i++)                        Sum += mas;            returnSum; } // 2. Косвенная адресация. Обращение к элементам массива через операцию *, // примененную к указателю (на очередной элемент массива). int Sum2 (int *mas, int len) { int       * ip; int       Sum = 0;            for (ip = mas; ip < mas+len; ip++)                        Sum += *ip;            return Sum; } // 3. Косвенная адресация. Обращение к элементам массива через операцию * // и смещение указателя относительно начала массива. int Sum3 (int * mas, int len) { int       i; int       Sum;            for (i = 0, Sum = 0; i < len; i++)                        Sum += *(mas+i);            return Sum; } // Пример №6. Вывод на экран номеров и адресов элементов массива иллюстрирует // отличие способов адресации друг от друга. Спецификатор формата для вывода // адреса – %р. Так вы увидите реальные адреса памяти, выделенные для размещения // массива. void Out (int *mas, int len) { int       i; int       *ip;            for (ip = mas, i=0; ip < mas + len; ip++, i++)                        printf("Номер %d Адрес %pn", i++, ip); } // Пример №7. Функция поиска наибольшего (наименьшего) элемента массива. // Алгоритм решения следующий: введем переменную, обозначающую // максимальное значение, и сначала предположим, что наибольшим (наименьшим) // является первый элемент массива. Далее в цикле все последующие значения сравним // с максимальным (минимальным), и, если найдется такое значение, что побольше // максимума (меньше минимума), то значение максимального (минимального) // заменяется значением найденного элемента массива. // 1. Использование прямой адресации. int Max1 (int mas[], int len) { int       i; int       max;                                               // Наибольшее значение.            max = mas[0];                                         // Пусть первое наибольшее.            for (i = 0; i< len; i++)                        if (mas > max) max = mas;   // Если найден элемент (mas),                                                                   // больший, чем тот, которого                                                                   // считали максимальным (max),                                                                   // то запоминаем его значение.            returnmax;                                    // Возвращаем значение наибольшего. } // 2. Использование косвенной адресации. int Max2 (int mas[], int len) { int       *ip;                                                // Указатель на элемент массива. int     *imax;                                              // Указатель на наибольшее значение imax = mas;                                     // Запоминаем адрес максимального.            for (ip = mas+1; ip< mas + len; ip++)                        if (*ip > *imax) imax = ip; // Если найден элемент (*ip),                                                                   // больший, чем тот, которого                                                                   // считали максимальным (*imax),                                                                   // то запоминаем адрес.            returnimaxmas;                         // Возвращаем номер наибольшего. } // Пример №8. Функция удаления элемента из массива. Для определенности // удалим все отрицательные элементы массива. Удаление элемента заключается в // сдвиге части массива влево на одну позицию, начиная с удаляемого значения. // Длина массива уменьшается на 1 при каждом сдвиге, поэтому длина массива // возвращается по адресу. В этом алгоритме объединены поиск (Пример №3) // и удаление, причем цикл удаления внутренний, так как для каждого найденного // значения выполняется сдвиг оставшейся части массива влево на одну позицию. // Управление циклом выполняет оператор for, из которого изъято приращение // параметра цикла. Это необходимо, так как приращение номера элемента должно // происходить лишь тогда, когда удаления не было. Это позволит избежать ошибки, // когда удаляемые элементы будут идти подряд. void Del (int mas[], int &len) { // Поиск отрицательных элементов выполняется в цикле с рабочей переменной i. // Если найден отрицательный элемент, его номер будет i. int       i;                                                    // Рабочая переменная для поиска. int       j;                                                    // Рабочая переменная для удаления.            for (i = 0; i < len; )                         // Приращение изъято.             {                        if (mas[i] < 0)                      // Элемент должен быть удален.                                   {                                   for ( j = i; j < len – 1; j++)                                              mas[j] = mas[j+1];                                   len – –;                              // Длина стала меньше по завершении цикла.                                   }                                   else                                   i + +;                       // Переход к следующему поиску, только }                                                                // если не было удаления . } // Пример №9. Элементы массива можно менять местами. // Например, переставим их по кругу, это называется циклический сдвиг. // Последний элемент не упадет за край массива, а станет первым. void Cyrcle_Mas (int mas [], int len) { // Переменная tmp запомнит значение последнего элемента. int tmp = mas[len – 1];            // Сдвиг массива вправо, начиная с первого элемента, до len-1.            for (int i = len-1; i > 0; i– –)                        mas = mas[i-1];            mas[0] = tmp;                                // Запомненный элемент записывается вперед. } // Пример №10. Функция формирования нового массива. // Получим массив, в котором содержатся только положительные элементы // исходного массива. Все необходимые данные должны быть объявлены вне тела // функции, и должны быть известны вызывающей программе. Длина нового массива // и его значения получены функцией и возвращаются в вызывающую программу. int New_mas (int mas[],int len, int *mas_new, int &len_new) {            len_new = 0;                         // В новом массиве нет ни одного значения.                                                         // Переменная len_new индексирует новый                                                         // массив, а по завершению работы будет знать                                                         // число записанных элементов. // Прямой поиск положительных элементов:            for (int i = 0; i < len; i++)                        if ( mas > 0 )          // Найден положительный элемент:                                                         // запись его в новый массив.                                                         // Индексация в массивах различна.                                              mas_new [len_new++] = mas;        // По завершении цикла поиска определена длина нового массива, это переменная // len_new. Она может оказаться равной 0, поэтому имеет смысл возвращать значение // длины нового массива. Именно поэтому функция имеет тип int, что дает ей статус // функции, возвращающей логическое значение.            return len_new; } // При обращении к этой функции можно выполнить проверку: если функция // вернула 0, новый массив имеет нулевую длину, то есть, не сформирован. //         if ( New_mas (Array_old, 10, Array_new, len) ! = 0) //                     print_mas(Array_new,len); // В противном случае любые действия с новым массивом бессмысленны. // Пример №11. Функция может работать с данными базовых типов, а при обращении // ей передаются элементы массива. Например, функция находит расстояние между // двумя точками на плоскости . float R(float x1, float y1, float x2,float y2) {            return sqrt (pow (x1–x2, 2.)+pow (y1–y2 ,2.)); } 

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

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

 #include <stdio.h> #include "Task.hpp"              // Включен текст заголовочного файла. #define N 10                           // Это объявление длины массива … void main(void) { int       a[] = {1, –2, 3, –4, 5, –6};             // Объявление и инициализация массива а. // Длина массива определена длиной списка инициализации. int       na = sizeof(a) / sizeof(int); // Чтобы увидеть размещение в памяти элементов массива, выведем его на печать:            Print_mas (a, na); // Изменим значения элементов массива:            Transform_mas (a, na); // Покажем, что они изменились:            Print_mas (a, na); // Массив условно переменной длины. int       b[N];                                     // Выделена память для N элементов массива b. int       nb = 0;                                           // Реальная длина массива b < N.            printf ("Длина массива должна быть < %d", N); // Введем его значения.            Input_mas (b, nb);                // Длина будет определена при вводе. // Найдем сумму элементов массива тремя функциями вычисления суммы, // чтобы показать, что способы адресации в массиве могут быть различны, // а результат один и тот же.            printf ("Прямая адресация:          Sum1 = %dn", Sum1 (b, nb));            printf ("Косвенная адресация:      Sum2 = %dn", Sum2 (b, nb));            printf ("Косвенная адресация:      Sum3 = %dn", Sum3 (b, nb)); // Покажем сходство и различие механизмов адресации:            Out (b, nb); //Найдем наибольший элемент массива b:            printf ("Номер = %d, Значение = %dn", Max1 (b, nb), b[Max1 (b,nb)]); //Удалим из массива а отрицательные элементы.            Del (a, na); // Покажем, что осталось.            printf ("После удаления:n");            Print_mas (a, na);                          // Длина массива уменьшилась. // Выполним циклический сдвиг в массиве b:            Cyrcle_Mas (b, nb);            printf("После сдвига:n");            Print_mas (b, nb); // Циклический сдвиг можно выполнить много раз, если обратиться к функции в // цикле, например, трижды:            for (intC = 1; C<=3 ; C++)           // C– обычный счетчик.                        Circle_Mas (b, nb);            printf("После сдвига:n");            Print_mas (b, nb); // Объявим новый массив и проинициализируем его. int       d [5] = {–1, 1, –2, 2, –3}; // Объявим новый массив, длина которого не более 5-ти. int       c[5]; int       nc;                                        // Реальная длина нового массива. // Получим новый массив, в котором только положительные элементы массива d. // Данные нового массива и его длина будут получены функцией и возвращены // в вызывающую программу. Функция дважды возвращает длину, через имя и // через список параметров,            nc = New_mas (d, 5, c, nc);            if (nc != 0)                   // Длина нового массива больше 0, массив получен.                        {                                   printf ("Новый массив:n");                                   print_mas (c, nc);                        }                        else                                   printf ("Массива нетn"); // Массив не сформирован. // Обращение к функции с элементами массива. // Два массива определяют значения координат точек на плоскости. float    x[3] = {1., 2., 3.}; float    y[3] = {3., 2., 1.}; printf("С элементами массива обращаемся к функции,n                        чтобы найти расстояние от точек до начала координатn");            for (int i = 0; i < 3; i ++)                        { // При обращении к функции ей передается только одна точка.                                   printf ("%6.2f %6.2f, R = %6.2fn", x, y, R(0,0,x,y));                        } } // End of main 

Варианты заданий

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

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

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

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

void (int mas, int &len)

{      …

}

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

Задание 1.

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

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

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

Задание 2.

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

2. Описать функции ввода и вывода элементов массива. Описать функцию, которая удалит повторяющиеся элементы массива.

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

Задание 3.

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

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

3. Описать функцию случайной генерации элементов массива Y, в котором могут быть как положительные, так и отрицательные значения. Описать функцию получения нового массива Z по следующему закону: Zi = Yi ,если Yi по модулю больше 1, и Zi = 1 в противном случае. Найти и вернуть число единичек в новом массиве. Использовать механизм указателей.

Задание 4.

1. Проинициализировать массив. Описать функцию, которая найдет количество элементов массива, принадлежащих интервалам [–2, –5] или [2, 5]. Описать функцию, которая найдет сумму элементов, не входящих в указанные интервалы.

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

3. Описать функцию случайной генерации элементов массива. Описать функцию, которая сохранит в новом массиве только те элементы исходного, которые принадлежат интервалам [–2, –5] или [2, 5]. Использовать механизм указателей.

Задание 5.

1. Проинициализировать массив. Описать две функции для нахождения номеров наибольшего и наименьшего элементов массива.

2. Описать функции ввода и вывода элементов массива. Описать функцию, которая удалит из массива наибольший и наименьший элементы.

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

Задание 6.

1. Проинициализировать два массива, которые задают n точек координатами (X, Y) в двумерном пространстве. Описать функцию, которая находит расстояние между двумя произвольными точками. Описать функцию, которая найдет расстояние между всеми точками и выведет их на экран в виде таблицы. Описать функцию, которая найдет наибольшее расстояние.

2. Описать функции ввода и вывода элементов массива. Описать функцию, которая выполнить сжатие массива (удаление всех чисел, меньших нуля).

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

Задание 7.

1. Проинициализировать два массива, которые задают n точек координатами (X, Y) в декартовой системе координат. Описать функцию перевода декартовых координат точки в полярные (углы в градусной мере вычислять с точностью до градусов). Для всех точек перевести декартовы координаты в полярные, сохранить в массивах. Описать функцию поиска наибольшего значения. Найти номер точки, имеющей наибольший радиус-вектор, и номер точки, имеющей наибольший угол. Вывести значение декартовых и полярных координат этих точек.

2. Описать функции ввода и вывода элементов массива. Описать функции поиска и удаления из массива произвольных цепочек чисел (М1, М2, М3).

3. Описать функцию случайной генерации элементов массива. Описать функцию, которая находит в массиве все элементы, значения которых принадлежат некоторому указанному диапазону [M1;M2], и формирует из них новый массив. Использовать механизм указателей

Задание 8.

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

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

3. Описать функцию случайной генерации элементов массива. Описать функцию, один из параметров которой символьная переменная «знак», принимающая значения '>' или '<'. Функция перепишет в новый массив только те элементы исходного, которые больше среднего арифметического, если знак '>', и те, которые меньше, если знак '<'. Использовать механизм указателей.

Задание 9.

1. Проинициализировать массив. Описать две функции, которые определят, являются ли элементы массива упорядоченными по возрастанию, и являются ли элементы массива упорядоченными по убыванию. Описать функцию, которая одна выполняет полную проверку. Если порядок возрастания, функция вернет 1, если убывания, –1, если нет порядка, 0.

2. Даны координаты материальных точек, расположенных на прямой. Описать функции ввода и вывода массивов. Ввести координаты точек. Описать функцию, которая найдет координату центра тяжести системы. Описать функцию, которая найдет номер точки, наиболее удаленной от начала оси. Описать функцию, которая удалит эту точку.

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

Задание 10.

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

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

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

Задание 11.

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

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

 , а остальные удалит.

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

Задание 12.

1. Проинициализировать массив, в котором могут быть как положительные, так и отрицательные числа. Описать функцию, которая проверит, являются ли элементы массива упорядоченными по возрастанию. Описать функцию сортировки массива по возрастанию методом пузырька. Алгоритм заключается в следующем: массив просматривается по перекрещивающимся парам чисел (аi, ai+1). Если аi > ai+1, они меняются местами. Перестановки подсчитываются. Алгоритм завершает работу, если при просмотре массива нет ни одной перестановки. Сортировка выполняется в том же массиве.

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

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

Задание 13.

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

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

3. Описать функцию случайной генерации элементов массива. Задать массив произвольной длины, определяющий коэффициенты многочлена степени N. Описать функцию, которая вычислит и сохранит в новом массиве коэффициенты многочлена, являющегося его производной первой степени. Использовать механизм указателей.

Задание 14.

1. Проинициализировать массив. Описать функции поиска наименьшего, наибольшего элементов массива и функцию выравнивания массива (замена нулем минимального и максимального его элементов).

2. Описать функции ввода и вывода массива. Описать функцию, которая проверит, является ли массив упорядоченным по убыванию. Описать функцию, которая в упорядоченный по убыванию массив включит некоторый элемент b, с сохранением упорядоченности.

3. Описать функцию случайной генерации элементов массива. Локальным минимумом называется любой элемент, который меньше своих соседей. Описать функцию, которая найдет все локальные минимумы, с записью их в новый массив. Использовать механизм указателей.

Задание 15.

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

2. Описать функции ввода и вывода массива. Описать функцию, которая определит, является ли некоторое число простым. Описать функцию, которая удалит из массива все простые числа.

3. Описать функцию случайной генерации элементов массива. Получить два массива одинаковой длины. Описать функцию, которая сложит или вычтет массивы поэлементно с записью в новый массив. Операция (знак '+' или '–') передается в функцию как параметр. Использовать механизм указателей.

Задание 16.

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

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

3. Описать функцию случайной генерации элементов массива. Описать функцию копирования массива. Использовать механизм указателей.

Задание 17.

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

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

3. Описать функцию случайной генерации элементов массива. Получить массив В. Описать функцию, которая сольет некоторый упорядоченный массив А со случайным массивом В, многократно выполняя вставки элементов из массива В в массив А. Использовать механизм указателей.

Задание 18.

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

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

3. Описать функцию случайной генерации элементов массива. Пусть два массива произвольной длины хранят коэффициенты двух многочленов степеней N и M. Описать функцию сложения (вычитания) многочленов, которая получит значения коэффициентов нового многочлена в новом массиве. Характер операции (знак '+' или '–') задать как параметр функции. Использовать механизм указателей.

Задание 19.

1. Проинициализировать массив. Описать функцию, которая определит, образуют ли элементы массива арифметическую прогрессию. Если да, вернуть знаменатель прогрессии, иначе 0. Описать функцию, которая определит, образуют ли элементы массива геометрическую прогрессию. Если да, вернуть знаменатель прогрессии, иначе 1.

2. Описать функции ввода и вывода элементов массива. Описать функцию, которая удалит из массива первый и последний элементы.

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

Задание 20.

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

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

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


Информация

Комментировать статьи на нашем сайте возможно только в течении 60 дней со дня публикации.

Популярные новости

Статистика сайта



Rambler's Top100



 
Copyright © НеОфициальный сайт факультета ЭиП