Методичка Си(2сем)

ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
«ПРИДНЕСТРОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
им. Т. Г. ШЕВЧЕНКО»


ПГУ им. Т.Г.Шевченко
Рыбницкий филиал
Кафедра физики, математики и информатики








программирование
на языке высокого уровня СИ


ЧАСТЬ II

практикум












Рыбница, 2010
УДК 681.3.06
ББК 32.973.2-018
П 78

Программирование на языке высокого уровня СИ. Часть II: практикум/
Сост. О. В. Шестопал, О. В. Сташкова. – Тирасполь, 2010. – 83 с.


Практикум составлен в соответствии с учебной программой по дисциплинам «Программирование на языке высокого уровня» для студентов 1 курса специальности «Программное обеспечение вычислительной техники и автоматизированных систем».
Практикум (II часть) включает в себя 5 лабораторных работ по структурированным типам данных: массивы, строки, перечисляемый и диапазонный типы данных, структуры и объединения, файлы. Особое внимание уделено вопросам программирования рекурсивных алгоритмов. Каждая из лабораторных работ включает теоретический материал, экспериментальный и самостоятельный разделы. Порядок расположения материала соответствует последовательности его изучения.
Основные цели предлагаемого практикума – придать курсу программирования научно-обоснованный базис, сформировать на его основе определенную культуру проектирования и разработки программ.



Рецензенты:
В.Е. Лозовский, учитель высшей категории, директор МОУ «Рыбницкая средняя образовательная школа №6 с лицейскими классами»
А.Б. Глазов, ст. преп. кафедры «ФМИ»



Рекомендовано Научно-методическим советом ПГУ им. Т.Г. Шевченко
Протокол № _______от ____________ 2010 г.


© Составление О.В. Шестопал, О.В.Сташкова, 2010 г.



Содержание


13 TOC \o "1-3" \h \z \u 1413 LINK \l "_Toc250891305" 14Работа 1. ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ В СИ 13 PAGEREF _Toc250891305 \h 1451515
13 LINK \l "_Toc250891306" 14Работа 2. СТРУКТУРИРОВАННЫЙ ТИП ДАННЫХ МАССИВ 13 PAGEREF _Toc250891306 \h 14161515
13 LINK \l "_Toc250891307" 14Работа 3. СИМВОЛЬНЫЙ И СТРОКОВЫЙ ТИПЫ ДАННЫХ 13 PAGEREF _Toc250891307 \h 14321515
13 LINK \l "_Toc250891308" 14Работа 4. СТРУКТУРЫ 13 PAGEREF _Toc250891308 \h 14441515
13 LINK \l "_Toc250891309" 14Работа 5. РАБОТА С ФАЙЛАМИ 13 PAGEREF _Toc250891309 \h 14541515
13 LINK \l "_Toc250891310" 14СПИСОК ЛИТЕРАТУРЫ 13 PAGEREF _Toc250891310 \h 14661515
15


Работа 1. ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ В СИ

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

I. Теоретический раздел работы
1. Функции
Любая Си-программа составляется из "строительных блоков", именуемых функциями. Функция это подпрограмма, которая содержит одну или несколько Си-инструкций и выполняет одну или несколько задач. Хороший стиль программирования на Cи предполагает, что каждая функция выполняет только одну задачу.
Каждая функция имеет имя, которое используется для ее вызова. Своим функциям программист может давать любые имена за исключением имени main (), зарезервированного для функции, с которой начинается выполнение программы.
В Cи ни одна функция не может быть встроена в другую: все функции рассматриваются как отдельные компоненты. (Безусловно, одна функция может вызывать другую.)
Прототип объявляет функцию до ее первого использования.
Общий формат Си-функций

Общий формат Си-функций:

тип_возвращаемого_значения имя (список_параметров)
{
тело функции
}
Рассмотрим подробно все элементы, составляющие функцию.
С помощью элемента тип_возвращаемого_значения указывается тип значения, возвращаемого функцией. Если функция не возвращает никакого значения, необходимо указать тип void. Если функция действительно возвращает значение, оно должно иметь тип, совместимый с указанным в определении функции.
Каждая функция имеет имя. Оно, как нетрудно догадаться, задается элементом имя. После имени функции между круглых скобок указывается список параметров, который представляет собой последовательность пар (состоящих из типа данных и имени), разделенных запятыми. Если функция не имеет параметров, элемент список_параметров отсутствует, т.е. круглые скобки остаются пустыми.
В фигурные скобки заключено тело функции. Тело функции составляют Си-инструкции, которые определяют действия функции. Функция завершается (и управление передается вызывающей процедуре) при достижении закрывающей фигурной скобки или инструкции return.

1.1. Аргументы функций
Функции можно передать одно или несколько значений. Значение, передаваемое функции, называется аргументом. Верхний предел числа принимаемых аргументов определяется конкретным компилятором. Согласно стандарту Cи он равен 256.
Аргумент это значение, передаваемое функции при вызове.
Параметр это определяемая функцией переменная, которая принимает передаваемый функции аргумент.
При создании функции, которая принимает один или несколько аргументов, иногда необходимо объявить переменные, которые будут хранить значения аргументов. Эти переменные называются параметрами функции. Например, следующая функция выводит произведение двух целочисленных аргументов, передаваемых функции при ее вызове.
void mul(int x, int у)
{
cout << x * у << " " ;
}
При каждом вызове функции mul() выполняется умножение значения, переданного параметру х, на значение, переданное параметру у. Однако помните, что х и у это просто переменные, которые принимают значения, передаваемые при вызове функции.
Если вы никогда не работали с языком программирования, в котором разрешены параметризованные функции, описанный процесс может показаться несколько странным. Однако волноваться не стоит: по мере рассмотрения других Си-программ принцип использования функций, их аргументов и параметров станет более понятным.
Примечание. Термин аргумент относится к значению, которое используется при вызове функции. Переменная, которая принимает этот аргумент, называется параметром. Функции, которые принимают аргументы, называются параметризованными функциями.
Если Си-функции имеют два или больше аргументов, то они разделяются запятыми - список аргументов.

1.2.Функции, возвращающие значения.
В Cи многие библиотечные функции возвращают значения. Например, уже знакомая функция abs () возвращает абсолютное значение своего аргумента. Функции, написанные программистом, также могут возвращать значения. В Cи для возврата значения используется инструкция return. Общий формат этой инструкции таков:
return значение;
Нетрудно догадаться, что здесь элемент значение представляет собой значение, возвращаемое функцией.
В более ранних версиях СИ для типов значений, возвращаемых функциями, существовало соглашение, действующее по умолчанию. Если тип возвращаемого функцией значения не указан, предполагалось, что эта функция возвращает целочисленное значение. Несмотря на то, что большинство компиляторов поддерживают это правило ради, обратной совместимости, вы должны явно задавать тип значения, возвращаемого каждой функцией, которую пишете.
При достижении инструкции return функция немедленно завершается, а весь остальной код игнорируется. Функция может содержать несколько инструкций return. Возврат из функции можно обеспечить с помощью инструкции return без указания возвращаемого значения, но такую ее форму допустимо применять только для функций, которые не возвращают никаких значений и объявлены с использованием ключевого слова void.

1.3. Функция main ()
Функция main () специальная, поскольку это первая функция, которая вызывается при выполнении программы. В отличие от некоторых других языков программирования, в которых выполнение всегда начинается "сверху", т.е. с первой строки кода, каждая С++-программа всегда начинается с вызова функции main () независимо от ее расположения в программе. (Все же обычно функцию main () размещают первой, чтобы ее было легко найти.)
В программе может быть только одна функция main (). Если попытаться включить в программу несколько функций main (), она "не будет знать", с какой из них начать работу. В действительности большинство компиляторов легко обнаружат ошибку этого типа и сообщат о ней. Как упоминалось выше, поскольку функция main () встроена в язык СИ, она не требует прототипа.

2. Рекурсия.
Если какую-либо группу операторов необходимо было многократно повторить, то нами использовались операторы цикла. Одна и та же последовательность действий, выполняемая на различных этапах обработки информации, оформлялась нами в виде самостоятельной программной единицы – процедуры или функции. Процедуры и функции позволяют не только сократить объем программы, улучшить ее структуру и наглядность а, следовательно, и понимание, но являются также эффективным средством проектирования программных продуктов. Подпрограммы, записанные однократно в описательной части, могут быть вызваны по имени, как в теле основной программы, так и в других подпрограммах.
В языке С++ существует еще одна уникальная возможность вызова подпрограммой самой себя. Такие процедуры и функции называются рекурсивными. Различают прямую рекурсию, когда подпрограммы обращаются к своему имени в «недрах» себя, и косвенную, когда ссылка на нее идет через цепочку других процедур и функций. В данной работе мы познакомимся с некоторыми простейшими рекурсивными алгоритмами.
С понятием рекурсия тесно связано понятие рекуррентное соотношение (оба слова имеют общий корень от латинского recurro – возвращаться, бежать назад). Запишем в общем виде рекуррентное соотношение порядка к:

f(n) = G (n, f (n - 1),f (n - 2), f (n - k)), (1)

где G – некоторая функция к + 1 аргумента.
Если известны начальные значения f(1), f(2), f(k), то выражение (1) позволяет однозначно определить f(n). Выбрав другие начальные условия, получим тем же способом другую функцию от n, удовлетворяющую (1). Каждая такая функция является решением данного рекуррентного соотношения.
Как правило, программы, записанные в виде рекурсивных процедур и функций отличаются простотой и компактностью записи текста. Рекурсия – мощный инструмент в руках программиста. Однако им необходимо умело пользоваться, знать его сильные и слабые стороны.
Принцип работы рекурсивных подпрограмм подобен работе стека. Прямой ход рекурсии – операция засылки информации в стек (операция Push): Обратный ход рекурсии – последовательное извлечение данных из стека (операция Pop):
В прямом ходе, при очередном вызове подпрограммы-функции все ее локальные переменные, а также параметры, заносятся в специальную область памяти (сегмент стека), причем копии всех обращений временно сохраняются. Число копий, находящихся в памяти, т.е. число рекурсивных вызовов подпрограммы без возврата, называется глубиной рекурсии. В прямом ходе рекурсии это число возрастает. Следует помнить, что размеры стека не бесконечны (по умолчанию, объем стека равен 16 Кбайт), и существует реальная опасность его переполнения. Кроме того, в рекурсивном алгоритме обязательно должно быть условие, гарантирующее завершение цепочки обращений к функции.
При обратном ходе оперативная память, занятая под локальные переменные и параметры функции освобождается, а полученный результат передается в точку возврата – оператор присваивания значений вычисляемой функции.

II. Экспериментальный раздел работы

Пример 1. Вычисление факториала. Факториал числа n! определяет количество способов размещения n предметов в некотором ряду. Так, при n=3 имеется три способа для размещения первого предмета. Если он уже зафиксирован, то существует два способа установки второго предмета и один для третьего. Таким образом, 3!=3*2*1=6. Приведем таблицу для нескольких первых значений факториала: 4!=24; 5!=120; 6!=720; 7!=5040; 8!=40320 Характерной особенностью этой величины является ее экспоненциальное возрастание. При больших значениях n справедлива следующая оценка Стирлинга:
13EMBED Equation.31415. (2)
Некоторые важные свойства факториала можно найти в справочной литературе, а мы подробнее остановимся на рекурсивном алгоритме его вычисления. Запишем факториал в виде
n! = n (n-1)! (3)
В такой записи задача вычисления факториала сводится к ней самой же, путем изменения исходных данных, т.е. «новое» значение n! выражено через «старое» (n-1)!. Кроме того, условие 0! =1 позволяет завершить вычислительный процесс. Составим рекурсивную функцию:

double Factorial(int number)
{
if (number > 1)
return number * Factorial(number - 1);
return 1;
}
13 INCLUDEPICTURE \d "http://0" \* MERGEFORMATINET 1415
Рис 1. Рекурсивные вызовы функции для выражения factorial(5).
Пример 2. Алгоритм Евклида. Построим рекурсивные алгоритмы вычисления наибольшего общего делителя НОД (n,m) двух целых чисел n и m. Говорят, что два целых числа делятся (или n кратно m), если n=k*m, где k – целое число. Наибольший общий делитель – это максимальное значение числа k, которое делит и n и m. Например,

НОД (39, 15)=3, НОД (18, 12)=6.

Геометрическая трактовка НОД (n, m) – это набольшая общая мера двух соизмеримых отрезков, т.е. отрезков, каждый из которых в n и m-раз соответственно длиннее, чем некоторый выбранный отрезок - масштаб. Такая геометрическая иллюстрация НОД подсказывает простейший, буквально следующий определению, алгоритм его нахождения. Действительно, выберем из двух отрезков наименьший и проверим, не укладывается ли он целое число раз в другом. Если да, то цель достигнута. Если нет, то возьмем половину меньшего отрезка и проверим, не укладывается ли он целое число раз в другом. В случае неудачи перейдем к трети отрезка и т.д. Условие соизмеримости отрезков гарантирует успешное окончание этого процесса. Представим описанный алгоритм в виде подпрограммы-функции
int Nod(int n,int m)
{
int i,k,rez;
if(n>m) k=m;
else k=n;
for(i=1;i<=k;i++){
if((m%i==0)&&(n%i==0)) rez=i;}
return rez;
}
Нетрудно заметить, что такой алгоритм неэффективен, поскольку предполагает выполнение многих лишних действий по перебору нужного варианта (при n>m необходимо выполнить m - действий). Существенно более выгодным является метод, предложенный Евклидом более 2300 лет назад. Рассмотрим две его трактовки в связи с возможностью их рекурсивной реализации. Алгоритм Евклида строится, опираясь на свойства наибольшего общего делителя. Сформулируем их:

1. НОД (n, m) = НОД (-n, m) = НОД (n,-m);
2. НОД (n, m) = НОД (n - m, m) = НОД (n, m - n);
3. НОД (n, 0) = n, при n 13 EMBED Equation.3 14150;
4. НОД (n, m) = НОД ( m, n mod m);

В записи этих свойств уже заложена рекурсивная трактовка. Рассмотрим сначала более подробно свойства 3 и 4. Пусть a0 = n, а1= m. Основываясь на указанных свойствах можно сформировать последовательность остатков от деления а2, а3,, используя рекуррентное соотношение

13 EMBED Equation.3 1415 (4)
Продолжая этот процесс до тех пор, пока an+1 =0, получим

НОД (a0,a1) = НОД (a1,a2) = = НОД (an,0) = an (5)
Данную последовательность можно записать в более привычном виде:













где qk - целые числа.
Например,
НОД (39,15) = НОД (15,9) = НОД (9,6) = НОД (6,3) = НОД (3,0) = 3

Действительно, разложив на множители эти числа 39 = 3*13 и 15 = 3*5, получим
НОД (39,15)= 3.
Поскольку нет необходимости запоминать промежуточные результаты и, следовательно, вводить массив целых чисел, запишем алгоритм Евклида так:

1. Ввод исходных данных: n,m;
2. Повторить r = n mod m; n = m; m = r пока r = 0;
3. Вывод результата: НОД (n,m) = n.

Составим подпрограмму-функцию:
int Nod_2(int n,int m)
{
int r=n%m;
if(r==0) return m;
else return Nod_2 (m,r);
}
Составьте подпрограммы вычисления НОД на основе свойств 1 и 2.
Настоятельно рекомендуется поэкспериментировать с приведенными функциями, сравнить их по количеству действий, эффективности действий, наглядности и т.д.

Пример 3. Решение нелинейных уравнений. Рассмотрим задачу нахождения корней нелинейного уравнения

f(x)=0 (6)
Алгоритм нахождения корней приближенными методами можно разбить на два этапа. На первом – изучается расположение корней и проводится их разделение. Находится область [a,b], в которой существует корень уравнения или начальное приближение к корню x0. Простейший способ выделения корней – табуляция функции и анализ ее графика.
Существование на найденном отрезке [a,b], по крайней мере, одного корня уравнения (6) следует из условия, что знаки функций на концах отрезка различны:

f(a)
· f(b) < 0 (7)
При этом подразумевается, что функция f(x) непрерывна и монотонна на данном отрезке
На втором этапе решения, используя полученное начальное приближение, стоится итерационный процесс, позволяющий уточнять значение корня с некоторой, наперед заданной точностью 13 EMBED Equation.3 1415.

13 EMBED Equation.3 1415 (8)
Рассмотрим простейший метод уточнения значения корня с заданной точностью 13 EMBED Equation.3 1415 - метод деления отрезка пополам. Если определен интервал нахождения корня [a,b], то этот алгоритм состоит из:
1. Задания значений величин 13 EMBED Equation.3 1415 и вычисления значений функции u=f(a), v:=f(b).
2. Последовательно выбранный отрезок делится пополам и осуществляется выбор того из двух отрезков, на котором функция меняет знак.
3. Вычисление заканчивается, если выполнено условие (8), иначе возврат к шагу 2.
Приведем рекурсивный вариант программы-функции, реализующей описанный метод:

double X_Dich(double a, double b, double eps){
double x;
if (f(a)*f(b)> 0.0) {cout<<”error”};exit;}
else
{ x=0.5*(a+b);
if (abs(f(x)) > eps)
{ if (f(a)*f(x) <0.0)
Return X_Dich(a,x,eps);
Else Return X_Dich(x,b,eps);
Return x;
}
}
Изучите приведенный алгоритм, проведите отладку программы и сделайте её тестирование. В качестве теста используйте любое уравнение с известным решением. В частности, можно рекомендовать уравнение Валлиса 13 EMBED Equation.3 1415, имеющего один вещественный корень 2.09455.
Полезно в своей библиотеке иметь не только подпрограммы-функции, но и процедуры, составленные на основе приведенных алгоритмов. Напишите их, выполните отладку и тестирование. Составьте подпрограммы с использованием рекурсии и без нее.
Выбор очередной точки в середине отрезка не является единственным вариантом. Можно в качестве такой точки выбрать случайное число, заменив оператор x:=0.5*(a+b) на x:=a+(b-a)*random, предварительно инициализируя датчик случайных чисел Randomize. Проведите соответствующие расчеты и сравните требуемое число итераций для достижения заданной точности.
Более совершенный метод выбора точки деления отрезка [a,b] – метод хорд, в котором в качестве x выбирается точка пересечения с осью абсцисс прямой y=Ax+B (хорды), проведенной через концы интервала u=f(a) и v=f(b).
13 EMBED Equation.3 1415, где 13 EMBED Equation.3 1415. (9)
Сделайте корректировку программы и проведите вычислительный эксперимент, сравнивая число итераций, требуемых для достижения заданной точности.
Определите количество итераций разных методов, требуемых для достижения точности 13 EMBED Equation.3 1415.


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

Пример 5. Рассмотрим рекуррентную числовую последовательность Фибоначчи, играющую важную роль в математике:

f(0) = 0; f (1) = 1
f (n) = f (n-1) + f (n-2), (12)

Запишем несколько первых значений последовательности чисел Фибоначчи:
f(2)=1; f(3)=2; f(4)=3; f(5)=5; f(6)=8; f(7)=13;..
Простейшее рекуррентное соотношение второго порядка (12), в котором каждое следующее значение вычисляется по двум предыдущим, может быть естественным образом реализовано в виде рекурсивной функции:


int Fib(int n){
if (n= = Ш) return Ш;
if (n = = 1) return 1;
else return Fib(n – 2) + Fib(n-1)
}
Приведем не рекурсивный вариант решения данной задачи:

int Fib(int n){
int i,j,k,m;
m=Ш; k=1;
for(i=2; i<=n; i++){
j=k;
k+=m;
m=j;
end;
return k;
}
Сравнение этих подпрограмм показывает, что рекурсивный вариант организован не лучшим образом, он менее экономичен по числу обращений к функции. Это и понятно, вычисление слагаемого f(n) требует ссылки на f(n-1) и f(n-2). А вычисление слагаемого f(n-1), в свою очередь, на f(n-2) и f(n-3), т.е. происходит два независимых вычисления f(n-2). Это можно проиллюстрировать в виде следующего дерева графа для n = 4:

4


3 2
1 0

2 1

Из девяти вызовов функции f(n) - четыре сделаны повторно. Это неэффективно.
Приведем аналитическое решение рекуррентного соотношения (6):

13 EMBED Equation.3 1415 (13)
Нетрудно показать, что вычисление по рекурсивному алгоритму требует 13 EMBED Equation.3 1415 обращений к функции, в отличие от N1 = (n – 2) обращений во второй программе, использующей цикл. Зависимость N1 от n - линейная, а N2 от n - показательная с основанием 13 EMBED Equation.3 1415, т.е. 13 EMBED Equation.3 1415.
Данный пример показывает неудачное применение рекурсии и указывает на необходимость тщательного анализа используемых алгоритмов. Красиво не всегда означает эффективно. Кстати и циклические вычисления не застрахованы от плохой реализации, где могут, например, повторяться уже проделанные операции. Но, как правило, итерационные алгоритмы более прозрачны с точки зрения их анализа, в отличие от рекурсивных, где заметить дефекты бывает значительно труднее. Несмотря на сказанное, рекурсия это мощный инструментарий, позволяющий легко реализовывать многие сложные алгоритмы. Но об этом еще разговор впереди, а сейчас нужно освоить простейшие навыки составления рекурсивных подпрограмм.

III. Задания для самостоятельной работы

A.
1. Вычислить числа Фибоначчи второго порядка:
u0 =1; u1 =2; u2 =3
un = un-1 + un-2 + un-3 , при n=3, 4,
2. Написать рекурсивную функцию для вычисления значения так называемой функции Аккермана для неотрицательных чисел n и m. Функция Аккермана определяется следующим образом:
13 EMBED Equation.3 1415
3. Вычислить рекурсивно функцию:

n –10, если n>100
F(n)= F(F(n+4)), если n<100


4. Вычислить рекурсивно функцию :

1, если n=1
S(n) S(n/2), если n=2k
S((3n+1)/2), если n=2k+1

5. Написать рекурсивную и нерекурсивную функции вычисления биномиальных коэффициентов:

C(n,0) = C(n,n) = 1
C(m,n) = C(m,n-1) + C(m-1,n-1) при 0 < m < n
6. Написать рекурсивную и нерекурсивную функции для разностного уравнения
А(0) = 1
A(n) = A(ndiv2)+A(ndiv3)
7. Написать рекурсивную функцию:
а) вычисления суммы цифр натурального числа;
б) вычисления количества цифр натурального числа.
8. Даны первый член и разность арифметической прогрессии. Написать рекурсивную функцию для нахождения:
а) n-го члена прогрессии;
б) суммы n первых членов прогрессии.
9. Даны первый член и знаменатель геометрической прогрессии. Написать рекурсивную функцию:
а) нахождения ее n-го члена;
б) нахождения суммы n первых членов прогрессии.
B.
1. Вычислить рекурсивно полином Лежандра порядке n:

P0(x) = 1; P1(x) = x;
Pn(x)=((2n-1)Pn-1(x) - (n-1)Pn-2(x)/n

2. Написать рекурсивную и не рекурсивную функции вычисления полинома Чебышева первого ряда:

T0(x)=1; T1(x)=x
Tn(x)=2xTn-1(x) – Tn-2(x)
Сравнить число операций.
3. Написать рекурсивную и не рекурсивную функции вычисления полинома:

H0(x)=1; H1(x)=x
Hn(x)=xHn-1(x) –(n-2)Hn-2(x)
Сравнить число операций.
4. Написать рекурсивную и не рекурсивную функции вычисления полинома:

G0(x)=1; G1(x)=x-1
Gn(x)=(x-2n+1)Gn-1(x) –(n-1)2Gn-2(x)
Сравнить число операций.
5. Написать рекурсивную и не рекурсивную функции вычисления полинома:

L0(x)=1; L1(x)=x
13EMBED Equation.31415
Сравнить число операций.
6. Написать рекурсивную и не рекурсивную функции вычисления полинома Эрмита

H0(x)=1; H1(x)=2x
Hn(x)=2xHn(x) – 2nHn-1(x)
7. Написать рекурсивную и не рекурсивную функции вычисления полинома Лагерра:
13EMBED Equation.31415, n=1,2,
L0(x)=1; L1(x)=1-x.
8. Вычислить рекурсивно и нерекурсивно:
13 EMBED Equation.3 1415,
где
k!! = 1*3*5*k, если k – нечетно
k!! = 2*4*6*k, если k - четно
9. Вычислить, используя рекурсию и без нее:

а) 13EMBED Equation.31415;
б) 13EMBED Equation.31415 ;
в) 13EMBED Equation.31415;
г) 13EMBED Equation.31415;
д) 13EMBED Equation.31415;
е) 13EMBED Equation.31415

C.
1. Используя команды write(x) лишь при х=0,1,9 написать рекурсивную процедуру вывода на экран десятичной записи натурального числа n.
2. Используя команды write(x) лишь при х=0,1 написать рекурсивную процедуру вывода на экран двоичной записи натурального числа n.
3. Используя команды write(x) лишь при х=0,1,9 написать рекурсивную процедуру вывода на экран восьмеричной записи натурального числа n.
4.Написать рекурсивную и нерекурсивную функции возведения вещественного числа х в натуральную степень n.
5. Цифровой корень натурального числа находится через сумму цифр этого числа до тех пор, пока эта сумма не станет цифрой. Написать рекурсивную функцию нахождения цифрового корня натурального числа.
6. Написать рекурсивную процедуру перевода числа из десятичной системы в N –ю
(2<= N <= 16).
7. Составить рекурсивную функцию нахождения суммы первых n членов арифметической и геометрической прогрессий.
8. Составить рекурсивную процедуру нахождения максимального элемента в массиве.
9. Написать рекурсивный алгоритм головоломки «ханойская башня».
10. Написать рекурсивный алгоритм перевода из двоичной системы счисления в десятичную ( из восьмеричной и шестнадцатеричной в десятичную).
11. Написать рекурсивный алгоритм представления натурального числа в римском исчислении.
12. Написать рекурсивную процедуру для вывода на экран цифр натурального числа в обратном порядке.
13. Написать рекурсивную процедуру перевода натурального числа из десятичной системы счисления в N-ичную. Значение N в основной программе вводится с клавиатуры (2 13 EMBED Equation.3 1415 N13 EMBED Equation.3 1415 1б).
14. Написать рекурсивную функцию, определяющую, является ли заданное натуральное число простым (простым называется натуральное число, большее 1, не имеющее других делителей, кроме единицы и самого себя).
Работа 2. СТРУКТУРИРОВАННЫЙ ТИП ДАННЫХ МАССИВ

Цель работы:
– изучить способы задания массивов;
– изучить способы передачи массивов в качестве параметров подпрограмм;
– получить навыки хранения и обработки большого количества данных.

I. Теоретический раздел работы
1.1. Структурированный тип данных массив
Часто возникает необходимость хранить не одну переменную, а набор однотипных переменных. Например, список учащихся класса – это набор данных строкового типа, координаты вершин многоугольника или коэффициенты многочлена – это набор числовых данных. Для хранения наборов данных используются структуры данных. Основная структура данных – это массив.
Массив  это структура однотипных данных, занимающих непрерывную область памяти. Массив имеет размер  количество элементов в нем. Каждый элемент массива имеет свой номер (также называемый индексом), обращение к элементу массива осуществляется путем указания его индекса. В языке Cи элементы нумеруются начиная с 0, поэтому последний элемент массива имеет номер на 1 меньше размера массива.
Массив в языке Cи задается следующим образом:
тип_элементов идентификатор[размер];
где тип_элементов  произвольный тип данных языка Cи, который будут иметь элементы массива, например, int, double и т.д.; идентификатор  имя массива, размер  число элементов в нем.
К элементу массива можно обращаться, как идентификатор[индекс]. Например, если было сделано объявление
double A[5];
то таким образом создается 5 элементов массива типа double: A[0], A[1], A[2], A[3], A[4].
Как уже известно, имя массива является константным указателем. Именно поэтому и невозможно копирование массивов с помощью простого оператора присвоения. Константный указатель "охраняет" область памяти, выделенную для размещения данного массива. При этом значения элементов массива можно изменять в ходе выполнения программы. Защитить их от изменения можно с помощью дополнительного спецификатора типа const. При этом массив должен быть проинициализирован непосредственно в момент определения:
const int cIntArray[] = {0,1,2,3,4,5,6,7,8,9};
Это аналог константного указателя на массив констант. Попытки изменения значения элементов массива пресекаются на этапе компиляции.
cIntArray[5] = 111; // Ошибка.

1.2. Передача массива в качестве параметра
Массивы можно передавать функции в качестве параметра. Но при этом размер создаваемого массива может быть неопределен на момент компиляции программы, поэтому функция не может знать размер полученного массива. Поэтому при объявлении функции необходимо задавать два параметра: массив передаваемых элемента (без указания размера массива) и размер массива. Например, функция поиска наименьшего значения в массиве int A[n] может быть объявлена так:
double Min (int A[], int n)
Соответственно, внутри функции main должен быть объявляем массив int A[n] и вызываем функцию Min, передав в качестве параметров массив A и его размер n: Min(A,n);

1.3. Многомерные массивы
Объявление int A[n] создает в памяти одномерный массив: набор пронумерованных элементов, идущих в памяти последовательно. Но можно создать и массив массивов следующим образом: int A[n][m]. Данное объявление создает массив из n объектов, каждый из которых в свою очередь является массивом типа int [m]. Тогда A[i], где i принимает значения от 0 до n-1 будет в свою очередь одним из n созданных обычных массивов, и обратиться к элементу с номером j в этом массиве можно через A[i][j].
Подобные объекты (массивы массивов) также называют двумерными массивами. Двумерные массивы можно представлять в виде квадратной таблицы, в которой первый индекс элемента означает номер строки, а второй индекс – номер столбца. Например, массив A[3][4] будет состоять из 12 элементов и его можно записать в виде
A[0][0] A[0][1] A[0][2] A[0][3]
A[1][0] A[1][1] A[1][2] A[1][3]
A[2][0] A[2][1] A[2][2] A[2][3]
Можно объявлять не только двумерные массивы, но и массивы с большим количеством измерений. Например, объявление int A[n][m][l] создает трехмерный массив из n*m*l элементов. Для обращения к каждому элементу такого массива необходимо указать три индекса: A[i][j][k], при этом 0<=i, i
II. Экспериментальный раздел

Пример 1. Составим процедуры ввода и вывода данных. Пусть покупается n разных товаров. Известна цена ci и количество mi каждого товара. Требуется вычислить общую стоимость приобретенного товара.
#include ;
#include ;
#include ;
#include ;
#include ;
const NomEl = 100;
double* c1;
int* k1;

int Data(double* &c, int* &k);
void Print(double* c, int* k,int n);
void Sum(double* c,int* k,int n, double& s1, int& s2);

/*Основная программа*/
void main(void)
{ int s2; double s1; int n;
n = Data(c1,k1);
Print(c1,k1,n);
Sum(c1,k1,n,s1,s2);
cout< getch();
}
/*подпрограмма ввода массива */
int Data(double* &c, int* &k)
{ char text1[60]=" вводите последовательно цену и количество товара";
char text2[60]="Отрицательное значение одной из этих величин – конец покупок!";
int i;
cout< c = new double[NomEl];
k = new int[NomEl];
do { i++;
cout<>c[i];
cout<<"kolichestvo=?"; cin>>k[i];
} while ((c[i]>0.0)&&(k[i]>0));
return i-1;
}
/*подпрограмма вывода массива */
void Print(double* c, int* k,int n)
{
char txt1[20]="----------------";
char txt2[20]=" N cena kol-vo";
int i;
cout<for (i=1; i<=n; i++)
{
cout< }
cout<};
/* подпрограмма суммирования данных*/
void Sum(double* c,int* k,int n, double& s1, int& s2)
{ int i;
s1=0.0; s2=0;
for (i=1; i<=n;)
{
s1=s1+c[i]*k[i]; s2=s2+k[i];i++;
}
};

Теперь дополним нашу программу процедурами вставки и удаления элементов в массиве. Для осуществления вставки числа z1 в массив z[i] после номера k необходимо:
первые k элементов сохранить без изменения;
все элементы массива, начиная с (k+1) – сдвинуть вправо;
на место элемента (k+1) записать число z1.
/* подпрограмма вставки элемента*/
void Insert(int k,int m1,double z1, double* z, int* m, int &n)
{int i;
for (i=n; i>=k+1; i--)
{ z[i+1]=z[i]; m[i+1]=m[i];}
z[k+1]=z1; m[k+1]=m1; n=n+1;
};

Здесь k – номер элемента, после которого необходимо вставить числа:
m1 – количество товара, которое добавляется и
z1- его цена.
Аналогично составим процедуру удаления элемента с номером k из массива, при этом все элементы, начиная с номера k, необходимо сдвинуть влево.
/* подпрограмма удаления элемента*/
void Delete(int k, double* z, int* m, int &n)
{ int i;
n=n-1;
for (i=k; i<=n;i++)
{
z[i]=z[i+1]; m[i]=m[i+1];
}
};

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

#include ;
#include ;
#include ;
#include ;
#include ·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
/*Основная программа*/
void main(void)
{ int s2; double s1,ci; int n,j,mi;

n = Data(c1,k1);
Print(c1,k1,n);
Sum(c1,k1,n,s1,s2);
cout< cout<>ci;
cout<<"количество=?"; cin>>mi;
Insert(j,mi,ci,c1,k1,n);
Print(c1,k1,n);
Sum(c1,k1,n,s1,s2);
cout< cout<>j;
Delete(j,c1,k1,n);
Print(c1,k1,n);
Sum(c1,k1,n,s1,s2);
cout< getch();
}

Заметим, что также можно организовать и процедуру обмена элементами в массиве.
void Swap(double a,b);
{ double z;
z=a; a=b; b=z
};
И, при необходимости, вызывать ее в основной программе: Swap(c[k1],c[k2]);

Пример 2. Составим программу транспонирования матриц, вычисления произведения двух квадратных матриц
13 EMBED Equation.3 1415
и преобразования двухмерной матрицы в одномерную. Пусть элементы исходных матриц a и b задаются с помощью датчика случайных чисел.
Program Example_102;
#include ;
#include ;
#include ;
#include ;
typedef int matr[5,5];
typedef int vectr[25];
void Data(matr t);
void Print(matr t);
void Tp(matr t);
/*Основная программа*/
void main(void)
{
randomize();
matr a,b,c;
vectr d;
cout<<"massiv a";
Data(a);
Print(a);
Tp(a);
Print(a);
cout<<"massiv b"; Data(b); Print(b);
Tp(b);
Print(b);
Dv(a,b,c);
cout<<"massiv c";
Print(c);
Tr(c,d);
getch();
}
/*подпрограмма ввода массива */
void Data(matr t)
{ int i,j;
for (i=1; i<=5; i++)
for (j=1; j<=5; j++)
t[i,j]=random(21)-10;
};
/*подпрограмма вывода массива */
void Print(matr t)
{int i,j;
cout<<"\n";
for (i=1; i<=5; i++)
{
for (j=1; j<=5; j++)
cout< cout<<"\n";
}
}

/*подпрограмма транспонирования матрицы */
void Tp(matr t)
{
int i,j,n,p;
n=5;
for (i=1; i<=n-1; i++)
for (j=i+1; j<=n; j++)
{
p=t[i,j];
t[i,j]=t[j,i];
t[j,i]=p;
}
// return t;
};

/* подпрограмма преобразования двумерной матрицы в одномерную*/
void Tr(matr x ;vectr z)
{

int i,j,n,k;
n=5;
for (i=1; i<= n; i++)
{
for (j=1; j<= n; j++)
{
k=(i-1)*n+j; z[k]=x[i,j] ; cin>>z[k];
};
getch();
}
};

/*подпрограмма переyмножения двух матриц*/
void Dv(matr x,y, z)
{int i,j,k;
for (i=1; i<=nn; i++)
for (j=1; j<=nn; j++)
{ s=0;
for (k=1; k<= nn; k++)
s=s+x[i,k]*y[k,j] ; z[i,j]=s
}
geth()
}

Проведите отладку и тестирование программы. Дополните её процедурами вычисления определителей и обращения матриц.

Пример 3. Разработаем программу решения системы из трех линейных уравнений методом Крамера.

#include ;
#include ;
#include ;
#include ;
typedef double vectr[n];
typedef double matr[n,n+1];
void Data(matr a);
void Print(matr a);
void Swap(double a,b);
double Det(matr a);
/*вычисление определителя*/
double Turn(int k);
void Solve_Kram(matr a; double x);
/* подпрограмма, реализующая метод Крамера

/*Основная программа*/
void main(void)
{ int I; matr a; vectr z; int n=3;
Data(a); Print(a); Solve_Kram(a,z);
for (I=1; I<= n; I++) cout<<[“<<=’< getch();
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·
·Разобравшись с приведенным текстом программ, проведите их отладку и тестирование. Поэкспериментировав с программой, проведите её улучшения по части сервиса и т.д.

III. Задания для самостоятельной работы.
A.
Разобрать демонстрационные примеры, ввести их в компьютер, провести тестовые расчеты. Выписать, какие параметры в программах являются формальные, какие фактическими, локальные и глобальные, параметры-переменные, а какие параметры-значения.
Составить подпрограмму нахождения суммы элементов массива, созданного с помощью датчика случайных чисел, кратных данному числу. Вычислить количество положительных и отрицательных элементов в данном массиве.
Составить подпрограмму нахождения всех отрицательных номеров случайным образом сформированного массива. Составить из этих данных новый массив, используя принцип “массива-маски”.
Сформировать с помощью датчика случайных чисел два массива. Найти среднее арифметическое каждого и сравнить эти значения.
Предполагая, что в массиве из случайных чисел максимальный элемент встречается несколько раз, составить подпрограмму их удаления.
Написать подпрограмму, в которой вставляется число после всех элементов массива, кратных трем.
Составить подпрограмму, в которой вставляется по одному элементу перед всеми отрицательными членами.
В одномерном массиве поменять местами первую и вторую его половины.
Составить процедуру нахождения количества элементов в каждой строке двумерного массива, больших среднего арифметического элементов данной строки.
Даны два двумерных массива одинаковой размерности. Создать третий массив той же размерности, каждый элемент, которого равен сумме соответствующих элементов первых двух.
Даны два двумерных массива одинаковой размерности. Создать третий массив той же размерности, где каждый элемент равен 1, если соответствующие элементы исходных матриц имеют одинаковый знак, иначе элемент равен 0.
Дано целое число N (> 0). Сформировать и вывести целочисленный массив размера N, содержащий N первых положительных нечетных чисел: 1, 3, 5,  .
Дано целое число N (> 0). Сформировать и вывести целочисленный массив размера N, содержащий степени двойки от первой до N-й: 2, 4, 8, 16,  .
Дано целое число N (> 1), а также первый член A и разность D арифметической прогрессии. Сформировать и вывести массив размера N, содержащий N первых членов данной прогрессии: A,    A + D,    A + 2·D,    A + 3·D,     .
Дано целое число N (> 1), а также первый член A и знаменатель D геометрической прогрессии. Сформировать и вывести массив размера N, содержащий N первых членов данной прогрессии: A,    A·D,    A·D2,    A·D3,     .
Дано целое число N (> 2). Сформировать и вывести целочисленный массив размера N, содержащий N первых элементов последовательности чисел Фибоначчи FK: F1 = 1,        F2 = 1,        FK = FK–2 + FK–1,    K = 3, 4,  .
Даны целые числа N (> 2), A и B. Сформировать и вывести целочисленный массив размера N, первый элемент которого равен A, второй равен B, а каждый последующий элемент равен сумме всех предыдущих.
Дан массив размера N. Вывести его элементы в обратном порядке.
Дан целочисленный массив размера N. Увеличить все четные числа, содержащиеся в массиве, на исходное значение первого четного числа. Если четные числа в массиве отсутствуют, то оставить массив без изменений.
Дан целочисленный массив размера N. Увеличить все нечетные числа, содержащиеся в массиве, на исходное значение последнего нечетного числа. Если нечетные числа в массиве отсутствуют, то оставить массив без изменений.
Дан массив размера N. Поменять местами его минимальный и максимальный элементы.
Дан массив размера N (N  четное число). Поменять местами его первый элемент со вторым, третий  с четвертым и т. д.
Дан массив размера N (N  четное число). Поменять местами первую и вторую половины массива.
Дан массив A размера N и целое число K (1 
· K 
· N). Преобразовать массив, увеличив каждый его элемент на исходное значение элемента AK.
Дан целочисленный массив размера N. Вывести все содержащиеся в данном массиве нечетные числа в порядке возрастания их индексов, а также их количество K.
Дан целочисленный массив размера N. Вывести все содержащиеся в данном массиве четные числа в порядке убывания их индексов, а также их количество K.
Дан целочисленный массив размера N. Вывести вначале все содержащиеся в данном массиве четные числа в порядке возрастания их индексов, а затем  все нечетные числа в порядке убывания их индексов.
Дан массив A размера N и целое число K (1 
· K 
· N). Вывести элементы массива с порядковыми номерами, кратными K: AK, A2·K, A3·K,  . Условный оператор не использовать.
Дан массив A размера N (N  четное число). Вывести его элементы с четными номерами в порядке возрастания номеров: A2, A4, A6, , AN. Условный оператор не использовать.
Дан массив A размера N (N  нечетное число). Вывести его элементы с нечетными номерами в порядке убывания номеров: AN, AN–2, AN–4, , A1. Условный оператор не использовать.
Дан массив A размера N. Вывести вначале его элементы с четными номерами (в порядке возрастания номеров), а затем  элементы с нечетными номерами (также в порядке возрастания номеров): A2,    A4,    A6,    ,    A1,    A3,    A5,     . Условный оператор не использовать.
Дан массив A размера N. Вывести вначале его элементы с нечетными номерами в порядке возрастания номеров, а затем  элементы с четными номерами в порядке убывания номеров: A1,    A3,    A5,    ,    A6,    A4,    A2. Условный оператор не использовать.
Дан массив A размера N. Вывести его элементы в следующем порядке: A1,    AN,    A2,    AN–1,    A3,    AN–2,     .
Дан массив A размера N. Вывести его элементы в следующем порядке: A1,    A2,    AN,    AN–1,    A3,    A4,    AN–2,    AN–3,     .
Дан массив A ненулевых целых чисел размера 10. Вывести значение первого из тех его элементов AK, которые удовлетворяют неравенству AK < A10. Если таких элементов нет, то вывести 0.
Дан целочисленный массив A размера 10. Вывести порядковый номер последнего из тех его элементов AK, которые удовлетворяют двойному неравенству A1 < AK < A10. Если таких элементов нет, то вывести 0.
Дан массив размера N и целые числа K и L (1 
· K 
· L 
· N). Найти сумму элементов массива с номерами от K до L включительно.
Дан массив размера N и целые числа K и L (1 
· K 
· L 
· N). Найти среднее арифметическое элементов массива с номерами от K до L включительно.
Дан массив размера N и целые числа K и L (1 < K 
· L 
· N). Найти сумму всех элементов массива, кроме элементов с номерами от K до L включительно.
Дан массив размера N и целые числа K и L (1 < K 
· L 
· N). Найти среднее арифметическое всех элементов массива, кроме элементов с номерами от K до L включительно.
Дан целочисленный массив размера N, не содержащий одинаковых чисел. Проверить, образуют ли его элементы арифметическую прогрессию (см. задание Array3). Если образуют, то вывести разность прогрессии, если нет  вывести 0.
Дан массив ненулевых целых чисел размера N. Проверить, образуют ли его элементы геометрическую прогрессию (см. задание Array4). Если образуют, то вывести знаменатель прогрессии, если нет  вывести 0.
Дан целочисленный массив размера N. Проверить, чередуются ли в нем четные и нечетные числа. Если чередуются, то вывести 0, если нет, то вывести порядковый номер первого элемента, нарушающего закономерность.
Дан массив ненулевых целых чисел размера N. Проверить, чередуются ли в нем положительные и отрицательные числа. Если чередуются, то вывести 0, если нет, то вывести порядковый номер первого элемента, нарушающего закономерность.
Дан массив A размера N. Найти минимальный элемент из его элементов с четными номерами: A2, A4, A6,  .
Дан массив A размера N. Найти максимальный элемент из его элементов с нечетными номерами: A1, A3, A5,  .
Дан массив размера N и целые числа K и L (1 
· K < L 
· N). Удалить из массива элементы с номерами от K до L включительно и вывести размер полученного массива и его содержимое.
Дан целочисленный массив размера N. Удалить из массива все нечетные числа и вывести размер полученного массива и его содержимое.
Дан целочисленный массив размера N (> 2). Удалить из массива все элементы с четными номерами (2, 4, ). Условный оператор не использовать.
Дан целочисленный массив размера N (> 2). Удалить из массива все элементы с нечетными номерами (1, 3, ). Условный оператор не использовать.
Дан целочисленный массив размера N. Удалить из массива все соседние одинаковые элементы, оставив их первые вхождения.
Дан целочисленный массив размера N. Удалить из массива все одинаковые элементы, оставив их первые вхождения.
Дан целочисленный массив размера N. Удалить из массива все одинаковые элементы, оставив их последние вхождения.
Дан целочисленный массив размера N. Удалить из массива все элементы, встречающиеся менее трех раз, и вывести размер полученного массива и его содержимое.
Дан целочисленный массив размера N. Удалить из массива все элементы, встречающиеся более двух раз, и вывести размер полученного массива и его содержимое.
Дан целочисленный массив размера N. Удалить из массива все элементы, встречающиеся ровно два раза, и вывести размер полученного массива и его содержимое.
Дан массив размера N и целое число K (1 
· K 
· N). Перед элементом массива с порядковым номером K вставить новый элемент с нулевым значением.
Дан массив размера N и целое число K (1 
· K 
· N). После элемента массива с порядковым номером K вставить новый элемент с нулевым значением.
Дан массив размера N. Вставить элемент с нулевым значением перед минимальным и после максимального элемента массива.
Дан массив размера N и два целых числа K и M (1 
· K 
· N, 1 
· M 
· 10). Перед элементом массива с номером K вставить M новых элементов с нулевыми значениями.
Дан массив размера N и два целых числа K и M (1 
· K 
· N, 1 
· M 
· 10). После элемента массива с номером K вставить M новых элементов с нулевыми значениями.
Дан массив размера N. Продублировать в нем элементы с четными номерами (2, 4, ). Условный оператор не использовать.
Дан массив размера N. Утроить в нем вхождения всех элементов с нечетными номерами (1, 3, ). Условный оператор не использовать.
Дан массив размера N. Перед каждым положительным элементом массива вставить элемент с нулевым значением.
Дан массив размера N. После каждого отрицательного элемента массива вставить элемент с нулевым значением.
Дан целочисленный массив размера N. Продублировать в нем все четные числа.
Дан целочисленный массив размера N. Утроить в нем вхождения всех нечетных чисел.

B.
Составить два массива из n членов геометрической прогрессии с одинаковым первым слагаемым, но разными знаменателями. Найти и проанализировать их скалярное произведение.
В подпрограмме вставить число А перед всеми элементами, большими А, а число В – после элементов, меньших его.
В одномерном массиве переставить в обратном порядке его элементы, расположенные между минимальным и максимальным элементами. Вычисления оформить в виде процедуры.
Вычислить сумму элементов главной диагонали случайным образом сформированной двумерной матрицы. Сравнить эти данные для трех матриц.
Составить подпрограмму заполнения и вывода на экран таблицы умножения Пифагора.
Составить подпрограмму вывода на экран арифметического квадрата, в нем первый столбец и первая строка заполнены 1, а каждый из остальных элементов равен сумме своих соседей сверху и слева.
Составить подпрограмму вывода на экран арифметического квадрата, в нем первый столбец и первая строка заполнены 1, а каждый из остальных элементов равен сумме своих соседей сверху и слева.
Вставить нулевую строку и нулевой столбец перед строкой и столбцом, где находиться минимальный элемент.
Удалить строку с номером i и столбец с номером j .
Удалить все строки и столбцы, на пересечении которых стоят отрицательные элементы.
Поменять местами максимальный и минимальный элементы двумерного массива.
В двумерном массиве переставить строки следующим образом: первую с последней, вторую - с предпоследней и так далее.
Дан двумерный массив. Начиная с первой строки, сдвинуть все строки на две вниз, а последние две перенести на место первых двух строк.
Даны массивы A и B одинакового размера N. Поменять местами их содержимое и вывести вначале элементы преобразованного массива A, а затем  элементы преобразованного массива B.
Дан массив размера N. Найти номера тех элементов массива, которые больше своего правого соседа, и количество таких элементов. Найденные номера выводить в порядке их возрастания.
Дан массив размера N. Найти номера тех элементов массива, которые больше своего левого соседа, и количество таких элементов. Найденные номера выводить в порядке их убывания.
Дан массив размера N. Найти номер его первого локального минимума (локальный минимум  это элемент, который меньше любого из своих соседей).
Дан массив размера N. Найти номер его последнего локального максимума (локальный максимум  это элемент, который больше любого из своих соседей).
Дан массив размера N. Найти максимальный из его локальных минимумов
Дан массив размера N. Обнулить все его локальные максимумы (то есть числа, большие своих соседей).
Дан массив размера N. Найти минимальный из его локальных максимумов.
Дан массив размера N. Найти максимальный из его элементов, не являющихся ни локальным минимумом, ни локальным максимумом (определения локального минимума и локального максимума даны в заданиях Array32 и Array33). Если таких элементов в массиве нет, то вывести 0 (как вещественное число).
Дан массив размера N. Найти количество его промежутков монотонности (то есть участков, на которых его элементы возрастают или убывают).
Дано число R и массив A размера N. Найти элемент массива, который наиболее близок к числу R (то есть такой элемент AK, для которого величина |AK – R| является минимальной).
Дан массив размера N. Найти два соседних элемента, сумма которых максимальна, и вывести эти элементы в порядке возрастания их индексов.
Дан целочисленный массив размера N, все элементы которого упорядочены (по возрастанию или по убыванию). Найти количество различных элементов в данном массиве.
Дан целочисленный массив размера N, содержащий ровно два одинаковых элемента. Найти номера одинаковых элементов и вывести эти номера в порядке возрастания.
Дан целочисленный массив размера N. Найти количество различных элементов в данном массиве.
Дан целочисленный массив размера N. Если он является перестановкой, то есть содержит все числа от 1 до N, то вывести 0; в противном случае вывести номер первого недопустимого элемента.
Дан массив A размера N. Сформировать новый массив B того же размера, элементы которого определяются следующим образом:
BK

2·AK,
если AK < 5,



AK/2
в противном случае.

Даны два массива A и B одинакового размера N. Сформировать новый массив C того же размера, каждый элемент которого равен максимальному из элементов массивов A и B с тем же индексом.
Дан целочисленный массив A размера N. Переписать в новый целочисленный массив B все четные числа из исходного массива (в том же порядке) и вывести размер полученного массива B и его содержимое.
Дан целочисленный массив A размера N (
· 15). Переписать в новый целочисленный массив B все элементы с нечетными порядковыми номерами (1, 3, ) и вывести размер полученного массива B и его содержимое. Условный оператор не использовать.
Дан целочисленный массив A размера N (
· 15). Переписать в новый целочисленный массив B все элементы с порядковыми номерами, кратными трем (3, 6, ), и вывести размер полученного массива B и его содержимое. Условный оператор не использовать.
Дан целочисленный массив A размера N. Переписать в новый целочисленный массив B того же размера вначале все элементы исходного массива с четными номерами, а затем  с нечетными: A2,    A4,    A6,    ,    A1,    A3,    A5,     . Условный оператор не использовать.
Дан массив A размера N. Сформировать новый массив B того же размера по следующему правилу: элемент BK равен сумме элементов массива A с номерами от 1 до K.
Дан массив A размера N. Сформировать новый массив B того же размера по следующему правилу: элемент BK равен среднему арифметическому элементов массива A с номерами от 1 до K.
Дан массив A размера N. Сформировать новый массив B того же размера по следующему правилу: элемент BK равен сумме элементов массива A с номерами от K до N.
Дан массив A размера N. Сформировать новый массив B того же размера по следующему правилу: элемент BK равен среднему арифметическому элементов массива A с номерами от K до N.
Дан массив A размера N. Сформировать два новых массива B и C: в массив B записать все положительные элементы массива A, в массив C  все отрицательные (сохраняя исходный порядок следования элементов). Вывести вначале размер и содержимое массива B, а затем  размер и содержимое массива C.
Даны два массива A и B размера 5, элементы которых упорядочены по возрастанию. Объединить эти массивы так, чтобы результирующий массив C (размера 10) остался упорядоченным по возрастанию.
Даны три целочисленных массива A, B и C размера NA, NB, NC соответственно, элементы которых упорядочены по убыванию. Объединить эти массивы так, чтобы результирующий целочисленный массив D (размера NA + NB + NC) остался упорядоченным по убыванию.
Дан массив A размера N и целые числа K и L (1 
· K < L 
· N). Переставить в обратном порядке элементы массива, расположенные между элементами AK и AL, включая эти элементы.
Дан массив размера N. Обнулить элементы массива, расположенные между его минимальным и максимальным элементами (не включая минимальный и максимальный элементы).
Дан массив размера N. Заменить каждый элемент массива на среднее арифметическое этого элемента и его соседей.
C.
Дана матрица n*n, состоящая из натуральных чисел. Повернуть ее на 90 градусов против часовой стрелки и вывести результат.
В многоэтажном доме n квартир. В массиве А записано количество человек, живущих в каждой квартире. Распечатать, в каких квартирах живут один, два и так далее человек. –Программу оформить в виде процедур.
В массиве А записаны фамилии студентов, которые упорядочены по алфавиту. В этот список вставить(удалить) две фамилии новых студентов так, чтобы упорядочение по алфавиту сохранилось.
В двумерном массиве записаны результаты сдачи сессии студентов Вашей группы. Вывести на экран фамилии тех студентов, у которых только хорошие оценки, только одна тройка.
Рост студентов группы представлен в виде массива. Определить средний рост мальчиков и девочек и сравнить их.
При поступлении в университет лица, получившие двойку на первом экзамене, ко второму экзамену не допускаются. Считая фамилии абитуриентов и их оценки после первого экзамена исходными данными, составить список абитуриентов, допущенных ко второму экзамену.
Известно, что в Москве самыми теплыми являются дни с 15 июля по 15 августа. Для проведения фестиваля были выбраны 7 подряд дней, наиболее теплых по данным за последние 10 лет. Составить подпрограмму для выполнения этих расчетов.
Дан массив размера N. Найти количество участков, на которых его элементы возрастают.
Дан массив размера N. Найти количество участков, на которых его элементы убывают.
Дан массив размера N. Осуществить сдвиг элементов массива вправо на одну позицию (при этом A1 перейдет в A2, A2  в A3, , AN–1  в AN, a исходное значение последнего элемента будет потеряно). Первый элемент полученного массива положить равным 0.
Дан массив размера N. Осуществить сдвиг элементов массива влево на одну позицию (при этом AN перейдет в AN–1, AN–1  в AN–2, , A2  в A1, a исходное значение первого элемента будет потеряно). Последний элемент полученного массива положить равным 0.
Дан массив размера N и целое число K (1 
· K < N). Осуществить сдвиг элементов массива вправо на K позиций (при этом A1 перейдет в AK+1, A2  в AK+2, , AN–K  в AN, а исходное значение K последних элементов будет потеряно). Первые K элементов полученного массива положить равными 0.
Дан массив размера N и целое число K (1 
· K < N). Осуществить сдвиг элементов массива влево на K позиций (при этом AN перейдет в AN–K, AN–1  в AN–K–1, , AK+1  в A1, а исходное значение K первых элементов будет потеряно). Последние K элементов полученного массива положить равными 0.
Дан массив размера N. Осуществить циклический сдвиг элементов массива вправо на одну позицию (при этом A1 перейдет в A2, A2  в A3, , AN  в A1).
Дан массив размера N. Осуществить циклический сдвиг элементов массива влево на одну позицию (при этом AN перейдет в AN–1, AN–1  в AN–2, , A1  в AN).
Дан массив A размера N и целое число K (1 
· K 
· 4, K < N). Осуществить циклический сдвиг элементов массива вправо на K позиций (при этом A1 перейдет в AK+1, A2  в AK+2, , AN  в AK). Допускается использовать вспомогательный массив из 4 элементов.
Дан массив A размера N и целое число K (1 
· K 
· 4, K < N). Осуществить циклический сдвиг элементов массива влево на K позиций (при этом AN перейдет в AN–K, AN–1  в AN–K–1, , A1  в AN–K+1). Допускается использовать вспомогательный массив из 4 элементов.
Дан массив размера N, все элементы которого, кроме первого, упорядочены по возрастанию. Сделать массив упорядоченным, переместив первый элемент на новую позицию.
Дан массив размера N, все элементы которого, кроме последнего, упорядочены по возрастанию. Сделать массив упорядоченным, переместив последний элемент на новую позицию.
Дан массив размера N, все элементы которого, кроме одного, упорядочены по убыванию. Сделать массив упорядоченным, переместив элемент, нарушающий упорядоченность, на новую позицию.
Дан массив A размера N (
· 6). Упорядочить его по возрастанию методом сортировки простым обменом («пузырьковой» сортировкой): просматривать массив, сравнивая его соседние элементы (A1 и A2, A2 и A3 и т. д.) и меняя их местами, если левый элемент пары больше правого; повторить описанные действия N – 1 раз. Для контроля за выполняемыми действиями выводить содержимое массива после каждого просмотра. Учесть, что при каждом просмотре количество анализируемых пар можно уменьшить на 1.
Дан массив A размера N (
· 6). Упорядочить его по возрастанию методом сортировки простым выбором: найти максимальный элемент массива и поменять его местами с последним (N-м) элементом; выполнить описанные действия N – 1 раз, каждый раз уменьшая на 1 количество анализируемых элементов и выводя содержимое массива.
Дан массив A размера N (
· 6). Упорядочить его по возрастанию методом сортировки простыми вставками: сравнить элементы A1 и A2 и, при необходимости меняя их местами, добиться того, чтобы они оказались упорядоченными по возрастанию; затем обратиться к элементу A3 и переместить его в левую (уже упорядоченную) часть массива, сохранив ее упорядоченность; повторить этот процесс для остальных элементов, выводя содержимое массива после обработки каждого элемента (от 2-го до N-го). При выполнении описанных действий удобно использовать прием «барьера», записывая очередной элемент перед его обработкой в дополнительный элемент массива A0.
Дан массив A размера N. Не изменяя данный массив, вывести номера его элементов в том порядке, в котором соответствующие им элементы образуют возрастающую последовательность. Использовать метод «пузырьковой» сортировки (см. задание Array112), модифицировав его следующим образом: создать вспомогательный целочисленный массив номеров I, заполнив его числами от 1 до N; просматривать массив A, сравнивая пары элементов массива A с номерами I1 и I2, I2 и I3,  и меняя местами соответствующие элементы массива I, если левый элемент пары больше правого. Повторив описанную процедуру просмотра N – 1 раз, получим в массиве I требуемую последовательность номеров.
Дан целочисленный массив A размера N. Назовем серией группу подряд идущих одинаковых элементов, а длиной серии  количество этих элементов (длина серии может быть равна 1). Сформировать два новых целочисленных массива B и C одинакового размера, записав в массив B длины всех серий исходного массива, а в массив C  значения элементов, образующих эти серии.
Дан целочисленный массив размера N. Вставить перед каждой его серией элемент с нулевым значением.
Дан целочисленный массив размера N. Вставить после каждой его серии элемент с нулевым значением.
Дан целочисленный массив размера N. Преобразовать массив, увеличив каждую его серию на один элемент.
Дан целочисленный массив размера N, содержащий по крайней мере одну серию, длина которой больше 1. Преобразовать массив, уменьшив каждую его серию на один элемент.
Дано целое число K (> 0) и целочисленный массив размера N. Преобразовать массив, удвоив длину его серии с номером K. Если серий в массиве меньше K, то вывести массив без изменений.
Дано целое число K (> 1) и целочисленный массив размера N. Удалить из массива серию с номером K. Если серий в массиве меньше K, то вывести массив без изменений.
Дано целое число K (> 1) и целочисленный массив размера N. Поменять местами первую серию массива и его серию с номером K. Если серий в массиве меньше K, то вывести массив без изменений.
Дано целое число K (> 0) и целочисленный массив размера N. Поменять местами последнюю серию массива и его серию с номером K. Если серий в массиве меньше K, то вывести массив без изменений.
Дано целое число L (> 1) и целочисленный массив размера N. Заменить каждую серию массива, длина которой меньше L, на один элемент с нулевым значением.
Дано целое число L (> 0) и целочисленный массив размера N. Заменить каждую серию массива, длина которой равна L, на один элемент с нулевым значением.
Дано целое число L (> 0) и целочисленный массив размера N. Заменить каждую серию массива, длина которой больше L, на один элемент с нулевым значением.
Дан целочисленный массив размера N. Преобразовать массив, увеличив его первую серию наибольшей длины на один элемент.
Дан целочисленный массив размера N. Преобразовать массив, увеличив его последнюю серию наибольшей длины на один элемент (определение серии дано в задании Array116).
Дан целочисленный массив размера N. Преобразовать массив, увеличив все его серии наибольшей длины на один элемент.





Работа 3. СИМВОЛЬНЫЙ И СТРОКОВЫЙ ТИПЫ ДАННЫХ

Цель работы:
– изучить приемы работы с символьными и строковыми типами данных;
– изучить подпрограммы для работы с символьными и строковыми данными;
– освоить приёмы работы с перечисляемым типом данных.

Теоретический раздел
1.1. Символьный тип данных
Любой текст состоит из символов. Для хранения одного символа предназначен тип данных char. Переменную типа char можно рассматривать двояко: как целое число, занимающее 1 байт и способное принимать значения от 0 до 255 (тип unsigned char) или от -128 до 127 (тип signed char) и как один текстовый символ. Сам же тип char может оказаться как знаковым, так и беззнаковым, в зависимости от операционной системы и компилятора. Поэтому использовать тип char не рекомендуется, лучше явно указывать будет ли он знаковым (signed) или беззнаковым (unsigned).
Как и целые числа, данные типа char можно складывать, вычитать, умножать, делить, а можно выводить на экран в виде одного символа. Именно это и происходит при выводе символа через объект cout. Если же нужно вывести числовое значение символа (также называемый ASCII-кодом), то значение символа необходимо преобразовать к типу int. Например:
#include
using namespace std;
int main()
{
unsigned char c='A'; // Константы char заключаются в одинарные кавычки
cout< c=126; // char можно присвоить и числовое значение
cout< return 0;
}
В этом примере переменной с типа char присваивается значение, равное символу 'A' (константы типа char записываются как символы в одинарных кавычках), затем на экран выводится значение c, как символа и его ASCII-код, потом переменной c присваивается значение 126 (то есть символ с ASCII-кодом 126) и снова выводится на экран символ и его ASCII-код.
Организовать последовательное посимвольное считывание всего входного потока можно при помощи цикла while:
#include
using namespace std;
int main()
{
unsigned char c;
while(cin>>c) // Цикл пока считывание успешно
{ // Делаем необходимые действия
}
return 0;
}
В этом примере программа будет посимвольно считывать входной поток (по умолчанию  ввод с клавиатуры), пока не встретит признак конца файла. Для того, чтобы сообщить программе о завершении файла при вводе с клавиатуры необходимо нажать клавиши Ctrl-d в системе Linux и Ctrl-z в системе Windows.
Эта программа при считывании данных будет игнорировать символы–разделители: пробелы, символы новой строки и табуляции. Если нужно, чтобы в переменную c считывались все символы, в том числе и разделители, то необходимо для потока ввода cin установить манипулятор noskipws при помощи инструкции cin>>noskipws;.

Строковый тип данных
Строка представляет собой массив значений типа char, завершающийся нулевым байтом. Каждый символ в строке это на самом деле целое битовое значение кода ASCII, соответствующее отображаемому символу или операции, например возврату каретки или переводу строки.
Однако массивы типа char - символьные массивы - занимают в языке особое место. Во многих языках есть специальный тип данных - строка символов (string). В языке С отдельного типа строки символов нет, а реализована работа со строками путем использования одномерных массивов типа char.
В языке С символьная строка - это одномерный массив типа char, заканчивающийся нулевым байтом. Нулевой байт - это байт, каждый бит которого равен нулю. Для нулевого байта определена специальная символьная константа '\0'. Это следует учитывать при описании соответствующего массива символов. Так, если строка должна содержать N символов, то в описании массива следует указать N+1 элемент.
Например, описание char str[11] предполагает, что строка содержит 10 символов, а последний байт зарезервирован под нулевой байт. Конечно, был задан обычный одномерный массив, но если трактовать его как строку символов, то это будет строка максимум из 10 элементов.
Хотя в языке С нет специального типа строки, язык допускает строковые константы. Строковая константа - это список литер, заключенных в двойные кавычки. Например,
"Borland СИ", "Это строковая константа".
Есть два простых способа ввести строку с клавиатуры. Первый способ -воспользоваться функцией scanfO со спецификатором ввода %s. Надо помнить, что функция scanf() вводит символы до первого пробельного символа. Второй способ - воспользоваться специальной библиотечной функцией gets(), объявленной в файле stdio.h. Функция gets() позволяет вводить строки, содержащие пробелы. Ввод оканчивается нажатием клавиши Enter. Обе функции автоматически ставят в конец строки нулевой байт. Не забудьте зарезервировать для него место. В качестве параметра в этих функциях используется просто имя массива.
Вывод строк производится функциями printfO или puts(). Обе функции выводят содержание массива до первого нулевого байта. Функция puts() добавляет в конце выводимой строки символ новой строки. В функции printf() переход на новую строку надо предусматривать в строке формата самим.
Для работы со строками в С имеется богатая библиотека строковых функций (все они начинаются с букв str) string.h. Рассмотрим основные из них.
Функция strlen(s) возвращает длину строки, выраженную в символах.
Функции копирования:
char *strcpy (char* s1, const char* s2) строку s2 копирует в s1;
char *strncpy (char* s1,const char* s2, size_t count) копирует не более count символов из строки s2 в s1;
char *strdup (const char *s) выделяет память для хранения копии строки, на которую указывает s, копирует эту строку в выделенную область и возвращает указатель на неё.
Функции соединения строк:
char *strcat (char* s1, const char* s2) строку s2 присоединяет к строке s1;
char *strncat (char* s1, const char* s2, size_t count) не более count символов из строки s2 присоединяет к строке s1.
Функции поиска:
char * strchr ( const char* s, char c) находит первое вхождение символа с в строку s. Возвращает указатель на найденный символ или NULL, если символ не обнаружен;
char * strrchr ( const char* s, char c) находит последнее вхождение символа с в строку s. Возвращает указатель на найденный символ или NULL, если символ не обнаружен;
char * strstr ( const char* s, const char* substr) ищет в s первое вхождение подстроки substr. Возвращает указатель на первый символ найденной подстроки или NULL, если такая подстрока не найдена;
char *strpbrk ( const char *s1, const char *s2) возвращает указатель на первый символ в строке s1, совпадающий с каким-нибудь из символов строки s2. При этом нулевые символы в конце строки в рассмотрение не включаются;
char * strtok ( const char* s1, const char* s2) возвращает указатель на следующую лексему (часть строки) в строке s1. Символы строки s2 используются как ограничители, определяющие лексему. Как и в других функциях поиска, если лексема не найдена, возвращается NULL.
Функции преобразования строк:
char * strupr ( char* s) английские буквы нижнего регистра (“маленькие”) строки, на которую указывает s, преобразует в соответствующие буквы верхнего регистра (в “большие”). Остальные символы не меняются;
char * strlwr ( char* s) английские буквы верхнего регистра (прописные) строки, на которую указывает s, преобразует в соответствующие буквы ниж-него регистра (в “маленькие”). Остальные символы не меняются.

Перечисляемый тип данных
Перечислимый тип (enumeration) - это множество поименованных целых констант. Перечислимый тип определяет все допустимые значения, которые могут иметь переменные этого типа. Основная форма объявления типа следующая:
enum имя_типа (список_названий) список переменных:
Список переменных может быть пустым. Пример определения перечислимого типа и переменной данного типа:
enum seasons { win, spr, sum, aut };
enum seasons s;
Ключом к пониманию сущности перечислимого типа является то, что каждое из имен win, spr, sum и aut представляет собой целую величину. Если эти величины не определены по-другому, то по умолчанию они соответственно равны нулю, единице, двум и трем. Оператор
printf ("%d %d", win, aut);
выдаст на экран числа 0 и 3. Во время объявления типа можно одному или нескольким символам присвоить другие значения, например:
enum value {one=l, two, three, ten=10, thousand=1000, next};
Если теперь напечатать значения
prinlf ("%d %d %d %d %d\n", one, two, ten, thouthend, next);
то на экране появятся числа 1 2 10 1000 1001, т. е. каждый следующий символ увеличивается на единицу по сравнению с предыдущим, если нет другого присваивания.
С переменными перечислимого типа можно производить следующие операции:
присвоить переменную типа enum другой переменной того же типа;
провести сравнение с целью выяснения равенства или неравенства;
арифметические операции с константами типа enum (i = win - aut).
Нельзя использовать арифметические операции и операции ++ и -- к переменных типа enum.
Основная причина использования перечислимого тина - это улучшение читаемости программ.

Экспериментальный раздел.
Пример 1. Вывод алфавита на экран.
#include
void main(void)
{
char alphabet [34]; // 33 буквы плюс NULL char letter;
int index;
for (letter = 'A', index = 0; letter <= 'Я'; letter++, index++) alphabet[index] = letter;
alphabet[index] = NULL;
cout << "Буквы " << alphabet;
}
Пример 2. Переворот строки.
void swap(char c[])
{ int i,j;
for (i=0; c[i] !='\0'; i++);
for (j=0,i--; i>j; i--,j++)
{ char s; s=c[i]; c[i]=c[j]; c[j]=s; }
}

Пример 3. Преобразование целого char[] в int
int StringToInt(char c[ ]){
int n,i;
for (i=0; !(c[i]>='0' && c[i]<='9'); i++)
if (c[i]=='\0') return 0;
for (n=0; c[i]>='0' && c[i]<='9'; i++)
n = n * 10 + c[i] - '0';
return n;
}
Поэкспериментируйте с предложенным примером и составьте функцию IntToString, реализующую преобразование целого int в char[].
Пример 4. Поиск самой внутренней скобки.
int find(char c[]){
int i, k, max, b;
for (i=0, max=0, b=-1; c[i]!=0; i++){
if (c[i]== '}' ) k--;
if (c[i]== '{' ) {
k++;
if (k>max) { max=k; b=i; }}
}
if (k!=0) return 0;
return b; }
Задания для самостоятельной работы.
А.
1. Составить программу:
которая запрашивает имя человека и повторяет его на экране;
которая запрашивает имя человека и повторяет его на экране с приветствием;
которая запрашивает название футбольной команды и повторяет его на экране со словами: "Это чемпион!".
2. Дано название футбольного клуба. Определить количество символов в нем.
3. Дано название города. Определить, четно или нет количество символов в нем.
4. Даны две фамилии. Определить, какая из них длиннее.
5. Дано слово.
Вывести на экран его третий символ.
Вывести на экран его последний символ.
Вывести на экран его k-й символ.
Определить, одинаковы ли второй и четвертый символы в нем.
Верно ли, что оно начинается и оканчивается на одну и ту же букву?
Получить и вывести на экран буквосочетание, состоящее из его второго и четвертого символов.
Получить и вывести на экран буквосочетание, состоящее из его третьего и последнего символов.
Получить его часть, образованную второй, третьей и четвертой буквами.
Получить его часть, образованную идущими подряд буквами, начиная с т-й и кончая n-й.
6. Даны два слова. Верно ли, что первое слово начинается на ту же букву, которой оканчивается второе слово?
7. Составить программу, которая запрашивает отдельно имя и отдельно фамилию, а затем выводит их как одну символьную строку.
8. Из слова "яблоко" путем вырезок его букв получить слова "блок" и "око”.
9. Из слова "информатика" путем вырезок его букв получить слова "форма" и "тик".
10. Из слова "вертикаль" путем вырезок и склеек его букв получить слова "тир" и "ветка".
11. Из слова "программа" путем вырезок и склеек его букв получить слова "ром" и "рампа".
12. Из слова "трос" путем вырезок и склеек его букв получить слова "сорт", "рост" и "торс".
13. Из слова "клоун" путем вырезок и склеек его букв получить слова "уклон", "кулон" и "колун".
14. Из слова "апельсин" путем вырезок и склеек его букв получить слово "спаниель".
15. Из слова "вирус" путем замены его букв получить слово "фокус".
16. Из слова "курсор" путем замены его букв получить слово "танцор".
17. Из слова "пробел" путем замены его букв получить слово "продел".
18. Из слова "строка" путем замены его букв получить слово "строфа".
19. Из слова "муха" путем замены его букв получить слово "слон".
20. Из слова "тетрадь" путем замены его букв получить слово "дневник".
21. Дано название футбольного клуба. Напечатать его на экран столбиком.
22. Получить строку, состоящую из пяти звездочек, т.е. символов "*".
23. Получить строку, состоящую из восьми символов "_".
24. Составить программу, формирующую строку, состоящую из любого заданного количества любых одинаковых символов.
25. Дано слово. Добавить к нему в начале 4 символа "+" и в конце 5 символов "".
26. Дано предложение. Напечатать все его буквы "и".
27. Дано предложение. Составить программу, которая печатает столбиком все вхождения в предложение некоторого символа.
28. Дано слово из четного числа букв. Поменять местами его половины. Задачу решить двумя способами: без использования оператора цикла; с использованием оператора цикла.
29. Составить программу, которая печатает заданное слово, начиная с последней буквы.
30. Дано предложение. Вывести столбиков все его символы.

В.
1. Дано слово из 12 букв. Поменять местами его трети следующим образом:
первую треть слова разместить на месте третьей, вторую треть на месте первой, третью треть на месте второй;
первую треть слова разместить на месте второй, вторую треть на месте третьей, третью треть на месте первой.
2. Дано слово. Переставить первые три и последние три буквы, сохранив порядок их следования. Задачу решить двумя способами: без использования оператора цикла; с использованием оператора цикла.
3. Дано слово. Перенести первые k его букв в конец.
4. Дано слово s1. Получить слово s2, образованное нечетными буквами слова s1.
5. Дано слово s. Получить слово t, получаемое путем прочтения слова s, начиная с его конца.
6. Дано слово. Добавить к нему в начале и в конце столько звездочек, сколько букв в этом слове.
7. Дано предложение.
Вывести столбиком его третий, шестой и т.д. символы.
Вывести все буквы "м" и "н" в нем.
Составить программу, которая выводит все вхождения в предложение двух заданных символов.
Вывести все имеющиеся в нем буквосочетания "нн".
Вывести столбиком все его буквы "и", стоящие на четных местах.
Вывести столбиком его первый, второй, пятый, шестой, девятый, десятый и т.д. символы.
Определить число букв "о" в нем.
Определить число пробелов в нем.
Определить число вхождений в него некоторого символа.
Определить долю (в %) букв "а" в нем.
8. Дано предложение. Определить:
число вхождений в него буквосочетания "ро";
число вхождений в него некоторого буквосочетания из двух букв;
число вхождений в него некоторого буквосочетания.
9. Дан текст. Подсчитать общее число вхождений в него символов "+" и "".
10. Дана фраза. Определить, сколько в ней предложений.
11. Дано предложение.
Определить, сколько в нем гласных букв.
Все буквы "е" в нем заменить на букву "и".
Все пробелы в нем заменить на символ "_".
Все его символы, стоящие на четных местах, заменить на букву "ы".
Все его символы, стоящие на третьем, шестом, девятом и т.д. местах, заменить на букву "А".
Заменить в нем все вхождения буквосочетания "ах" на "ух".
Заменить в нем все вхождения буквосочетания "да" на "не".
Заменить в нем все вхождения буквосочетания "про" на "нет”.
Заменить в нем все вхождения буквосочетания "бит" на "рог".
Заменить в нем все вхождения подстроки Strl на подстроку Str2.
12. Дан символ. Выяснить, является ли он цифрой.
13. Дан текст. Напечатать все имеющиеся в нем цифры. Определить количество цифр в нем.
14. Дан текст. Определить, является ли он правильной десятичной записью целого числа.
15. Дано предложение. Определить, каких букв в нем больше: "м" или "н".
16. Дано предложение. В нем слова разделены одним пробелом (символ " " в предложении отсутствует). Верно ли, что число слов в предложении больше трех.
17. Дано предложение, в котором имеются буквы "с" и "т". Определить, какая из них встречается позже (при просмотре слова слева направо). Если таких букв несколько, то должны учитываться последние из них. Оператор цикла с условием не использовать.
18. Дан текст. Верно ли, что в нем есть пять идущих подряд одинаковых символов?
19. Дано предложение. Напечатать все его символы, предшествующие первой запятой. Рассмотреть два случая: известно, что в предложении запятые имеются; в предложении запятых может не быть.
20. Дано предложение, в котором имеется несколько букв "е". Найти:
порядковый номер первой из них;
порядковый номер последней из них.
21. Дано предложение. Определить, есть ли в нем буква "а". В случае положительного ответа найти также порядковый номер первой из них.
22. Дано слово. Проверить, является ли оно перевертышем (перевертышем называется слово, читаемое одинаково как с начала, так и с конца).
23. Дан текст. Определить количество букв "и" в первом предложении. Рассмотреть два случая:
известно, что буквы "и" в этом предложении есть;
букв "и" в тексте может не быть.
24. Дано предложение, в котором нет символа "". Определить количество букв "о" в первом слове. Учесть, что в начале предложения могут быть пробелы.
25. Дано предложение. Определить количество букв "н", предшествующих первой запятой предложения. Рассмотреть два случая:
известно, что запятые в предложении есть;
запятых в предложении может не быть.
26. Дана последовательность слов. Проверить, правильно ли в ней записаны сочетания "жи" и "ши". Проверить, правильно ли в ней записаны сочетания "ча" и "ща". Исправить ошибки.
27. Дано предложение. Напечатать все символы, расположенные между первой и второй запятой. Если второй запятой нет, то должны быть напечатаны все символы, расположенные после единственной имеющейся запятой.
28. Дано предложение, в котором имеются одна буква "с" и одна буква "т". Определить, какая из них встречается раньше (при просмотре слова слева направо).
29. Символьной строке по ошибке вместо "опечатка" присвоено значение "очепатка". Изменить значение s так, чтобы ошибки не было.
30. Дано слово. Поменять местами его m-ю и п-ю буквы. Поменять местами первую из букв "а" и последнюю из букв "о". Учесть возможность того, что таких букв в слове может не быть.
31. Дано слово из четного числа букв. Поменять местами первую букву со второй, третью с четвертой и т.д. Поменять местами его половины следующим способом: первую букву поменять с последней, вторую с предпоследней и т.д.
32. Дано слово из 12 букв. Переставить в обратном порядке буквы, расположенные между второй и десятой буквами (т.е. с третьей по девятую).
33. Дано слово из 15 букв. Переставить в обратном порядке буквы, расположенные между k-й и s-й буквами (т.е. с (k + 1)-й по (s -1)-ю). Значения k и s вводятся с клавиатуры, k < s.
34. Устранить имеющуюся в заданном слове ошибку:
а) дано слово "глинянный";
б) дано слово "граффика".
35. Дано слово:
Удалить из него третью букву;
Удалить из него k-ю букву.
Удалить из него первую из букв “о”, если такая буква есть;
Удалить из него последнюю из букв "т", если такая буква есть.
Если его длина нечетная, то удалить среднюю букву, в противном случае две средних буквы.
Удалить из него все повторяющиеся буквы, оставив их первые вхождения, то есть в слове должны остаться только различные буквы.
36. Дано слово, оканчивающееся символом "_". Вставить заданную букву после первой буквы "и".
37. Дано предложение, оканчивающееся символом “__". Вставить заданную букву перед последней буквой “и”.
38. Путем вставок и удаления символов исправить ошибки:
в слове "прроцесор";
во фразе "текстовыйфайл";
во фразе "програма и аллгоритм";
во фразе "процесор и паммять".
39. Дано ошибочно написанное слово "рпроцессo". Путем перемещения его букв получить слово "процессор". Аналогично для слов:
"иинформаця" - "информация";
"алигортм" - "алгоритм";
"роцессорп” - "процессор".
"ИТЕРНЕТН" - "ИНТЕРНЕТ".
"килбайот" - "килобайт".

С.
1. Дано предложение. В нем слова разделены одним пробелом (начальные и конечные пробелы и символ "" в предложении отсутствуют). Определить количество слов в предложении.
2. Дано предложение. В нем слова разделены одним или несколькими пробелами (символ "" в предложении отсутствует). Определить количество слов в предложении. Рассмотреть два случая:
начальные и конечные пробелы в предложении отсутствуют;
начальные и конечные пробелы в предложении имеются.
3. Дано предложение. Найти наибольшее количество идущих подряд пробелов.
4. Дан текст. Найти наибольшее количество идущих подряд одинаковых символов.
5. Дан текст, в котором имеются цифры.
Найти их сумму.
Найти максимальную цифру.
6. Дан текст, в начале которого имеются пробелы и в котором имеются цифры. Найти порядковый номер максимальной цифры, считая, что первый номер имеет первый непробел. Если максимальных цифр несколько, то должен быть найден номер первой из них.
7. Дан текст, представляющий собой десятичную запись целого числа. Вычислить сумму цифр этого числа.1.
8. Дан текст, имеющий вид: d1+d2++dn, где di цифры (n > 1). Вычислить записанную в тексте сумму.
9. Дан текст, имеющий вид: d1–d2+d3–, где di цифры (n > 1). Вычислить записанную в тексте алгебраическую сумму.
10. Дан текст, имеющий вид: d1 ± d2 ±...± dn, где di цифры (n > 1). Вычислить записанную в тексте алгебраическую сумму.
11. Дан текст. Найти наибольшее количество идущих подряд цифр.
Найти сумму всех имеющихся в нем чисел.
Найти максимальное из имеющихся в нем чисел.
12. Дан текст, в котором имеется несколько идущих подряд цифр. Получить число, образованное этими цифрами.
13. Дана последовательность символов, в начале которой имеется некоторое количество одинаковых символов. Определить это количество. Рассмотреть два случая:
известно, что не все символы последовательности одинаковые;
все символы последовательности могут быть одинаковыми.
14. Даны два слова. Определить, сколько начальных букв первого слова совпадает с начальными буквами второго слова. Рассмотреть два случая:
известно, что слова разные;
слова могут быть одинаковыми.
15. Дано предложение. Определить порядковые номера первой пары одинаковых "соседних" символов. Если таких символов нет, то должно быть напечатано соответствующее сообщение. Определить, есть ли в нем сочетания "чу" или "щу". В случае положительного ответа найти также порядковый номер первой буквы первого из них.
16. Дано предложение.
Удалить из него все символы с nl-го по n2-й (n1 < n2).
Удалить из него все буквы "с".
Удалить из него все буквы "о", стоящие на нечетных местах.
17. Проверить, является ли некоторая символьная строка перевертышем после удаления из нее всех пробелов Последние символы "__", полученные после удаления пробелов, не учитывать.
18. Дано слово.
Переставить его s-ю букву на место k-й (s < k). При этом (s + 1)-ю, (s+ 2)-ю, . ., k-ю буквы сдвинуть влево на одну позицию.
Переставить его первую букву на место последней. При этом вторую, третью, ..., последнюю буквы сдвинуть влево на одну позицию.
Переставить его первую букву на место k-й. При этом вторую, третью, ..., k-ю буквы сдвинуть влево на одну позицию.
Переставить его последнюю букву на место первой. При этом первую, вторую, ... , предпоследнюю буквы сдвинуть вправо на одну позицию.
Переставить его последнюю букву на место k-й. При этом k-ю, (k + 1)-ю, . ., предпоследнюю буквы сдвинуть вправо на одну позицию.
Определить, сколько различных букв в нем.
19. В слове имеются только две одинаковых буквы. Найти их.
20. Даны два слова.
Для каждой буквы первого слова (в том числе для повторяющихся в этом слове букв) определить, входит ли она во второе слово. Например, если заданные слова "информация" и "процессор", то для букв первого из них ответом должно быть. "нет нет нет да да нет нет да нет нет".
Для каждой буквы первого слова определить, входит ли она во второе слово. Повторяющиеся буквы первого слова не рассматривать. Например, если заданные слова "процессор" и "информация", то для букв первого из них ответом должно быть: "нет да да да нет нет".
Напечатать только те буквы слов, которые есть только в одном из них (в том числе повторяющиеся). Например, если заданные слова "процессор" и "информация", то ответом должно быть:
"п е с с и ф м а и я".
Напечатать только те буквы слов, которые встречаются в обоих словах только один раз. Например, если заданные слова "процессор" и "информация", то ответом должно быть: "п е ф м л я".
Определить, можно ли из букв первого из них получить второе. Рассмотреть два варианта:
повторяющиеся буквы второго слова могут в первом слове не повторяться;
каждая буква второго слова должна входить в первое слово столько же раз, сколько и во второе.
21. Даны три слова.
Напечатать их общие буквы. Повторяющиеся буквы каждого слова не рассматривать.
Напечатать только те буквы слов, которые есть только в одном из слов. Рассмотреть два варианта: повторяющиеся буквы каждого слова рассматриваются; не рассматриваются.
Напечатать неповторяющиеся в них буквы.
22. Дано предложение из 10 слов. Заполнить ими массив из 10 элементов.
23. Дано предложение.
Напечатать его в обратном порядке слов, например, предложение "мама мыла раму" должно быть напечатано в виде "раму мыла мама".
Поменять местами его первое и последнее слова.
Напечатать все его слова, отличные от слова "привет".
Определить: количество слов, начинающихся с буквы "н"; количество слов, оканчивающихся буквой "т".
Вывести на экран: его слова, начинающиеся и оканчивающиеся на одну и ту же букву; его слова, которые содержат ровно три буквы "е"; его слова, которые содержат хотя бы одну букву "о".
Найти какое-нибудь его слово, начинающееся на букву "к".
Найти длину его самого короткого слова.
Напечатать его самое длинное слово (принять, что такое слово единственное).
Верно ли, что его самое длинное слово имеет больше 10 символов?
Напечатать все его слова в порядке неубывания их длин.
Напечатать все слова, которые встречаются в нем по одному разу.
Напечатать все его различные слова.
В нем только два слова одинаковые. Найти эти слова.
24. Напечатать все слова предложения, предварительно преобразовав каждое из них по следующему правилу:
заменить первую встреченную букву "а" на "о";
удалить из слова все вхождения последней буквы (кроме нее самой);
оставить в слове только первые вхождения каждой буквы;
в самом длинном слове удалить среднюю (средние) буквы. Принять, что такое слово единственное.
25. Напечатать те слова последовательности, которые отличны от первого слова и удовлетворяют следующему свойству:
а) в слове нет повторяющихся букв;
b) слово симметрично.
26. Даны два предложения.
Для каждого слова первого предложения (в том числе для повторяющихся в этом предложении слов) определить, входит ли оно во второе предложение.
Для каждого слова первого предложения определить, входит ли оно во второе предложение. Повторяющиеся слова первого предложения не рассматривать.
Напечатать слова, которые есть только в одном из них (в том числе повторяющиеся).
Напечатать слова, которые встречаются в двух предложениях только один раз.
27. Дан текст. Проверить, правильно ли в нем расставлены круглые скобки (то есть, находится ли справа от каждой открывающей скобки соответствующая ей закрывающая скобка, а слева от каждой закрывающей соответствующая ей открывающая). Предполагается, что внутри каждой пары скобок нет других скобок.
Ответом должны служить слова "да" или "нет".
В случае "неправильности" расстановки скобок:
если имеются лишние правые (закрывающие) скобки, то выдать сообщение с указанием позиции первой такой скобки;
если имеются лишние левые (открывающие) скобки, то выдать сообщение с указанием количества таких скобок.
28. Строка содержит арифметическое выражение, в котором используются круглые скобки, в том числе вложенные. Проверить, правильно ли в нем расставлены скобки.
Ответом должны служить слова "да" или "нет".
В случае "неправильности" расстановки скобок:
если имеются лишние правые (закрывающие) скобки, то выдать сообщение с указанием позиции первой такой скобки;
если имеются лишние левые (открывающие) скобки, то выдать сообщение с указанием количества таких скобок.

Работа 4. СТРУКТУРЫ

Цель работы:
– изучить способы задания структур;
– сравнить структуры и объединения;
– сравнить эффективность решения задач с применением структур и массивов;

I. Теоретический раздел работы
Кроме известных типов данных языка С позволяется создавать ещё несколько типов данных:
- структуры;
- объединения;
- перечисляемый тип (см. лаб. раб. № 3);
- поля битов;
- использование оператора typedef с целью создания нового имени для уже существующих типов.

1.1. Структура
Часто в программировании необходимо объединить разнородные, но логически связанные данные. Например, наш домашний адрес состоит из целых чисел: номеров квартиры, дома, почтового индекса, а также из названий: улицы, города, страны. В языке С для представления разнородных данных служит структурированный тип, который так и называется структурой или комбинированным типом данных.
Структуры, как и массивы, используются для описания упорядоченной совокупности величин. Во многом они схожи, но в отличие от массива, где все компоненты должны быть одного и того же типа, структуры обычно содержат компоненты различных типов. В случае массива переменная с индексами однозначно определяет требуемый элемент. Структура объединяет несколько переменных, возможно разного типа. Переменные, которые объединены структурой, называются членами, элементами или полями структуры.
Пример определения структуры:
struct student {
char name[30];
int kurs;
char group[3];
int stp;
}
Объявление структуры является оператором, и поэтому в конце должна стоять точка с запятой. При этом пока никакая переменная не объявлена. Выделения памяти под переменную не произошло. Под именем student задан частный вид структуры; говорят, что задан шаблон структуры и определен новый тип struct student. Для того чтобы объявить конкретные переменные типа struct student, можно написать
struct sudent studl, stud2;
Теперь объявлены две переменные - studl и stud2. Компилятор автоматически выделит под них место в памяти компьютера. Под каждую из переменных типа структуры выделяется непрерывный участок памяти. Задание шаблона структуры и объявление переменных может производиться и в одном операторе:
struct student {
char name[30];
char kurs;
char group[3];
int stip;
} stud1, stud2;
Здесь одновременно задается структура с именем student и объявляются переменные stud1 и stud2.
Доступ к конкретному элементу структуры осуществляется с помощью операции "точка". Например, stud1.name="Иванов М. С.";
Структуры, как и переменные другого типа, могут объединяться в массивы структур. Чтобы объявить массив структур, надо сначала задать шаблон структуры (у нас уже есть шаблон student), а затем объявить массив:
struct student studlkurs[200];
Этот оператор создаст в памяти 200 переменных типа структуры с шаблоном студент и именами studlkurs[0], studlkurs[l] и т. д.
Для доступа к полю kurs 25-го элемента массива используем studlkurs[24].kurs
Если объявлены две переменные типа структуры с одним шаблоном, можно сделать присваивание
studl=stud2; при этом произойдет побитовое копирование каждого поля одной переменной в соответствующее поле другой структуры. В то же время нельзя использовать операцию присваивания переменных типа структуры, шаблоны которых описаны под разными именами, пусть даже совсем идентично:
Переменная типа структуры может быть глобальной, локальной переменной и формальным параметром. Можно, естественно, использовать структуру или ее элемент структуры как любую другую переменную в качестве параметра функции.
Чтобы завершить разговор о структурах, надо добавить, что в качестве элементов структуры можно использовать массивы, структуры и массивы структур.
Пусть объявления переменных имеют вид
struct addr {
char city[30];
char street[30];
int house;
}
struct fulladdr {
struct addr addres;
int room;
char name[30];
} f,g;
Здесь addr - шаблон структуры, определенный перед объявлением структуры fulladdr и объявлением переменной f типа структуры fulladdr. Для присвоения значения элементу house структуры addres переменной f используем
a.addres.house=101;
1.2. Объединение
В языке Си определен еще один тип для размещения в памяти несколько переменных разного типа. Это объединение. Объявляется объединение так же, как и структура, например:
union u {
int i;
char ch;
long int li:
};
Это объявление не задает какую-либо переменную. Оно задает шаблон объединения. Можно объявить переменную
union u alfa. beta;
Можно было объявить переменные одновременно с заданием шаблона. В отличие от структуры для переменной типа union места в памяти выделяется ровно столько, сколько надо элементу объединения, имеющему наибольший размер в байтах. В приведенном выше примере под переменную alfa будет выделено 4 байта памяти. В самом деле, элемент i требует 2 байта, элемент с - 1 байт, и элемент 1i - 4 байта. Остальные переменные будут располагаться в том же месте памяти. Синтаксис использования элементов объединения такой же, как и для структуры:
u ch = «5»;
1.3. Переименование типов
Язык Си позволяет, кроме того, дать новое название уже существующим типам данных. Для этого используется ключевое слово typedef. При этом не создается новый тип данных.
Например:
typdef char SYMBOL;
typdef unsigned UNSIGN;
typdef float real;
Достаточно часто используется оператор typedef с применением структур:
typdef struct st_tag{
char name[30]:
int kurs;
char group|3|;
int slip;
} STUDENT;
Теперь для определения переменной можно использовать:
struct st_tag avar или STUDENT avar.

II. Экспериментальный раздел работы
Пример 1. Ввода - вывода простейшей структуры на дисплей.
#include
#include
#include
#include
struct Vkladchik
{ // определение структуры "Вкладчик"
int account; // номер счета
char name[10]; // имя
float suma; // сумма вклада
};
void main(void)
{ clrscr();
Vkladchik к ; // создание экземпляра объекта
cout«"Введите счет, имя , сумму \n"; cin»k.account»k.name»k.suma;
cout«"Cчёт"«setw(9 )«"Имя" <cout<cout«"\n\n";
getch();
}

Пример 2. Ввода - вывода массива структур на дисплей.
#include
#include
#include
#include
struct Vkladchik { // определение структуры "Вкладчик"
int account; // номер счета
char name [10]; // имя
float suma; // сумма вклада
};
void main(void)
{ int i, n;
сlrscr();
соut«"Введите число записей п= ";
cin»n;
Vkladchik к [10]; // создание массива экземпляров объектов
соut«"Введите счет, имя, сумму \n";
for(i=0;i cin»k[i].account»k[i].name»k[i].suma; cout«"?"«endl;
}
cout«"Cчёт"«setw(9)«"Имя" <for(i=0;icout<cout«"\n\n";
cout«"\nHажмите любую клавишу...";
getch();
}

Пример 3. Cоставить программу, с помощью которой можно расположить фамилии студентов Вашей группы в порядке убывания среднего балла, полученного по результатам сдачи зимней экзаменационной сессии.
Программа состоит из трех процедур:
ReadData – формирование исходных данных;
WriteData – вывод результатов;
SortChoice – сортировка фамилий студентов согласно среднего балла.
Подробности работы программы разберите по тексту, используя комментарии. Для простоты представлены данные по трем студентам, сдававшим четыре экзамена. Использовался алгоритм сортировки выбором.
#include
#include
#include
#include
int n=3;
int m=4;
typdef struct student_one { /* для данных по одному студенту */
char fio[30]; /*поле формирования фамилии и имени студента*/
int marks[m]; /*поле подмассив оценок, полученных в сессию*/
double sb; {поле для среднего балла }
}
typdef student_one student_all[n]; { массив для формирования данных
по всем студентам Вашей группы }
student_all group;
void ReadData(student_all r); {Процедура ввода данных и вычисления
среднего балла для каждого студента группы}
int i,k,s;
{
r[1].fio =« Иванов Андрей»; /*формирование данных по первому студенту*/
r[1].marks[1]=4; r[1].marks[2]=5; r[1].marks[3]=3; r[1].marks[4]=3;
r[2].fio =« Мунтян Светлана»; /* формирование данных по второму студенту */
r[2].marks[1]=4; r[2].marks[2]=4; r[2].marks[3]=5; r[2].marks[4]=3;
r[3].fio =« Бойко Вячеслав»; /* формирование данных по третьему студенту */
r[3].marks[1]=4; r[3].marks[2]=5; r[3].marks[3]=5; r[3].marks[4]=5;
for (i=1; i< n; i++) /* вычисление среднего балла для каждого студента*/
{ s=0;
for (k=1; k< m; i++; s=s+ r[i].marks[k]);
r[i].sb=s/m;
};
};

void WriteData(sstudent_all r); /*процедура вывода результатов*/
int i;
{
for (i=1; i< n; i++)
cin<< r[i].fio<<” “<};

void SortChoice(student_allgr); /*процедура сортировки методом выбора*/
int i,k,kmax;
double xmax;
student_one st;
{
for (i=1; i< (n-1); i++) /* шаг сортировки */
{ kmax=i; xmax=gr[i].sb; st=gr[i];
for (k=i+1; i< n; i++) /* поиск максимального элемента*/
{ if gr[k].sb > xmax
{
kmax=k; xmax=gr[k].sb; st= gr[k]
};
gr[kmax]=gr[i]; gr[i] =st; /*обмен местами максимального и I -элемента*/
}
};

{ /*Основная программа*/
ReadData(group); cout<<”несортированные данные”< WriteData(group);
SortChoice(group);
cout<<”сортированные данные”< WriteData(group);
getch();
}

Введите программу и проведите ее отладку и тестирование. Проведите сортировку фамилий по алфавиту, по результатам первого экзамена. Поэкспериментируйте с программой.

III. Задания для самостоятельной работы
А.
1. Фамилии и имена 25 учеников класса записаны в двух различных таблицах. Напечатать фамилию и имя каждого ученика на отдельной строке.
2. Названия 20 футбольных клубов и городов, которые они представляют, записаны в двух различных таблицах. Напечатать название и город каждого клуба на отдельной строке.
3. Даны названия 26 городов и стран, в которых они находятся. Среди них есть города, находящиеся в Италии. Напечатать их названия.
4. Известны данные о 16 сотрудниках фирмы: фамилия и отношение к воинской службе (военнообязанный или нет). Напечатать фамилии всех военнообязанных сотрудников.
5. Известны фамилии всех 30 сотрудников фирмы и их адреса. Определить, работают ли в фирме люди с одной из фамилий: Кузин, Куравлев, Кудин, Кульков или Кубиков. В случае положительного ответа напечатать их адреса.
6. Даны названия 20 стран и частей света, в которых они находятся. Определить, есть ли среди них страны, находящиеся в Африке или в Азии. В случае положительного ответа напечатать их названия.
7. Имеется информация о количестве осадков, выпавших за каждый день месяца, и о температуре воздуха в эти дни. Определить, какое количество осадков выпало в виде снега и какое - в виде дождя. (Считать, что идет дождь, если температура воздуха выше 00.)
8. Известны данные о мощности двигателя (в л.с.) и стоимости 30 легковых автомобилей. Определить общую стоимость автомобилей, у которых мощность двигателя превышает 100 л.с.
9. Известны данные о цене и тираже каждого из 15 журналов. Найти среднюю стоимость журналов, тираж которых меньше 10 000 экземпляров.
10. Известны стоимость и “возраст” каждой из 20 моделей легковых автомобилей. Найти среднюю стоимость автомобилей, “возраст” которых превышает 6 лет.
11. Известны данные о массе и объеме 30 тел, изготовленных из различных материалов. Определить максимальную плотность материала тел.
12. Известны данные о численности населения (а миллионах жителей) и площади (в тысячах квадратных километров) 28 государств. Определить максимальную плотность населения в отдельном государстве.
13. Известны данные о стоимости каждого из 20 наименований товаров: число рублей и число копеек. Составить программу, сравнивающую стоимость двух любых наименований товаров (определяющую, какой из товаров стоит дороже).
14. Известна информация о 25 моментах времени одних и тех же суток: часы (значения от 0 до 23) и минуты (от 0 до 59). Составить программу, сравнивающую два любых момента времени (определяющую, какой из моментов был в эти сутки раньше).
15. Даны даты каждого из 20 событий, произошедших после 1930 года: год, номер месяца и число. Составить программу, сравнивающую два любых события по времени (определяющую, какое из событий произошло позже).
16. Количество мячей, забитых и пропущенных футбольной командой в каждой из 22 игр, записано в массиве, элементами которого являются величины типа запись:
Для каждой проведенной игры напечатать словесный результат: “выигрыш”, “ничья” или “проигрыш»”.
Определить количество выигрышей данной команды.
Определить количество выигрышей и количество проигрышей данной команды.
Определить количество выигрышей, количество ничьих и количество проигрышей данной команды.
Определить общее число очков, набранных командой (за выигрыш дается 3 очка, за ничью - 1, за проигрыш - 0.
18. Известны сведения о высоте над уровнем моря 15 горных вершин. Все значения выражены в метрах. Напечатать названия вершин, чья высота превышает 3000 м над уровнем моря.
19. Известны максимальные скорости 20 моделей легковых автомобилей. Все значения выражены в км/ч, Напечатать названия моделей, у которых максимальная скорость превышает 180 км/ч.

В.
1. Известны вес и пол каждого из 20 человек. Найти общую массу мужчин.
2. Известны данные о количестве учащихся в каждом из 15 учебных заведений и о типе этого заведения (школа, техникум или училище). Найти общее число учащихся школ.
3. Известны рост и пол каждого из 22 человек. Найти средний рост мужчин.
4. Известны данные о стоимости каждой из 15 моделей автомобилей и об их типе (легковой или грузовой). Найти среднюю стоимость легковых автомобилей.
5. Известно количество очков, набранных каждой из 20 команд - участниц первенства по футболу. Ни одна пара команд не набрала одинакового количества очков.
Определить название команды, ставшей чемпионом.
Определить названия команд, занявших второе и третье места.
Определить названия команд, занявших первое и второе места, не используя при этом двух операторов цикла (два прохода по массиву).
Вывести названия команд в соответствии с занятыми ими местами в чемпионате.
6. Известен рост каждого из 25 учеников класса. Ни одна пара учеников не имеет одинакового роста.
Определить фамилии самого высокого и самого низкого учеников класса.
Определить фамилии двух учеников, являющихся самыми высокими, без учета действительно самого высокого ученика класса.
Определить фамилии двух учеников, являющихся самыми высокими в классе, не используя при этом два оператора цикла (два прохода по массиву).
Вывести фамилии учеников в порядке, возрастания их роста.
7. Известны данные о росте 15 юношей класса, упорядоченные по убыванию. Ни одна пара учеников не имеет одинакового роста. В начале учебного года в класс поступил новый ученик (известно, что его рост не совпадает с ростом ни одного из учеников класса, превышает рост самого низкого ученика и меньше роста самого высокого).
Вывести фамилии всех учеников, рост которых меньше роста новенького.
Определить фамилию ученика, после которого следует записать фамилию новенького, чтобы упорядоченность не нарушилась.
Определить фамилию ученика, рост которого меньше всего отличается от роста новенького.
Получить новый список фамилий учеников (с учетом фамилии новенького), в котором фамилии расположены в порядке убывания роста.
8. Известно количество очков, набранных каждой из 19 команд - участниц первенства по футболу, Перечень очков и команд дан в порядке занятых ими мест, то есть в порядке убывания количества набранных очков (ни одна пара команд-участниц не набрала одинакового количества очков). Выяснилось, что в перечень забыли включить еще одну, двадцатую, команду.
Определить, какое место заняла эта команда (известно, что она не стала чемпионом и не заняла последнее место),
Вывести названия команд, набравших меньше очков, чем эта команда.
Получить новый список команд (с учетом дополнительной команды), в котором команды также расположены в порядке убывания количества набранных ими очков.
В задачах а и b условный оператор не использовать.
9. В записной книжке указаны фамилии и номера телефонов 30 человек. Составить программу:
которая определяет, есть ли в записной книжке телефон некоторого человека, и, если есть, напечатать номер его телефона;
которая определяет, есть ли в записной книжке информация о человеке с заданным номером телефона, и, если есть, печатающую фамилию этого человека.
10. Известны оценки каждого из 25 учеников класса по десяти предметам. Найти фамилию одного из учеников:
имеющих наибольшую сумму оценок;
имеющих наименьшую сумму оценок.
11. Известны оценки каждого из 20 учеников класса по двенадцати предметам. Определить среднюю оценку каждого ученика и всего класса. Вывести фамилии учеников, у которых средняя оценка выше средней по классу.
12. Таблица футбольного чемпионата задана двухмерным массивом из одинакового количества строк и столбцов, а котором все элементы, принадлежащие главной диагонали, равны нулю, а каждый элемент, не принадлежащий главной диагонали, равен 3, 1 или 0 (числу очков, набранных в игре: 3 - выигрыш, 1 – ничья,0 - проигрыш). Известны названия 20 команд участниц чемпионата.
Определить названия команд, имеющих больше побед, чем проигрышей. Определить названия команд, которые прошли чемпионат без проигрышей.
Определить название команды, ставшей чемпионом.
Определить, расположены ли команды в соответствии с занятыми ими местами в чемпионате, и в случай отрицательного ответа найти название первой команды, результаты которой в таблице расположены в нарушение такого соответствия (принять, что при равном числе очков места распределяются произвольно).
Получить последовательность названий команд в соответствии с занятыми ими местами (сначала должна идти команда, ставшая чемпионом, затем команда, занявшая второе место, и т.д.).

С.
1. Количество мячей, забитых и пропущенных каждой из шестнадцати футбольных команд в каждой из 15 игр, записано в массиве. Его элементами являются массивы величин типа запись. Названия команд известны.
Определить, в скольких играх была ничья.
Определить, в скольких играх разность забитых, пропущенных мячей была большей или равной трем.
Определить количество выигрышей, количество ничьих и количество проигрышей каждой команды.
Общее число очков, набранных каждой командой (за выигрыш дается 3 очка, за ничью - 1, за проигрыш - 0).
Определить название команды, ставшей чемпионом.
2. Годовые оценки по десяти предметам за 9-й класс каждого из 25 учеников класса напечатаны в виде таблицы (в первой строке - оценки первого ученика, во второй - второго и т.д.). Фамилия ученика записана в первом столбце. В начале нового учебного года в класс пришел новый ученик. Изменить таблицу так, чтобы в ней были фамилия и оценки за 9-й класс и нового ученика, учитывая, что этот ученик в списке должен быть на s-м месте.
3. В таблице напечатаны оценки каждого из 29 учеников класса по двенадцати предметам (в первом столбце - по первому предмету, во втором - по второму и т.д.). Названия предметов указаны в соответствующем столбце первой строки. Выяснилось, что в таблицу забыли записать оценки еще по одному пред мету. Изменить таблицу так, чтобы в ней были название пропущенного предмета и оценки по нему, учитывая, что этот предмет в списке должен быть на k-м месте.
4. Известны фамилии, адреса и телефоны 25 человек. Найти фамилии и адреса людей, чей телефон начинается с цифры “3”. Рассмотреть два случая:
телефон задан в виде 7-значного числа;
телефон задан в виде, аналогичном следующему: 268-50-59.
5. Известна информация о 20 сотрудниках фирмы: фамилия, имя, отчество, адрес и дата поступления на работу (месяц, год). Напечатать фамилию, имя, отчество и адрес каждого из сотрудников, проработавших и фирме на сегодняшний день уже не менее трек, лет. День месяца не учитывать. Определить:
фамилию мужчины, имеющего самую большую зарплату (считать, что такой есть и он единственный);
фамилии мужчины и женщины, имеющих самую .маленькую зарплату (считать, что такие есть и они единственные в своей группе сотрудников).
6. Известны данные о 16 сотрудниках фирмы: фамилия, возраст и отношение к воинской службе (военнообязанный или нет). Определить:
фамилию самого младшего по возрасту человека среди военнообязанных (считать, что такой есть и он единственный );
фамилии самых старших по возрасту людей среди военнообязанных и среди невоеннообязанных (считать, что такие есть и они единственные в своей группе).
7. Известны фамилии 25 человек, их семейное положение: женат (замужем) или нет, и сведения о наличии детей (есть или нет). Определить фамилии женатых (замужних) людей, имеющих детей.
8. Известны данные о 20 учениках класса: фамилии, имена, отчества, даты рождения (год, номер месяца и число). Определить, есть ли в классе ученики, у которых сегодня день рождения, и если да, то напечатать имя и фамилию каждого.
9. Известны оценки каждого из 22 учеников класса по четырем предметам. Определить фамилию одного из учеников, имеющих максимальную сумму оценок.
10. Известны баллы, набранные каждым из 20 спортсменов-пятиборцев в каждом из пяти видов спорта. Определить фамилию спортсмена - победителя соревнований.
11. Известны данные о 25 учениках класса: фамилия, имя, отчество, адрес и домашний телефон, если он есть. Вывести на экран фамилию, имя и адрес каждого ученика, у которого нет домашнего телефона. Рассмотреть два случая:
телефон задан в виде 7-значного числа;
телефон задан в виде, аналогичном следующему: 268-50-59.
12. Известна информация о 30 клиентах пункта проката: фамилия, имя, отчество, адрес и домашний телефон. Известно также название предмета, взятого каждым из них напрокат (в виде: т - телевизор, х - холодильник и т.п.). Вывести на экран фамилию, имя и адрес каждого из клиентов, взявших напрокат телевизор.
13. Известна информация о 28 учениках нескольких школ, занимающихся в районном Доме творчества учащихся (фамилия, имя, адрес, номер школы и класс). Фамилию, имя и адрес тех учеников, которые учатся в данной школе в старших (10-11-х) классах, записать в отдельный массив.
14. Известна информация о багаже (количество вещей и общий вес багажа) 24 пассажиров.
Найти число пассажиров, имеющих более двух вещей.
Выяснить, имеется ли хоть один пассажир, багаж которого состоит из одной вещи весом менее 25 кг.
Найти число пассажиров, у которых количество -вещей превосходит среднее число вещей всех пассажиров.
Найти номер пассажира, в багаже которого средний вес одной вещи отличается от общего среднего веса одной вещи не более чем на 0,5 кг.
15. Известно расписание поездов, проходящих через станцию: номер поезда, назначение (откуда куда, например, “Москва – Омск” ), часы и минуты прибытия, часы и минуты отправления. Значения часов и минут целые, положительные; число часов не превышает 23, число минут – 59. Общее число проходящих поездов равно 25. Поезда приходят каждый день. По данному времени определить, какие поезда (номер и назначение) стоят в этот момент на станции.
16. Используя процедуры и функции работы со стеком, написать процедуру, реализующую действие стирающего символа, т.е. символа, который удаляет символ, стоящий перед ним подобно клавише.
17. Используя процедуры и функции работы со стеком, написать процедуру, реализующую действие «символа-убийцы», т.е. символа, который удаляет все символы текущей строки, стоящие перед ним.
18. Используя процедуры и функции работы со списками, реализовать стеки и очереди, как частные случаи списков.
19. Используя процедуры и функции работы со списками, написать процедуру удаления совпадающих элементов Purge( var L:list).

Работа 5. РАБОТА С ФАЙЛАМИ

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

I. Теоретический раздел работы
1.1.Введение
Файл – это именованная область внешней памяти. Файл имеет следующие характерные особенности:
1. имеет имя на диске, что дает возможность программам работать с несколькими файлами;
2. длина файла ограничивается только емкостью диска.
Особенностью Си является отсутствие в этом языке структурированных файлов. Все файлы рассматриваются как не структурированная последовательность байтов. При таком подходе понятие файла распространяется и на различные устройства. Одни и те же функции используются как для обмена данными с файлами, так и для обмена с устройствами.
Библиотека Си поддерживает три уровня ввода-вывода:
- потоковый ввод-вывод;
- ввод-вывод нижнего уровня;
- ввод-вывод для консоли портов (зависит от конкретной ОС).

1.1. Потоковый ввод-вывод
На уровне потокового ввода-вывода обмен данными производится побайтно, т. е. за одно обращение к устройству (файлу) производится считывание или запись фиксированной порции данных (512 или 1024 байта). При вводе с диска или при считывании из файла данные помещаются в буфер ОС, а затем побайтно или порциями передаются программе пользователя. При выводе в файл данные также накапливаются в буфере, а при заполнении буфера записываются в виде единого блока на диск. Буферы ОС реализуются в виде участков основной памяти. Т.о. поток – это файл вместе с предоставленными средствами буферизации. Функции библиотеки Си, поддерживающие обмен данными на уровне потока позволяют обрабатывать данные различных размеров и форматов. При работе с потоком можно:
1. Открывать и закрывать потоки (при этом указатели на поток связываются с конкретными файлами).
2. Вводить и выводить строки, символы, форматированные данные, порции данных произвольной длины.
3. Управлять буферизацией потока и размером буфера.
4. Получать и устанавливать указатель текущей позиции в файле.
Прототипы функций ввода-вывода находятся в заголовочном файле , который также содержит определения констант, типов и структур, необходимых для обмена с потоком.

1.2. Открытие и закрытие потока
Прежде, чем начать работать с потоком, его надо инициировать, т. е. открыть. При этом поток связывается со структурой предопределенного типа FILE, определение которой находится в файле . В структуре находится указатель на буфер, указатель на текущую позицию и т. п. При открытии потока возвращается указатель на поток, т. е. на объект типа FILE. Указатель на поток должен быть объявлен следующим образом:
#include
........
FILE *f; //указатель на поток
Указатель на поток приобретает значение в результате выполнения функции открытия потока:
FILE* fopen(const char* filename, const char* mode);
где const char* filename – строка, которая содержит имя файла, связанного с потоком, const char* mode – строка режимов открытия файла.
Например: f = fopen(“t.txt”,”r”);
где t.txt – имя файла,
r – режим открытия файла.
Файл связанный с потоком можно открыть в одном из 6 режимов
Режим
Описание режима открытия файла

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

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

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

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

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

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

Поток можно открывать в текстовом (t) или двоичном режиме(b). В текстовом режиме поток рассматривается как совокупность строк, в конце каждой строки находится управляющий символ \n’. В двоичном режиме поток рассматривается как набор двоичной информации. Текстовый режим устанавливается по умолчанию.
В файле определена константа EOF, которая сообщает об окончании файла (отрицательное целое число).
При открытии потока могут возникать следующие ошибки:
- файл, связанный с потоком не найден (при чтении из файла);
- диск заполнен (при записи);
- диск защищен от записи (при записи) и т. п.
В этих случаях указатель на поток приобретет значение NULL (0). Указатель на поток, отличный от аварийного не равен 0.
Для вывода об ошибке при открытии потока используется стандартная библиотечная функция из файла
void perror (const char*s);
Эта функция выводит строку символов, не которую указывает указатель s, за этой строкой размещается двоеточие пробел и сообщение об ошибке. Текст сообщения выбирается на основании номера ошибки. Номер ошибки заносится в переменную int errno (определена в заголовочном файле ).
После того как файл открыт, в него можно записывать информацию или считывать информацию, в зависимости от режима.
Открытые файлы после окончания работы рекомендуется закрыть явно. Для этого используется функция: int fclose(FILE* f);
Изменить режим работы с файлом можно только после закрытия файла.



1.3. Стандартные файлы и функции для работы с ними.
Когда программа начинает выполняться, автоматически открываются несколько потоков, из которых основными являются:
- стандартный поток ввода (stdin);
- стандартный поток вывода (stdout);
- стандартный поток вывода об ошибках (stderr).
По умолчанию stdin ставится в соответствие клавиатура, а потокам stdout и stderr -монитор. Для ввода-вывода с помощью стандартных потоков используются функции:
- getchar()/putchar() – ввод-вывод отдельного символа;
- gets()/puts() – ввод-вывод строки;
- scanf()/printf() – форматированный ввод/вывод.
Функции рассматривались, когда мы рассматривали строковые и символьные данные. Теперь мы можем связать их со стандартными потоками: ввод осуществляется из стандартного потока stdin вывод осуществляется в стандартный поток stdout. Аналогично работе со стандартными потоками выполняется ввод-вывод в потоки, связанные с файлами.
Для символьного ввода-вывода используются функции:
- int fgetc(FILE*fp), где fp – указатель на поток, из которого выполняется считывание. Функция возвращает очередной символ в форме int из потока fp. Если символ не может быть прочитан, то возвращается значение EOF.
- int fputc(int c, FILE*fp), где fp – указатель на поток, в который выполняется запись, c – переменная типа int, в которой содержится записываемый в поток символ. Функция возвращает записанный в поток fp символ в форме int . Если символ не может быть записан, то возвращается значение EOF.
Для построчного ввода-вывода используются следующие функции:
- char* fgets(char* s,int n,FILE* f), где
char*s – адрес, по которому размещаются считанные байты,
int n – количество считанных байтов,
FILE* f – указатель на файл, из которого производится считывание.
Прием байтов заканчивается после передачи n-1 байтов или при получении управляющего символа \n’. Управляющий символ тоже передается в принимающую строку. Строка в любом случае заканчивается \0’. При успешном завершении считывания функция возвращает указатель на прочитанную строку, при неуспешном – 0.
- int puts(char* s, FILE* f), где
char*s – адрес, из которого берутся записываемые в файл байты,
FILE* f – указатель на файл, в который производится запись.
Символ конца строки (\0’) в файл не записывается. Функция возвращает EOF, если при записи в файл произошла ошибка, при успешной записи возвращает неотрицательное число.
Для блокового ввода-вывода используются функции:
1) int fread(void*ptr,int size, int n, FILE*f), где void* ptr – указатель на область памяти, в которой размещаются считанные из файла данные,
int size – размер одного считываемого элемента,
int n – количество считываемых элементов,
FILE*f – указатель на файл, из которого производится считывание.
В случае успешного считывания функция возвращает количество считанных элементов, иначе – EOF.
2) int fwrite(void*ptr,int size, int n, FILE*f), где
void* ptr – указатель на область памяти, в которой размещаются считанные из файла
данные,
int size – размер одного записываемого элемента,
int n – количество записываемых элементов,
FILE*f – указатель на файл, в который производится запись.
В случае успешной записи функция возвращает количество записанных элементов, иначе – EOF.

1.4. Форматированный ввод-вывод
В некоторых случаях информацию удобно записывать в файл без преобразования, т.е. в символьном виде пригодном для непосредственного отображения на экран. Для этого можно использовать функции форматированного ввода-вывода:
1) int fprintf(FILE *f, const char*fmt,. . .) , где
FILE*f – указатель на файл, в который производится запись,
const char*fmt – форматная строка,
. . . – список переменных, которые записываются в файл.
Функция возвращает число записанных символов.
2) int fscanf(FILE *f, const char*fmt, par1,par2, . . .) , где
FILE*f – указатель на файл, из которого производится чтение,
const char*fmt – форматная строка,
par1,par2,. . . – список переменных, в которые заносится информация из файла.
Функция возвращает число переменных, которым присвоено значении.

1.5. Прямой доступ к файлам
Рассмотренные ранее средства обмена с файлами позволяют записывать и считывать данные только последовательно. Операции чтения/записи всегда производятся, начиная с текущей позиции в потоке. Начальная позиция устанавливается при открытии потока и может соответствовать начальному или конечному байту потока в зависимости от режима открытия файла. При открытии потока в режимах “r” и “w” указатель текущей позиции устанавливается на начальный байт потока, при открытии в режиме “a” - за последним байтом в конец файла. При выполнении каждой операции указатель перемещается на новую текущую позицию в соответствии с числом записанных/прочитанных байтов.
Средства прямого доступа дают возможность перемещать указатель текущей позиции в потоке на нужный байт. Для этого используется функция
int fseek(FILE *f, long off, int org), где
FILE *f - – указатель на файл,
long off – позиция смещения
int org – начало отсчета.
Смещение задается выражение или переменной и может быть отрицательным, т. е. возможно перемещение как в прямом, так и в обратном направлениях. Начало отсчета задается одной из определенных в файле констант:
SEEK_SET = =0 – начало файла;
SEEK_CUR= =1 – текущая позиция;
SEEK_END = =2 – конец файла.
Функция возвращает 0, если перемещение в потоке выполнено успешно, иначе возвращает ненулевое значение.
Примеры:
fseek(f,0L,SEEK_SET); //перемещение к началу потока из текущей позиции
fseek(f,0L,SEEK_END); //перемещение к концу потока из текущей позиции
fseek(f,-(long)sizeof(a),SEEK_SET); //перемещение назад на длину переменной а.
Кроме этой функции, для прямого доступа к файлу используются:
long tell(FILE *f);//получает значение указателя текущей позиции в потоке;
void rewind(FILE *f);//установить значение указателя на начало потока.

II. Экспериментальный раздел работы.
Пример 1: Посимвольный вывод содержимого файла на экран.
#include
#include
#include
void main()
{
FILE *f;
char c;
char *filename=”f.txt”;
if((f=fopen(filename,”r”)==0)
{ perror(filename);
exit(0);
}
while(c=fgetc(f)!=EOF) putchar(c); //вывод с на стандартное устройство вывода
fclose(f);
}
Измените программу так, чтобы работа велась со строками.
Пример 2. Копирование содержимого файла.

int MAXLINE=255;//максимальная длина строки
FILE *in,//исходный файл
*out;//принимающий файл
char* buf[MAXLINE];//строка, с помощью которой выполняется копирование
in=fopen(“f1.txt”,”r”);//открыть исходный файл для чтения
out=fopen(“f2.txt”,”w”);//открыть принимающий файл для записи
while(fgets(buf,MAXLINE,in)!=0)//прочитать байты из файла in в строку buf
fputs(buf,out);//записать байты из строки buf в файл out
fclose(in);fclose(out);//закрыть оба файла

Поэкспериментируйте с предложенным отрывком программы, доработайте для копирования по следующей схеме A->B->C.
Пример 3. Создание базы данных сотрудников предприятия.
struct Employee
{
char name[30];
char title[30];
float rate;
};
void main()
{
Employee e;
FILE *f;
if((f=fopen(“f.dat”,”wb”))==NULL)
{
cout<<”\n Невозможно открыть файл для записи”;
exit(1);
}
int n;
//запись в файл
printf(“\nN-?”);
scanf(“%d”,&n);
for(int i=0;i {
//формируем структуру е
printf(“\nname:”);scanf(“%s”,&e.name);
printf(“\ntitle:”);scanf(“%s”,&e.title);
printf(“\nrate:”);scanf(“%s”,&e.rate);
//записываеме в файл
fwrite(&e,sizeof(Employee),1,f);
}
fclose(f);
//чтение из файла
if((f=fopen(“f.dat”,”rb”))==NULL)
{
cout<<”\n Невозможно открыть файл для чтения”;
exit(2);
}
while(fread(&e,sizeof(Employee)1,f)
{
printf(“%s % s%f”, e.name, e.title, e.rate)
}
fclose(f);
}

Пример 4. Редактирование базы данных сотрудников предприятия

//добавление записи в файл
void add(char *filename)
{
student a;
int n;
f=fopen(filename,”a”)открыть файл для добавления
cout<<"\nHow many records would you add to file?";
cin>>n;
for(int i=0;i {
прочитать объект
fwrite(&a,sizeof(student),1,f);//записать в файл
}
fclose(f);//закрыть файл

}

//удаление записи с номером х
void del(char *filename)
{
FILE *f, *temp;
f=fopen(filename,”rb”);//открыть исходный файл для чтения
temp=fopen(“temp”,”wb”)//открыть вспомогательный файл для записи
student a;
for(long i=0;.fread(&a,sizeof(student),1,f);i++)
if(i!=x)
{
fwrite(&a,sizeof(student)1,temp);
}
else
{
cout< }
fclose(f);
fclose(temp);
remove(filename);
rename(“temp”, filename);
}
Измените программу, представленную в примере 3, используя предложенные подпрограммы.

III. Задания для самостоятельной работы
A.
Дан текстовый файл, содержащий целые числа. Найти:
количество чисел в файле;
максимальный элемент в файле, максимальные элементы в каждой строке файла;
сумму чисел в файле, то же для каждой строки файла;
разность между максимальным и минимальным элементами в файле, то же для каждой строки файла;
среднее арифметическое чисел в файле, то же для каждой строки файла;
номер максимального элемента в файле;
сумму максимальных элементов в файле;
сумму четных чисел в файле.
Дан текстовый файл, содержащий строки. Найти:
количество строк, начинающихся с заглавных латинских букв;
количество строк, начинающихся и заканчивающихся одинаковыми символами;
самые короткие строки;
симметричные строки (палиндромы).
Дан текстовый файл. Вставить в начало каждой строки ее номер и записать преобразованные строки в новый файл.
Даны два текстовых файла. Записать в третий только те строки, которые есть и в первом, и во втором файлах.
Дан текстовый файл. Дописать в его конце следующие данные: количество строк, количество символов в каждой строке, количество чисел в каждой строке.
Даны два текстовых файла А и В. Поменять местами содержимое этих файлов. Использовать процедуру Rename не разрешается.
Содержимое текстового файла копируется в другой файл, при этом каждая строка циклически сдвигается вправо на п символов. Пример циклического сдвига строки abcdefqwrt на 3 символа: wrtabcdefq. Решить ту же задачу, сдвигая каждое слово на половину его длины.
Дано некоторое множество слов. Исключить их из текстового файла. Например, из файла с текстом программы исключить все слова Begin и End.
Считаем, что длина строк текстового файла не превышает 80 символов. Преобразовать файл так, чтобы все строки были отцентрированы.
Дан файл, в котором встречаются даты. Каждая дата это число, месяц и год (например, 13.05.1949 г.). Найти наименьшую дату.
Дан массив строк. Записать их в файл, расположив каждый элемент массива на отдельной строке с сохранением порядка.
В конец существующего текстового файла записать три новые строки текста. Записываемые строки вводятся с клавиатуры.
Имеется текстовый файл, в котором записана одна строка – “Здравствуйте, дорогие ребята”. Приписать в конце строки восклицательный знак.
Имеется текстовый файл, Удалить из него: третью строку; первую строку, в конце которой стоит вопросительный знак.
Имеется текстовый файл. Напечатать:
его первую строку;
его пятую строку;
его первые 5 строк;
его строки с s1-й по s2-ю;
весь файл.
Имеется текстовый файл. Напечатать:
все его строки, начинающиеся с буквы “Т”;
все его строки, содержащие более 30 символов;
все его строки, в которых имеется более трех пробелов;
все его строки, содержащие в качестве фрагмента заданный текст.
Имеется текстовый файл. Найти:
количество строк, начинающихся с букв “А” или “а”;
в которых имеется ровно 5 букв “и”.
Имеется текстовый файл.
Найти длину самой длинной строки.
Найти номер самой длинной строки. Если таких строк несколько, то найти номер одной из них.
Напечатать самую длинную строку. Если таких строк несколько, то напечатать первую из них.
Имеется текстовый файл. Выяснить, имеется ли в нем строка, начинающаяся с буквы “т”. Если да, то определить номер первой из таких строк.
Имеется текстовый файл. Напечатать n символ строки под номером m.
Имеется текстовый файл, в каждой строке которого первые два символа являются буквами. Получить;
слово, образованное первыми буквами каждой троки;
слово, образованное вторыми буквами каждой строки;
последовательность символов, образованную s1-ми символами каждой строки.
Имеется текстовый файл, содержащий 20 строк. Переписать каждую из его строк в массив в том же порядке
Имеется текстовый файл. Переписать его строки в другой файл. Порядок строк во втором файле должен:
совпадать с порядком строк в заданном файле;
быть обратным по отношению к порядку строк в заданном файле.
Имеется текстовый файл. Переписать его строки в перевернутом виде в другой файл. Порядок строк во втором файле должен:
совпадать с порядком строк в заданном файле;
быть обратным по отношению к порядку строк в заданном файле.
Имеется текстовый файл. Получить текст, в котором в конце каждой строки из заданного файла добавлен восклицательный знак.
Имеется текстовый файл. Переписать в другой файл те его строки, в которых имеется более 30 символов.
Имеется текстовый файл. Переписать в другой файл все его строки с заменой в них символа “0”на символ “1” и наоборот.
Имеется текстовый файл. Все четные строки этого файла записать во второй файл, а нечетные - в третий файл. Порядок следования строк сохраняется.
Имеются два текстовых файла с одинаковым. числом строк. Переписать с сохранением порядка следования строки первого файла во второй, а строки второго файла - в первый. Использовать вспомогательный файл .
Имеются два текстовых файла с одинаковым числом строк. Выяснить, совпадают ли их строки. Если нет, то получить номер первой строки, в которой эти файлы отличаются друг от друга.
Создать файл и записать в него числа 10, 12, 14,16.
Дан массив из двадцати вещественных чисел. Записать все числа массива в файл в том же порядке.
Дано предложение. Записать каждый из его символов в файл.
Дана последовательность целых чисел, оканчивающаяся нулем. Записать все числа последовательности в файл.
Дана строка S. Если S является допустимым именем файла, то создать пустой файл с этим именем и вывести True. Если файл с именем S создать нельзя, то вывести False.
Дано имя файла и целое число N (> 1). Создать файл целых чисел с данным именем и записать в него N первых положительных четных чисел (2, 4,...).
Дано имя файла и вещественные числа A и D. Создать файл вещественных чисел с данным именем и записать в него 10 первых членов арифметической прогрессии с начальным членом A и разностью D: A, A+D, A + 2·D, A + 3·D, .
Даны имена четырех файлов. Найти количество файлов с указанными именами, которые имеются в текущем каталоге.
Дано имя файла целых чисел. Найти количество элементов, содержащихся в данном файле. Если файла с таким именем не существует, то вывести-1.
Дано целое число K и файл, содержащий неотрицательные целые числа. Вывести K-й элемент файла (элементы нумеруются от 1). Если такой элемент отсутствует, то вывести -1.
Дан файл целых чисел, содержащий не менее четырех элементов. Вывести первый, второй, предпоследний и последний элементы данного файла.
Даны имена двух файлов вещественных чисел. Известно, что первый из них существует и является непустым, а второй в текущем каталоге отсутствует. Создать отсутствующий файл и записать в него начальный и конечный элементы существующего файла (в указанном порядке).
Даны имена двух файлов вещественных чисел. Известно, что один из них (не обязательно первый) существует и является непустым, а другой в текущем каталоге отсутствует. Создать отсутствующий файл и записать в него конечный и начальный элементы существующего файла (в указанном порядке).
Дан файл целых чисел. Создать новый файл, содержащий те же элементы, что и исходный файл, но в обратном порядке.
Дан файл вещественных чисел. Создать два новых файла, первый из которых содержит элементы исходного файла с нечетными номерами (1,3, ..), а второй с четными (2, 4, .).
Дан файл целых чисел. Создать два новых файла, первый из которых содержит четные числа из исходного файла, а второй нечетные (в том же порядке). Если четные или нечетные числа в исходном файле отсутствуют, то соответствующий результирующий файл оставить пустым.
Дан файл целых чисел. Создать два новых файла, первый из которых содержит положительные числа из исходного файла (в обратном порядке), а второй отрицательные (также в обратном порядке). Если положительные или отрицательные числа в исходном файле отсутствуют, то соответствующий результирующий файл оставить пустым.
Дан файл вещественных чисел. Найти среднее арифметическое его элементов.
Дан файл вещественных чисел. Найти сумму его элементов с четными номерами.
Дан файл целых чисел. Найти количество содержащихся в нем серий (то есть наборов последовательно расположенных одинаковых элементов). Например, для файла с элементами 1, 5, 5, 5, 4, 4, 5 результат равен 4.
Дан файл целых чисел. Создать новый файл целых чисел, содержащий длины всех серий исходного файла (серией называется набор последовательно расположенных одинаковых элементов, а длиной серии количество этих элементов). Например, для исходного файла с элементами 1, 5, 5, 5, 4, 4, 5 содержимое результирующего файла должно быть следующим: 1, 3, 2, 1.
Дан символьный файл, содержащий по крайней мере один символ пробела. Удалить все его элементы, расположенные после первого символа пробела, включая и этот пробел.
Дан символьный файл, содержащий по крайней мере один символ пробела. Удалить все его элементы, расположенные после последнего символа пробела, включая и этот пробел.
Дан символьный файл, содержащий по крайней мере один символ пробела. Удалить все его элементы, расположенные перед первым символом пробела, включая и этот пробел.
Дан символьный файл, содержащий по крайней мере один символ пробела. Удалить все его элементы, расположенные перед последним символом пробела, включая и этот пробел.
Дан символьный файл. Упорядочить его элементы по возрастанию их кодов.
Дано целое число K (> 0) и строковый файл. Создать два новых файла: строковый, содержащий первые K символов каждой строки исходного

B.
Дан строковый файл. Создать новый строковый файл, содержащий все строки исходного файла наименьшей длины (в том же порядке).
Дан строковый файл. Создать новый строковый файл, содержащий все строки исходного файла наибольшей длины (в обратном порядке).
Дан строковый файл. Создать новый строковый файл, в котором строки из исходного файла располагались бы в лексикографическом порядке, то есть по возрастанию кодов их символов, начиная с первого символа.
Дан строковый файл, содержащий даты в формате «день/месяц/год», причем под день и месяц отводится по две позиции, а под год четыре (например, «16/04/2001»). Создать два файла целых чисел, первый из которых содержит значения дней, а второй значения месяцев для дат из исходного строкового файла (в том же порядке).
Дан строковый файл, содержащий даты в формате, например, «16/04/2001». Создать два файла целых чисел, первый из которых содержит значения месяцев, а второй значения лет для дат из исходного строкового файла (в обратном порядке).
Дан файл вещественных чисел. Найти его первый локальный минимум (локальным минимумом называется элемент, который меньше своих соседей).
Дан файл вещественных чисел. Найти его последний локальный максимум (локальным максимумом называется элемент, который больше своих соседей).
Дан файл вещественных чисел. Найти общее количество его локальных экстремумов, то есть локальных минимумов и локальных максимумов (определения локального минимума и локального максимума даны в заданиях File1 8 и File1 9).
Дан файл вещественных чисел. Создать файл целых чисел, содержащий номера всех локальных максимумов исходного файла в порядке возрастания (определение локального максимума дано в задании File 19).
Дан файл вещественных чисел. Создать файл целых чисел, содержащий номера всех локальных экстремумов исходного файла в порядке убывания (определение локального экстремума дано в задании File20).
Дан файл вещественных чисел. Создать файл целых чисел, содержащий длины всех убывающих последовательностей элементов исходного файла. Например, для исходного файла с элементами 1.7, 4.5, 3.4, 2.2, 8.5, 1.2 содержимое результирующего файла должно быть следующим: 3,2.
Дан файл вещественных чисел. Создать файл целых чисел, содержащий длины всех монотонных последовательностей элементов исходного файла. Например, для исходного файла с элементами 1.7, 4.5, 3.4, 2.2, 8.5, 1.2 содержимое результирующего файла должно быть следующим: 2, 3, 2, 2.
Дан файл вещественных чисел. Заменить в нем все элементы на их квадраты.
Дан файл вещественных чисел. Поменять в нем местами минимальный и максимальный элементы.
Дан файл целых чисел с элементами A1, A2 ,, AN (N количество элементов в файле). Заменить исходное расположение его элементов на следующее: A1, An, A2, An-1, A3.
Дан файл вещественных чисел. Заменить в файле каждый элемент, кроме начального и конечного, на его среднее арифметическое с предыдущим и последующим элементом.
Дан файл целых чисел, содержащий более 50 элементов. Уменьшить его размер до 50 элементов, удалив из файла необходимое количество конечных элементов.
Дан файл целых чисел, содержащий четное количество элементов. Удалить из данного файла вторую половину элементов.
Дан файл целых чисел, содержащий более 50 элементов. Уменьшить его размер до 50 элементов, удалив из файла необходимое количество начальных элементов.
Дан файл целых чисел, содержащий четное количество элементов. Удалить из данного файла первую половину элементов.
Дан файл целых чисел. Удалить из него все элементы с четными номерами.
Дан файл целых чисел. Удалить из него все отрицательные числа.
Дан файл целых чисел, содержащий менее 50 элементов. Увеличить его размер до 50 элементов, записав в начало файла необходимое количество
нулей.
Дан файл целых чисел. Удвоить его размер, записав в конец файла все его исходные элементы (в том же порядке).
Дан файл целых чисел. Удвоить его размер, записав в конец файла все его исходные элементы (в обратном порядке).
Дан файл целых чисел. Продублировать в нем все элементы с нечетными номерами.
Дан файл целых чисел. Продублировать в нем все числа, принадлежащие диапазону 5-10.
Дан файл целых чисел. Заменить в нем каждый элемент с четным номером на два нуля.
Дан файл целых чисел. Заменить в нем каждое положительное число на три нуля.
Даны два файла произвольного типа. Поменять местами их содержимое.
Дан файл произвольного типа. Создать его копию с новым именем.
Даны три файла одного и того же типа, но разного размера. Заменить содержимое самого длинного файла на содержимое самого короткого.
Даны три файла одного и того же типа, но разного размера. Заменить содержимое самого короткого файла на содержимое самого длинного.

C.
Дана строка S0, целое число N(
·4) и N файлов одного и того же типа с именами S1 ,, SN. Объединить содержимое этих файлов (в указанном порядке) в новом файле с именем S0.
Даны два файла одного и того же типа. Добавить к первому файлу содержимое второго файла, а ко второму файлу содержимое первого.
Даны три файла целых чисел одинакового размера с именами SA, SB, SC и строка SD. Создать новый файл с именем SD, в котором чередовались бы элементы исходных файлов с одним и тем же номером: A1, B1, C1, A2, B2, C2
Даны два файла вещественных чисел с именами S1 и S2, элементы которых упорядочены по возрастанию. Объединить эти файлы в новый файл с именем S3 так, чтобы его элементы также оказались упорядоченными по возрастанию.
Даны три файла вещественных чисел с именами S1, S2 и S3, элементы которых упорядочены по убыванию. Объединить эти файлы в новый файл с именем S4 так, чтобы его элементы также оказались упорядоченными по убыванию.
Дана строка S0, целое число N (
· 4) и N файлов целых чисел с именами S1 ,, SN. Объединить их содержимое в новом файле-архиве с именем S0, используя следующий формат: в первом элементе файла-архива хранится число N, в следующих N элементах хранится размер (число элементов) каждого из исходных файлов, а затем последовательно размещаются данные из каждого исходного файла.
Дана строка S, целое число N (> 0) и файл-архив целых чисел, содержащий данные из нескольких файлов в формате. Восстановить из файла-архива файл с номером N и сохранить его под именем S. Если файл-архив содержит данные из менее чем N файлов, то оставить результирующий файл пустым.
Дана строка S и файл-архив целых чисел, содержащий данные из нескольких (не более шести) файлов в формате.
Для каждого из файлов, содержащихся в архиве, найти среднее арифметическое всех его элементов (вещественное число) и записать найденные числа (в том же порядке) в файл вещественных чисел с именем S.
Дана строка S0, целое число N (
· 4) и N файлов целых чисел с именами S1 ,, SN. Объединить их содержимое в новом файле-архиве с именем S0, последовательно записывая в него следующие данные: размер (число элементов) первого исходного файла и все элементы этого файла, размер второго исходного файла и все его элементы ., , размер N-го исходного файла и все его элементы.
Дана строка S, целое число N (> 0) и файл-архив целых чисел, содержащий данные из нескольких файлов в формате, описанном в задании File55. Восстановить из файла-архива файл с номером N и сохранить его под именем S. Если файл-архив содержит данные из менее чем N файлов, то оставить результирующий файл пустым.
Даны строки S1, S2 и файл-архив целых чисел, содержащий данные из нескольких файлов в формате, описанном в задании File55. Создать новые файлы целых чисел с именами S1 и S2 и записать в первый из них начальные элементы всех файлов, содержащихся в архиве, а во второй конечные элементы этих файлов (в том же порядке).
Дан файл вещественных чисел, содержащий элементы квадратной матрицы (по строкам). Создать новый файл, содержащий элементы матрицы, транспонированной к исходной.
Даны два файла вещественных чисел с именами Sa и Sb, содержащие элементы квадратных матриц A и B (по строкам). Создать новый файл с именем S& содержащий элементы произведения A· B. Если матрицы A и B нельзя перемножать, то оставить файл SC пустым.

СПИСОК ЛИТЕРАТУРЫ

Абрамов С. А. Начала информатики, - М.: Наука, 1990
Абрамов С. А. и др. Задачи по программированию,- М.: Наука, 1998
Берёзин Б.И., Берёзин С.Б. Начальный курс С и С. – М.: ДИАЛОГ-ЬИФИ, 1996.- 288 с.
Гусева А. И. Учимся информатике: задачи и методы их решения, - М.: Диалог МИФИ, 1998
Кушниренко А.Г. Основы и информатики и вычислительной техники: Проб.учеб. для сред.учеб.заведений./А.Г.Кушниренко, Г. В. Лебедев, Р.А.Сворьев. – 3-е изд.- М.: Просвещение, 1993. – 224 с. : ил.
Микелсен Клаус. Язык программирования С#. Лекции и упражнения. Учебник.Пер. с англ./ Микелсен Клаус –СПб.: ООО «ДиаСофтЮП», 2002. – 656 с.
Сван Т. Освоение Borland C 4.5. Практический курс. – К.: «Диалектика», 1996. – 544с.
Сердвик Роберс Фундаментальные алгоритмы на С. Анализ/Структуры данных/Сортировки/Поиск.:пер. англ./Роберт Сердвик.-К.: Издательство «ДиаСофт», 2001.-688 с.
Том Сван. Освоение Borland C 4.5. Энциклопедия функций. – К.: «Диалектика», 1996. – 320с.
Трой Д. Программирование на языке Си для персонального компьютера IPM PC: Пер с англ. – М.: Радио и связь, 1991. – 432 с.: ил.
Халперн, Пабло. Стандартная библиотека С на примерах.: Пер. с англ. : М.: Издательский дом «Вильямс», 2001. – 336 с.: ил.
Шелест В.Д. Программирование.- СПб.: БХВ-Петербург, 2001. – 592 с.: ил.
Шилдт, Герберт С: базовый курс, 3-е издание.: Пер. с англ. – М.: Издательский дом «Вильямс», 2005. -624 с.: ил.
Язык Си для профессионалов по материалам книги Г.Шилдта. «И.И.К.-СОФТ», Москва. 1992. 319 с.
Языки программирования Ада, Си, Паскаль. Сравнение и оценка /под ред. А.Р. Фьюэра, Н.Джехани: пер.с англ. В.В.Леонаса.- М.: Радио и связь, 1989.-368 с.: ил.













Учебное издание

Программирование на языке высокого уровня Си
Часть II

Практикум





Компьютерная верстка: О.В. Сташкова
Формат А 4. Уч.-изд. 3,6 п.л. Тираж - 10 экз.










13PAGE 15


13PAGE 14515



a0 = q1a1 + a2
a1 = q2a2 + a3
..
ak = qk+1ak+1 + ak+2
..
an-1 = qnan13 EMBED Equation.3 1415







Root EntryEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation NativeEquation Native

Приложенные файлы

  • doc 325982
    Размер файла: 662 kB Загрузок: 0

Добавить комментарий