71713

Программирование линейных алгоритмов. Работа с отладчиком

Лабораторная работа

Информатика, кибернетика и программирование

Линейная программа Если в программе все операторы выполняются последовательно, один за другим, такая программа называется линейной. Рассмотрим в качестве примера программу, вычисляющую результат по заданной формуле.

Русский

2014-11-11

1.58 MB

15 чел.

PAGE  15

Разработал Кашпар А.И  


Второй индекс

Первый

индекс

-3

-3

6

-3

6

-3

6

NULL

EMBED Equation.3  


Лабораторная  работа  № 1

Тема: «Программирование линейных алгоритмов. Работа с отладчиком»

  1.  Цель  работы
    1.  Освоение простейшей структуры программы на языке Си.
    2.  Получение навыков в организации ввода-вывода на Языке Си.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.

  1.  Постановка  задачи

Написание простейшей программы с обработкой данных.

  1.  Содержание отчета
    1.  Тема и цель работы.
    2.  Постановка задачи.
    3.  Текст программ.
    4.  Результаты выполнения программ.
    5.  Схемы алгоритма программ.

  1.  Общие  сведения

5.1 Линейная программа

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

Задача 1.1. Расчет по формуле

Написать программу, которая переводит температуру в градусах по Фаренгейту в градусы Цельсия по формуле:

C =5/9 (F-32),

где С - температура по Цельсию, a F — температура по Фаренгейту.

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

В данном случае:

- в качестве исходных данных выступает одно вещественное число, представляющее собой температуру по Цельсию,

- в качестве результата — другое вещественное число.

Перед написанием программы откроем интегрированную среду Visual C++:

Пуск/Программы/Microsoft Visual Studio/ Microsoft Visual C++ 6.00

Далее создадим проект. Для этого:

  1.  File > New...
  2.  В открывшемся окне:

- выберите тип Win32 Console Application;

 - введите имя проекта в текстовом поле Project Name;

- введите (выберете с помощью кнопки …) имя каталога размещения файлов проекта в текстовом поле Location, например G:/ASOIZ/

- щелкните левой кнопкой мыши на кнопке ОК.

  1.   открывается диалоговое окно Win32 Console Application — Stepl of 1 и в нем:

- выберите тип An empty project;

- щелкните на кнопке Finish.

  1.   После щелчка появится окно New Project, в котором щелкните на кнопке ОК.

Далее создадим файл:

1) File > New....  В результате откроется диалоговое окно New.

2) На вкладке Files:

выберите тип файла (в данном случае: C++ Source File);

в текстовом поле File Name введите нужное имя файла;

флажок Add to project должен быть включен;

щелкните на кнопке ОК.

Набираем следующий текст программы:

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

В начале программы записана директива препроцессора, по которой к исходному тексту программы подключается заголовочный файл <iostream.h>. Это файл, который содержит описания операторов ввода-вывода cin и cout.

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

Любая заготовка при написании программы имеет вид:

#include <…>

#include <…>

int main()       

{

 объявление переменных;

 ввод исходных данных;

 расчет результата;

 вывод результата;

  return 0;        

}

Для хранения исходных данных и результатов надо выделить достаточно места в оперативной памяти. Для этого служит оператор 2. В нашей программе требуется хранить два значения: температуру по Цельсию и температуру по Фаренгейту, поэтому в операторе определяются две переменные. Одна, для хранения температуры по Фаренгейту, названа fahr, другая (по Цельсию) — cels. Имена переменным дает программист, исходя из их назначения. Имя может состоять только из латинских букв, цифр и знака подчеркивания и должно начинаться не с цифры.

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

Основные типы:

int  (short, unsigned) – целочисленные,

float (double, long double) –  вещественные

charсимвольный

bool – логический

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

В операторе 4 выполняется ввод с клавиатуры одного числа в переменную fahr. Для этого используется стандартный объект cin и операция извлечения (чтения) >>.  Если требуется ввести несколько величин, используется цепочка операций  >>.

В операторе 5 вычисляется выражение, записанное справа от операции присваивания (обозначаемой знаком =), и результат присваивается переменной cels, то есть заносится в отведенную этой переменной память.  Cначала целая константа 5 будет поделена на целую константу 9, затем результат этой операции умножен на результат вычитания числа 32 из переменной fahr.

Для вывода результата в операторе 6 применяется объект cout. Выводится цепочка, состоящая из пяти элементов. Это строка " По Фаренгейту:", значение переменной fahr, строка ", в градусах Цельсия:" , значение переменной cels и оператор перехода на новую строку endl. 

Последний оператор (оператор 7) этой программы предназначен для возврата из нее и передачи значения во внешнюю среду.

Далее компилируем программу. Для этого нажимаем кнопку на панели инструментов либо комбинацию клавиш Ctrl+F7. В окне вывода (внизу экрана) должно вывестись сообщение 0 error(s), 0 warning(s) (0 ошибок, 0 предупреждений). Если есть ошибки - сверьте с оригиналом.

Для запуска программы нажимаем кнопку на панели инструментов либо комбинацию клавиш Ctrl+F5.

При запуске программы вместо русских символов видим ???, что вызвыно различными стандартами кодировки символов кириллицы в операционных системах MS DOSWindows. Для исправления добавим в программу функцию CharToOem (дополнения для наглядности выделены красным цветом)

#include <iostream.h>

#include <windows.h>

char  buf[256];

char* RUS(const char* text)

{

  CharToOem(text, buf);

  return buf;

}

int main()       

{

  float fahr, cels;       

  cout<<endl<<RUS(" Введите температуру По Фаренгейту")<<endl;  

  cin>>fahr;       

  cels=5/9 * (fahr - 32);      

  cout<<RUS(" По Фаренгейту: ")<<fahr;

  cout<<RUS(", в градусах Цельсия: ")<<cels<<endl;  

  return 0;        

}

Функцию Rus() нельзя использовать более одного раза в цепочке операций << для одного объекта cout, поэтому мы разбили его на два.

Как вы можете видеть, результат выполнения программы со стабильностью оказывается равным нулю! Это происходит из-за способа вычисления выражения. Давайте вновь обратимся к оператору 4. Константы 5 и 9 имеют целый тип, поэтому результат их деления также целочисленный. Естественно, что результат дальнейших вычислений не может быть ничем, кроме нуля. Исправить эту ошибку просто — достаточно записать хотя бы одну из констант в виде вещественного числа, например:

cels = 5. / 9 * (fahr - 32);

Задания1

Напишите программу для расчета по двум формулам. Предварительно подготовьте тестовые примеры по второй формуле с помощью калькулятора (результат вычисления по первой формуле должен совпадать со второй). Для использования математических функций необходимо подключить к программе заголовочный файл <math. h>

Функция

Выполняемые действия

Abs(n)

Возвращаемый модуль целого числа

fabs (x)

Возвр. модуль вещественного числа  

acos(x)

asin(x)

atan (x)

atan 2(x)

Arcos x

Arsin x

Arctg x

Возвращаем  arctg x/y

cos(x)

sin(x)

tan(x)

exp(x)

log(x)

log10(x)

pow(x,y)

sqrt(x)

Cos x

Sin x

Tag x

Степень числа  е

Натуральный логарифм

Логарифм по основанию 10

Возводит число х в степень у

Квадратный корень из числа

1

2

3                                            10

4

5

6

7

8


Лабораторная  работа  № 2

Тема: «Работа с главным меню системы  Visual  C++. Изучение базовых типов данных. Форматированный ввод- вывод информации.»

  1.  Цель  работы
    1.  Изучение интегрированной среды Visual  C++ 6.0
    2.  Освоение простейшей структуры программы на языке С++.
    3.  Получение навыков в организации ввода-вывода на языке С++.
    4.  Изучить базовые типы данных языка С++.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Window
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.

  1.  Постановка  задачи

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

  1.  Содержание отчета
    1.  Тема и цель работы.
    2.  Постановка задачи.
    3.  Текст программы.
    4.  Результаты выполнения программы.

  1.  Общие  сведения

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

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

С не предусматривает никаких предопределенных структур файлов: файлы рассматриваются как последовательности байтов.

Функции ввода и вывода библиотеки языка С позволяют читать данные из файлов и с устройств и писать данные в файлы и на устройства. Библиотека языка С поддерживает следующие три уровня ввода-вывода: ввод-вывод потока, ввод-вывод нижнего уровня и ввод-вывод для консоли и порта.

  1.  Консольный  ввод-вывод

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

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

Простейшей из стандартных функций ввода-вывода на консоль является  getchar(), читающая символы с клавиатуры, и  putchar(), печатающая символ на экран в текущей позиции курсора. Тем не менее getchar() имеет некоторые существенные ограничения, описываемые ниже. В Borland C добавлена функция getche(), которая читает символ с клавиатуры без ожидания нажатия клавиши  <Enter>. Ниже показаны прототипы функций getchar(), getche() и putchar():

int getchar(void);

int getche(void);

int putchar(int ch);

Функция getchar() читает символ с клавиатуры и ожидает нажатие <Enter>. Функция getche() читает символ с клавиатуры и не ожидает нажатие <Enter>. Функция возвращает значение ch в случае успеха или  EOF в случае ошибки (EOF – это макроопределение, означающее конец файла). Функции getchar()  и  putchar()  требуют заголовочного файла stdio.h. Функция getche()  требует заголовочного файла  conio.h. Следующий пример программы вводит символы с клавиатуры и выводит их в противоположном регистре. То есть прописные символы будут выведены  строчными, а строчные – прописными. Программа останавливается при обнаружении точки. Заголовочный файл ctype.h содержит прототипы функций для обработки символов.

/* переключатель регистра */

#include <conio.h>

#include <stdio.h>

#include <ctype.h>

int main(void)    {

  char ch;

  do {

         ch=getche();

             if(islower(ch))  putchar(toupper(ch));

             else putchar(tolower(ch));

 }  while  (ch!=’.’);  /* использование точки для остановки */

}

  1.  Чтение  и  запись  строк

Функции gets() и  puts()  позволяют читать строки с клавиатуры и выводить их на экран.

Функция gets() читает строку символов, введенных с клавиатуры и помещает их по адресу,  указанному в аргументе.  Можно  набирать символы,  пока  не нажата клавиша < >. Символ, соответствующий клавише Enter – возврат каретки – не станет частью строки. Функция  gets() имеет прототип:

char *gets(char *str);

где str – это массив символов. Функция gets() возвращает указатель на str. Следующая программа осуществляет чтение строки в массив  str  и выводит ее длину:

#include  <stdio.h>

#include  <string.h>

int main(void)

{

  char  str[80];

  gets(str);

  printf(“Length is %d”,strlen(str);

}

Имеется проблема, связанная с gets(), о которой следует знать: нельзя переходить границы массива, с которым она вызывалась. Для предыдущего примера это 80.

Функция  puts()  выводит передаваемый ею аргумент на экран, завершая вывод переходом на новую строку. Она имеет следующий прототип:

int puts(const char *str);

Здесь  str – выводимая строка. Функция возвращает нецелое число в случае удачи и EOF в случае неудачи. Она воспринимает коды и с обратным слэшем, как и printf(), например  \t  воспринимается как табуляция. Вызов функции puts() требует гораздо меньше процессорного времени на реализацию, чем printf(). Она не может выводить числа и выполнять преобразование форматов.

  1.  Форматированный консольный ввод-вывод

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

  1.  Форматированный вывод

Функция printf() имеет следующий прототип:

int printf(const char *форматная_строка, …);

Первый аргумент форматная_строка определяет способ вывода последующих аргументов. Он часто называется форматной строкой и содержит два типа элементов: символы, выводимые на экран и спецификаторы формата, определяющие способ вывода аргументов, следующих за форматной строкой. Спецификаторы формата начинаются со знака “%”, за которым следует код формата. Спецификаторы формата приведены в таблице 1. Должно быть полное соответствие между числом аргументов и числом спецификаторов формата, а также спецификаторы формата и аргументы должны соответствовать друг другу слева направо. Например, вызов:

printf(“Hi %c %d %s”, ‘c’,10, “there!”0;

отобразит на экране  «Hi c 10 there!». Функция printf() возвращает число напечатанных символов. В случае ошибки она возвращает EOF.

Таблица 1 – Спецификаторы формата функции printf()

Код

Формат

%c

%d

%i

%е

%Е

%f

%g

%G

%o

%s

%u

%x

%X

%p

%n

%%

Символ

Знаковое десятичное целое число

Знаковое десятичное целое число

Научная нотация (е – строчная)

Научная нотация (Е – прописная)

Десятичное число с плавающей точкой

Использует или %e, или %f, соответствующее более короткому представлению

Использует или %E, или %F, соответствующее более короткому представлению

Беззнаковое восьмиричное число

Строка символов

Беззнаковое десятичное число

Беззнаковое шестнадцатиричное число (строчные буквы)

Беззнаковое шестнадцатиричное число (прописные буквы)

Вывод указателя

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

Выводит знак  %

Печать  символов

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

Для печати строки используйте спецификатор %s.

Вывод  чисел

Можно использовать или спецификатор  %d, или спецификатор  %i для отбрахения знакового десятичного целого числа. Эти форматы эквивалентны и присутствуют оба по историческим причинам.

Для вывода беззнакового значения надо использовать спецификатор  %u.

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

Спецификаторы  %e и %E  сообщают  printf()  о небходимости вывода вещественного числа в научной нотации. Числа, представленные в научной нотации, имеют вид:

x.dddddE+/-yy.

Если необходимо вывести символ «Е», используйте %Е, иначе используйте  %е.

Можно указать функции  printf() использовать %f или %е, используя спецификаторы формата %g или %G. В результате этого printf() выбирает спецификатор формата, приводящий к более короткой форме выдачи информации. Если необходимо, чтобы в научной нотации присутствовало «Е», используйте %G, иначе - %g.

Можно отображать беззнаковые целые в восьмиричном или шестнадцатиричном форматах, используя %о и %х соответственно. Поскольку шестнадцатиричные числа используют буквы от А до F для представления чисел от 10 до 15, следует использовать спецификатор формата   %Х  для вывода прописных букв, а  %х  - для строчных.

Вывод  адресов

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

#include  <stdio.h>

int sample;

int main(void);

{

  printf(“%p”, &sample);

{

Спецификатор  %n

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

#include  <stdio.h>;

int main(void)

{

  int count;

  printf(“this%n is a test\n”, &count);

  printf(“%d”, count)

}

Программа выводит в первой строке this is a test, а во второй строке число 4. Спецификатор %n используется, как правило, для выполнения динамического форматирования.

Спецификатор минимума ширины поля

Целое число, помещаемое между знаком  %  и кодом формата, рассматривается как спецификатор минимума ширины поля. Он добавляет к выводу пробелы, для обеспечения некоторой минимальной длины. Если строка чисел длиннее, чем этот минимум, то она будет выводится без отсечений. По умолчанию для достижения необходимой длины строка дополняется пробелами. Если необходимо выводить не пробелы, а нули, следует поставить ноль перед спецификатором ширины поля. Например, спецификатор %05d будет выводить числа, длиной меньше пяти символов с впереди стоящими нулями, чтобы полная длина была пять. Следующая программа демонстрирует использование спецификатора минимума длины поля:

#include  <stdio.h>

int main(void)

{

 double item;

 item = 10.12304;

 printf(“%f\n”,item);

 printf(“%10f\n”,item);

 printf(“%012f\n”,item);

}

В результате работы  данной программы получаем:

10.123040

10.123040

00010.123040

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

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

При применении спецификатора точности к вещественным данным, используя спецификаторы %f, %e или %Е, он определяет число выводимых цифр в дробной части. Например, %10.4f  выводит числа, по крайней мере, с длиной строки в 10 символов, причем под дробную часть отводится 4 символа. Если не указать точность, то по умолчанию используется шесть символов.

Когда спецификатор точности применяется к  %g или  %G, он определяет число значимых цифр.

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

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

Следующая программа иллюстрирует применение спецификатора точности:

#include   <stdio.h>

int main(void)

{

 printf(“%.4f\n”, 123.1234567);

 printf(“%3.8d\n”, 1000);

 printf(“%10.15s\”, “This is a simple test”);

}

В результате работ программы получаем:

123.1235

00001000

This is a simpl

Выровненный вывод

По умолчанию все выводимое выравнивается по правому краю. То есть, если поле имеет ширину, большую чем выводимые данные, то данные размещаются с правого края поля. Можно выводить информацию с левого края, поместив знак минус сразу после  %. Например, %-10.2f  приведет к выравниванию по левому краю вещественного числа с двумя знаками после запятой в 10-символьном поле.

Работа с другими типами данных

Имеется два модификатора формата, позволяющие функции printf() выводить короткие и длинные целые. Эти модификаторы могут применяться к спецификаторам типа  d, i, o, u, x. Модификатор  l  сообщает функции printf() о том, что далее будет следовать длинный тип данных. Например, %ld  означает, что будет выводится значение  типа  long int. Модификатор  h  говорит функции printf() о необходимости вывода коротких целых. Например, %hu выводит данные типа short unsigned int.

Модификатор  L  может стоять перед спецификатором плавающего типа e, f  и g , тем самым указывая, далее следуют переменные типа  long double.

Модификаторы  *  и  #

Функция printf() поддерживает два дополнительных модификатора для некоторых спецификаторов формата: * и # .

Помещение  #  перед g, G, f, e или Е  обеспечивает наличие десятичной точки в случае отсутствия дробной части. Если перед спецификатором формата  х  или  Х  поставить  #, то шестнадцатиричное число будет печататься с префиксом 0х. Если перед спецификатором о  поместить  #, то выведенное число будет иметь в начале  0. Нельзя применять #  к остальным спецификаторам формата.

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

printf(“%*.*f”,10,4, 123.3);

минимальная ширина поля равна 10, точность – 4, а вводимое значение – 123.3.

  1.  Форматированный  ввод

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

 int scanf(const char *форматная_строка, …);

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

Форматная строка состоит из трех типов символов:

  •  Спецификаторы формата
  •  Специальные символы
  •  Стандартные символы

Функция scanf() возвращает число введенных полей. Она возвращает EOF, если обнаруживается преждевременный конец файла.

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

Перед спецификаторами формата ввода ставится знак  %, и они сообщают функции scanf() о типе читаемых далее данных. Эти спецификаторы перечислены в таблице 2. Спецификаторы формата рассматриваются слева направо, и в таком же порядке с ними сопоставляются аргументы из списка аргументов.

Таблица 2 – Спецификаторы формата функции scanf()

Код

Значение

%c

%d

%i

%е

%f

%g

%o

%s

%u

%x

%p

%n

%[]

Читает одиночные символы

Читает десятичное число

Читает десятичное число

Читает число с плавающей точкой

Читает число с плавающей точкой

Читает число с плавающей точкой

Читает восьмеричное число

Читает строку

Читает беззнаковое целое

Читает шестнадцатиричное число

Читает указатель

Получает целочисленное значение, равное числу прочитанных символов

Сканирует множество символов

Ввод чисел

Традиционно  для  чтения  десятичного  числа  используются  спецификаторы  %d или %i. 

Для чтения числа с плавающей точкой, представленного в стандартной или научной нотации, используются спецификаторы  %e, %f или %g.

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

#include  <stdio.h>

int main(void)

{

  int  i, j;

  scanf(“%o%x”, &i, &j);

  printf(“%o %x”, i, j);

}

Ввод беззнаковых целых

Для ввода беззнаковых целых используется спецификатор формата %u. Например:

  unsigned  num;

  scanf(“%u”, &num);

Чтение одиночных символов

Как показано ранее, можно читать отдельные символы, используя функции getchar() или  getche(). Для этих целей также можно использовать и scanf(), для чего нужно указать спецификатор формата  %с.

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

scanf(“%c%c%c”, &a, &b, &c);

вернет символ  х  в а, пробел в  b  и символ у в с.

Чтение строк

Функция  scanf() может использоваться для чтения строк и потока ввода, для чего надо указать спецификатор формата  %s. %s  заставляет функцию scanf() читать символы, пока не встретится специальный символ. Прочитанные символы помещаются в массив символов, на который указывает соответствующий аргумент, и результат завершается нулевым пробелом. Применительно к scanf() специальные символы – это пробел, новая строка, табуляция, вертикальная табуляция или перевод формата. В противоположность gets(), которая читает строку, пока не встретиться возврат каретки (нажатие <Enter>), функция scanf() читает строку до первого специального символа. Это означает, что нельзя использовать scanf() для чтения строки типа «this is a test», поскольку первый пробел завершит процесс ввода.

Ввод адреса

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

#include  <stdio.h>

int main(void)

{

  char *p;

  printf(“Enter an adress:  ”);

  scanf(“%p”, &p);

  printf(“Value at location  %p is %c\n”, p, *p);

}

Спецификатор  %n

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

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

Функция scanf() поддерживает спецификатор формата общего назначения, называемый множеством сканирования. Множество сканирования определяет набор символов. Когда  scanf() обрабатывает множество сканирования, она вводит символы до тех пор, пока символы являются частью множества сканирования. Читаемые символы сохраняются в символьном массиве, на который указывает соответствующий аргумент. Для определения множества сканирования необходимо поместить сканируемые символы в квадратные скобки. Открываемой квадратной скобке должен предшествовать  %. Например, следующее множество сканирования сообщает функции scanf() о необходимости только чтения символов X, Y и Z:

%[XYZ]

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

#include  <stdio.h>

int main(void)

{

  int  i;

  char  str[80], str2[80];

  scanf(“%d%[abcdefg]%s”, &i, str, str2);

  printf(“%d %s %s”, i, str, str2);

}

Введем 123abcdtye, после чего нажмем <Enter>. Программа отобразит 123 abcd tye. Поскольку символ «t» не является частью множества сканирования, scanf()  останавливает чтение символов в  str при обнаружении «t». Оставшиеся символы помещаются в str2.

Можно указать диапазоны множества сканирования, используя дефис. Например, следующая команда говорит функции scanf()  о необходимости чтения символов от «А» до «Z»:

%[A-Z]

Пропуск нежелательных специальных символов

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

Обычные символы в управляющей строке

Обычные символы в управляющей строке заставляют функцию scanf()  читать и отбрасывать соответствующие символы из потока ввода. Например, “%d,%d” заставляет функцию scanf() прочитать целое число, прочитать и пропустить запятую, а затем начать читать другое целое число. Если указанный символ не найден, то функция scanf() завершает работу.

В scanf() следует передавать адреса

Все переменные, используемые для получения значений из  , должны передавться в виде адресов. Это означает, что все аргументы должны быть указателями на переменные, используемые как аргументы. Например, для чтения целого в переменную  count  надо использовать следующий вызов scanf():

scanf(“%d”, &count);

Строки будут читаться в массивы символов, причем имя массива (без индексов) является адресом первого элемента массива. Таким образом, для чтения строки в символьный массив  str следует использовать

scanf(“%s”, str);

В  данном  случае  str  является  указателем  и  нет  необходимости ставить перед ним оператор &.

Модификаторы формата

Как функция printf(), так и функция scanf()  допускают наличие нескольких спецификаторов формата, немного изменяющих ввод.

Спецификаторы формата могут содержать модификатор максимальной длины поля. Это целое число, помещаемое между % и спецификатором формата, ограничивающее число символов, читаемых в поле. Например, для чтения не более 20 символов в str следует написать:

scanf(“%20s”, str);

Если поток ввода содержит более 20 символов, последующее обращение к вводу начнется с места, где было завершено предыдущее обращение. Например, если ввести

 ABCDEFGHIJKLMNOPQRSTUVWXYZ

В ответ на запрос функции , приведенной в предыдущем примере, в str поместятся только 20 символов (включая «Т») из-за наличия спецификатора максимальной ширины поля. Это означает, что оставшиеся символы UVWXYZ не были использованы. Если вызвать еще одну scanf()  , например:

 scanf(“%s”, str);

То буквы UVWXYZ поместятся в str. Вод в поле может окончится до достижения максимальной длины поля, если обнаружится специальный символ. В данном случае scanf() переходит к следующему полю.

Для чтения длинных целых следует поместить l перед спецификатором формата. Для чтения коротких целых следует поместить h перед спецификатором формата. Данные модификаторы могут использоваться с кодами формата  d, i, o, u и х.

По умолчанию спецификаторы f, e и g  сообщают  о необходимости присвоения данной переменной типу float. Если поместить перед одним из этих спецификаторов l , то scanf() присвоит данные типу double. Использование L сообщает  о необходимости представления полученных данных как long double.

Подавление ввода

Можно заставить scanf() прочитать поле, но не присвоить его какой-либо переменной, поставив перед кодом формата поля  *. Например, имея

scanf(“%d%*c%d”, &x, &y);

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

 

7. Варианты  задания

п.п.

Целые числа

Вещественные числа

Символы

Строки

Количество

Формат

Количество

Формат

Количество

Формат

Количество

Количество символов в строке

Формат

Ширина поля

Из них в научной нотации

Ширина поля

Кол-во знаков после точки

Ширина поля

Ширина поля

1

2

5

4

2

6

2

4

4

2

5

8

2

3

6

2

1

7

3

5

3

1

7

10

3

3

6

2

1

6

3

3

5

2

6

8

4

2

5

4

1

6

2

6

2

2

4

7

5

4

4

3

2

7

4

4

3

1

10

14

6

2

3

3

1

5

1

3

5

3

3

6

7

3

4

4

2

8

3

8

2

2

6

9

8

4

5

4

1

6

2

5

3

3

7

9

9

3

7

3

1

5

1

6

2

2

6

8

10

2

6

5

2

5

2

4

4

1

12

17

11

2

6

3

1

6

2

5

3

3

5

8

12

3

4

2

1

7

3

3

4

2

6

9

13

4

4

2

1

8

4

3

4

2

5

8

14

2

7

2

1

7

3

4

3

3

4

7

15

2

8

4

2

6

2

5

2

2

6

8


Лабораторная  работа  № 3

Тема: «Программирование разветвляющихся алгоритмов. Оператор  if»

  1.  Цель  работы
    1.  Освоение простейшей структуры программы на языке Си.
    2.  Изучение оператора ветвления if.
    3.  Получение навыков в программирование разветвляющихся алгоритмов.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.

  1.  Постановка  задачи

Разработать программу вычисления выражения (см.  таблицу)  и вывода полученного результата.

  1.  Содержание отчета

5.1. Тема и цель работы.

5.2. Постановка задачи.

5.3. Схема алгоритма решения задачи.

5.4. Текст программы.

5.5. Результаты выполнения программы.

  1.  Общие  сведения

5.2 Оператор  if

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

Стандартная форма записи оператора  if  следующая:

if  (выражение)

оператор;

else  

оператор;

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

В условии могут использоваться следующие операции:

Операции отношений (сравнения).

<

меньше, чем

>

больше, чем

<=

меньше или равно, чем

>=

больше или равно, чем

==

Равно

!=

не равно

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

Результат операции целочисленный: 0 (ложь) или 1 (истина).

Логические операции.

&& конъюнкция (И) арифметических операндов или отношений

|| дизъюнкция (ИЛИ) арифметических операндов или отношений

Результат 0 (ложь) или 1 (истина).

Примеры отношений и логических операций:

4 < 9 ( ≡ true)

3 = = 5 ( ≡ false)

3 != 5 || 3==5 ( ≡ true)

(3+4>5) && (3+5>4) && (4+5>3) ( ≡ true )

Стандартная форма оператора  if  с составными операторами следующая:

if  (выражение)  {

  последовательность операторов

}

else  {

  последовательность операторов

}

Если выражение истинно (любое значение, кроме 0), выполняется блок операторов, следующий за  if; иначе выполняется блок операторов, следующий за  else. Всегда выполняется код, ассоциированный или с  if,  или с  else, но никогда не выполняются оба кода одновременно.

Лесенка  if-else-if

Типичной программистской конструкцией является лесенка  if-else-if . Она выглядит следующим образом:

if  (выражение)

  оператор;

else if  (выражение)

  оператор;

else if  (выражение)

  оператор;

.

.

.

else

  оператор;

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

При написании программы в том же проекте делаем следующие действия:

  1.  В окне Workspace переходим на вкладку FileView в папке SourceFiles удаляем текущий файл(например a.cpp)

  1.  Cоздаем новый срр-файл(см. п. 6.1)

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

  1.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  2.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  3.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  4.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  5.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  6.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  7.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  8.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  9.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.
  10.  Написать программу для вычисления значения функции
    .
    Протестировать программу при различных значениях аргументов.


Лабораторная работа № 4

Тема «Программирование с использованием оператора switch»

  1.  Цель  работы

Получение  практических  навыков в работе c перечислениями и оператором принятия решения  switch.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Window
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.
  2.  Постановка  задачи

В старояпонском календаре принят 60-летний цикл, состоящий из пяти 12-летних подциклов. Подциклы обозначаются названиями цвета: зеленый, красный, желтый, белый и черный. Внутри каждого подцикла годы носят названия животных: крысы, коровы, тигра, зайца, дракона, змеи, лошади, овцы, обезьяны, курицы, собаки и свиньи. (1924 год – год зеленой крысы – был началом очередного цикла).

Написать программу, которая вводит номер некоторого года и печатает его название по старояпонскому календарю.

  1.  Содержание отчета

Постановка задачи.

Блок-схема алгоритма.

Текст программы.

Результаты выполнения программы.

  1.  Общие  сведения

Оператор  switch

Для выполнения многочисленных проверок в программах можно использовать конструкцию  if-else-if, но она очень трудна для восприятия и в нем легко запутаться. С этой целью в языке С есть оператор принятия решений  switch , выполняющий действия, основываясь на сравнении значения со списком констант символов или целых чисел. При обнаружении совпадения выполняется оператор или операторы, ассоциированные с данным значением. Оператор switch имеет следующий вид:

switch (выражение)  {

   case константа1 :

       последовательность операторов

 break;

  case константа2 :

       последовательность операторов

 break;

. . .

   case константаN :

       последовательность операторов

   default :

       последовательность операторов

}

Оператор default выполняется, если не найдено соответствий. default не обязателен и, его нет, то в случае отсутствия совпадений ничего не происходит. Когда обнаруживается совпадение, операторы, ассоциированные с соответствующим case, выполняются до тех пор, пока не встретится оператор break . В случае default (или последнего case, если отсутствует default), оператор switch заканчивает работу при обнаружении конца.

Следует знать о трех важных моментах оператора switch:

  1.  Оператор switch отличается от оператора if тем, что он может выполнять только операции проверки строгого равенства, в то время как if может вычислять логические выражения и отношения.
  2.  Не может быть двух констант в одном операторе switch, имеющих одинаковое значение. Конечно, оператор switch, включающий в себя другой оператор switch, может содержать аналогичные константы.
  3.  Если в операторе switch используются символьные константы, они автоматически преобразуются к целочисленным значениям.

Пример.

char sign;

int x, y, z;

switch (sign)  {

   case ‘‘ :  z = x-y;

      break;

   case ‘+’ :  z = x+y;

      break;

   case ‘*’ :  z = x*y;

      break;

   case ‘/’ :  z = x/y;

   case ‘%’ : z = x%y;

      break;

   default : printf(“Неизвестная операция\n”);

}

С технической точки зрения операторы break являются необязательными в операторе switch. Они используются для окончания работы последовательности операторов, ассоциированных с данной константой. Если оператор break отсутствует, продолжают выполняться операторы следующего раздела case, пока не будет достигнут оператор break или конец оператора switch. О константах выбора можно думать как о метках. Выполнение начинается с метки, соответствующей искомому значению и будет продолжаться, пока не будет достигнут break или конец оператора switch. Можно использовать пустые условия. Перепишем предыдущий пример в виде:

Пример.

char sign;

int x, y, z;

switch (sign)  {   

   case ‘%’ :

   case ‘‘ :  z = x-y;

   case ‘+’ :  z = x+y;

   case ‘*’ :  z = x*y;

   case ‘/’ :  z = x/y;

   default : printf(“Неизвестная операция\n”);

}

При работе с этим фрагментом будет происходить следующее:

1) при вводе символа sign = ‘%’ , будут  выполняться  операторы:  z = x-y;  z = x+y; z = x*y;  z=x/y и выводится сообщение “Неизвестная операция”;

2) при  вводе символа  sign = ‘+’ будут  выполняться  операторы:  z = x+y;  z = x*y; z = x/y  и  выводится сообщение “Неизвестная операция”;

3) при вводе символа  sign =’*’  будут выполняться операторы: z = x*y; z = x/y  и выводится сообщение “Неизвестная операция” и т. д.

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

switch (c)  {

   int  t;

   case  1:

.  .  .

}

или

switch (c)  {

      case  1:

      int  t;

.  .  .

}

6.3  Вложенные операторы  switch

Оператор switch может иметь среди последовательности операторов другой оператор switch. Даже если константы case внутреннего и внешнего операторов имеют одинаковые значения, не возникнет никакого конфликта. Например:

switch (x)  {

   case  1 :

      switch (y)  {

          case  0 : printf(“Ошибка! Деление на ноль.”);

                         Break;

          case  1 : process(x, y);

      }

      break;

   case  2 :

.  .   .


Лабораторная работа № 5

Тема «Оператор цикла for. Логические и поразрядные операции.»

  1.  Цель  работы
    1.  Получение навыков в использовании оператора цикла for.
    2.  Знакомство с итерационными процессами.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  IBM  PC/286  и более поздних моделей.
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.
  2.  Постановка  задачи

Составить таблицу значений функции. Результат вывести на экран.

  1.  Содержание отчета

5.1. Тема и цель работы.

5.2. Схема алгоритма решения задачи.

5.3. Текст программы.

5.4. Результаты выполнения программы.

  1.  Общие  сведения

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

  1.  Оператор for

Стандартный вид цикла  for  следующий:

for (инициализация; условие; увеличение) оператор;

Оператор  for  имеет три главные части:

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

Эти три важные части должны разделяться точкой с запятой. Цикл for работает до тех пор, пока условие истинно. Когда условие становится ложным, выполнение программы продолжается с оператора, за циклом for.

В нижеприведенном примере осуществляется вывод чисел от 1 до 100 включительно:

#include <stdio.h>

main()

{

 int  x;

 for (x=1; x<=100; x++)  printf(“%d  “, x);  }

В данной программе переменная х изначально установлена в 1. Поскольку х меньше 100, вызывается  printf(), после чего х увеличивается на 1 и проверяется условие: по-прежнему ли х меньше либо рано 100. Данный процесс продолжается до тех пор, пока х не станет больше 100, и в этот момент цикл прервется. В данном примере х является переменной цикла, которая изменяется и проверяется на каждой итерации цикла.

Ниже приведен пример цикла  for, повторяющего сразу несколько операторов:

for (x=100; x!=65; x=5)  {

  z = sqrt(x);

  printf(“%d,  %f”, x, z);

}

Как  sqrt(), так и printf(), вызываются и выполняются, пока х не равно 65. Обратим внимание, что в цикле переменная  х  уменьшается: сначала она получает значение 100 и на каждой итерации цикла происходит уменьшение на 5.

Важно понять, что в цикле for проверка условия выполняется в самом начале. Это означает, что код в цикле может вообще не выполняться, если условие изначально ложно. Например:

x = 10;

For (y=10; y!=x; ++y)  printf(“%d”, y);

printf(“%d”, y);

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

  1.  Вариации  цикла  for

Имеется еще несколько вариаций оператора  for, увеличивающие его мощь и гибкость в некоторых ситуациях.

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

for  (x = 0, y = 0; x +y < 10; ++x)  {

   scanf(“%d”, y);

   . . .

}

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

Другой пример использования нескольких переменных цикла можно найти в показанной ниже функции reverse(). Она предназначена для копирования значения первого строкового аргумента в второй строковый аргумент в обратном порядке. Например, если функция вызывается с параметром  “hello” для s, то после окончания работы функции r получит “olleh”:

/* Копирование  s  в  r  в обратном порядке  */

reverse(char  *s, char  *r)

{

  int i, j;

  for (i = strlen(s) – 1, j = 0; i >= 0; j++, i)  r[i] = s[j];

  r[j] = ‘\0’;      /* присоединение завершающего символа */

}

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

 sign_on()

{

  char  str[20];

  int  x;

  for  (x = 0;  x <3  && strcmp(str, “password”); ++x)  {

      printf(“Введите пароль: “);

  gets(str);

  }

  if (x= =3)  hang_up();

}

Надо помнить, что  strcmp() – это стандартная библиотечная функция, выполняющая сравнение двух строк и возвращающая  0  в случае совпадения.

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

#include  <stdio.h>

int  readnum(), prompt();

int  sqrnum(int  num);

main()

{

  int  t;

  for  (prompt(); t = readnum(); prompt())  sqrnum(t);

}

int  prompt()

{

  printf(“:  “);

}

int readnum()

{

  int  t;

  scanf(“%d”, &t)

  return t;

}

int  sqrnum(int  num)

{

  printf(“%d\n”, num*num);

}

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

Еще один интересный момент цикла  for – это необязательность наличия какой-либо части. Практически можно опустить любую часть. Например, следующий цикл работает до тех пор, пока не будет введено число 123:

for  (x = 0; x != 123; ) scanf(“%d”, &x);

Обратим внимание, что часть увеличения отсутствует. Это означает, что на каждой итерации цикла  х  проверяется на совпадение с числом 123, но больше ничего не выполняется. Если ввести с клавиатуры число 123, условие станет ложным и цикл прекратится.

Часто можно видеть часть инициализации вне оператора  for. Это встречается, когда начальное состояние переменной цикла вычисляется неким сложным образом. Например:

gets(s);   /*  чтение строки в s  */

if (*s) x = strlen(s);   /*  вычисление длины строки  */

for (  ; x < 10;  )   {

   printf(“%d”, x);

   ++x;

}

Здесь инициализация пуста и  х инициализируется до входа в цикл.

  1.  Бесконечный  цикл

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

for  (  ;  ;  ) printf(“ this loop will run forever. \n”);

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

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

for (  ;  ;  )   {

  ch = getchar() ;    /*  ввод  символа  */

  If  (ch = = ‘A’)  break;    /*  выход  из  цикла  */

}

printf(“Введен  символ  A”);

Цикл будет работать до тех пор, пока на клавиатуре не будет набран символ «А».

  1.  Циклы  for  без тела

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

Одной из наиболее типичных задач программирования является удаление побелов из потока ввода. Например, база данных может допускать запрос типа «покажите весь баланс меньше, чем 400». Базе данных необходимо иметь каждое слово запроса отдельно, без пробелов. То есть процессор ввода в базу данных распознает команду «покажите», но не распознает «  покажите». Следующий цикл удаляет все пробелы из потока, на который указывает  str:

for  (  ; *str = = ‘  ‘ ; str++) ;

Как видно, в цикле отсутствует тело.

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

for (t = 0;  t < SOME_VALUE;  t++) ;

Вариант 1

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где а, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац ИЛИ Вц) И (Ац ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И и ИЛИ — поразрядные. Значения а, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 2

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац И Вц) ИЛИ (Вц И Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

ВариантЗ

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

Ац И (Вц ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант4

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

Ац ИЛИ Вц ИЛИ Сц

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операция ИЛИ — поразрядная. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 5

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац ИЛИ Вц) И Сц

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 6

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац И Вц) ИЛИ (Ац И Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 7

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац ИЛИ Вц) МОД2 (Ац ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И, ИЛИ и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 8

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац МОД2 Вц) И НЕ(Ац ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И, ИЛИ и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант  9

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

НЕ(Ац ИЛИ Вц) И (Вц ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции НЕ, И и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 10

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где а, 0, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

НЕ(Ац ИЛИ Вц) И (Ац МОД2 Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции НЕ, И, ИЛИ и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 11

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где о, 6, с — действительные числа.

Функция F должна принимать действительное значение, если выражение (Ац И Вц) МОД2 Сц

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 12

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где я, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац ИЛИ Вц) И Сц

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений о, b, с, операции И и ИЛИ - поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 13

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац ИЛИ Вц) МОД2 (Вц И Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции И, ИЛИ и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 14

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац МОД2 Вц) ИЛИ (Ац МОД2 Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции ИЛИ и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 15

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, t>, с — действительные числа.

Функция F должна принимать действительное значение, если выражение НЕ(Ац ИЛИ Вц ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции НЕ и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант16

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение (Ац МОД2 Вц) И НЕ(Ац ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции НЕ, И, ИЛИ и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 17

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение (Ац ИЛИ Вц) И HE(Au ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции НЕ, И и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 18

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение

НЕ(Ац И Вц И Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции НЕ и И — поразрядные. Значения а, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 19

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с, dдействительные числа.

Функция F должна принимать действительное значение, если выражение

(Ац МОД2 Вц) ИЛИ (Ац МОД2 Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции ИЛИ и МОД2 (сложение по модулю 2) — поразрядные. Значения a, b, с, d, Хнач., Хкон., dX ввести с клавиатуры.

Вариант 20

Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон. с шагом dX.

где a, b, с — действительные числа.

Функция F должна принимать действительное значение, если выражение НЕ(Ац ИЛИ Вц) И НЕ(Ац ИЛИ Сц)

не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a, b, с, операции НЕ, И и ИЛИ — поразрядные. Значения a, b, с, Хнач., Хкон., dX ввести с клавиатуры.

Задание 2. ЦИКЛИЧЕСКИЙ ВЫЧИСЛИТЕЛЬНЫЙ ПРОЦЕСС
КОНЕЧНЫЕ СУММЫ И ПРОИЗВЕДЕНИЯ

  1.  Вычислить значение конечной суммы: .
  2.  Вычислить значение конечной суммы: .
  3.  Вычислить значение конечной суммы: .
  4.  Вычислить значение конечной суммы: .
  5.  Вычислить значение конечной суммы: .
  6.  Вычислить значение конечной суммы: .
  7.  Вычислить значение конечного произведения: .
  8.  Вычислить значение конечного произведения: .
  9.  Вычислить значение конечного произведения: .
  10.  Вычислить значение конечного произведения: .
  11.  Вычислить значение конечного произведения: .
  12.  Вычислить значение конечного произведения: .
  13.  Вычислить значение конечного произведения: .
  14.  Вычислить значение конечного произведения: .
  15.  Вычислить значение конечного произведения: .


Лабораторная  работа  № 6

Тема «Операторы цикла while и dowhile. Построение таблиц функций.»

  1.  Цель  работы
    1.  Получение навыков в использовании оператора цикла for.
    2.  Знакомство с итерационными процессами.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  IBM  PC/286  и более поздних моделей.
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.
  2.  Постановка  задачи

Составить таблицу значений функции, используя ее разложение в степенной ряд. Значение функции считать с точностью  . Результат вывести на экран.

  1.  Содержание отчета

5.1. Тема и цель работы.

5.2. Схема алгоритма решения задачи.

5.3. Текст программы.

5.4. Результаты выполнения программы.

  1.  Оператор цикла  while

Следующий итерационный оператор, доступный в С, - это while. Его стандартный вид следующий:

while (условие) оператор;

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

Следующий пример показывает процедуру, обрабатывающую ввод с клавиатуры, работающий, пока не будет введен символ А:

void wait_for_char(void);

{

  char  ch;

  ch = ‘\0’;     /*  инициализация  ch  */

  while (ch!=’A’)  ch = getchar();

}

Сначала  ch  устанавливается в 0. Цикл while начинается с проверки ch на равенство А. Поскольку ch инициализирован нулем, проверка условия выдаст истину и цикл начнется. При каждом нажатии клавиши на клавиатуре условие проверяется повторно. Если введено А, условие становится ложным и цикл прекращается.

Как и цикл  for, цикл  while сначала выполняет проверку, то есть тело цикла может вообще не выполняться. Благодаря этому можно не выполнять отдельные проверки перед циклом. Иллюстрацией этого является функция  pad(), добавляющая пробелы к концу строки до достижения предопределенной длины. Если строка уже имеет необходимую длину, то пробелы не будут добавляться:

void  pad(char *s,  int  length)

{

  int  l;

  l = strlen(s);               /* определение длины */

  while (l<length)  {

     s[l] = ‘  ‘;                /* вставка  пробела */

  }

  s[l] = ‘\0’;                  /* строки должны заканчиваться нулем */

}

Аргументами  pad()  являются  s – указатель на удлиняемую строку и  length – желаемая длина строки  s. Если строка s имеет длину, равную или больше length, то код внутри цикла выполняться не будет выполняться. Если длина строки s меньше чем  length, то  pad()  добавляет требуемое число пробелов к строке. Стандартная функция  strlen() возвращает длину строки.

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

void func1(void)

{

   int  working;

   working = 1;       /*  т. е.  истина  */

   while (working)   {

       working = process1();

       if  (working)

           working = process2();

       if (working)

           working = process3();

   }

}

Здесь любая из трех подпрограмм может вернуть ложь и вызвать остановку цикла.

В теле цикла может и не быть никаких операторов. Например:

while  ((ch = getchar())  != A’;

просто зацикливается до тех пор, пока с клавиатуры не введется буква  А..

  1.  Оператор  dowhile

В противоположность циклам for и while, сначала проверяющим условие, цикл dowhile проверяет условие в конце. То есть, цикл dowhile всегда выполняется, по крайней мере один раз. Стандартный вид цикла dowhile следующий:

do  {

  последовательность операторов;

}  while (условие);

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

Данный цикл  dowhile осуществляет чтение чисел с клавиатуры, пока одно из них станет меньше либо равно 100:

 do   {

    scanf(“%d”, &num);

 }  while (num > 100);

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

void  menu(void)

{

   char  ch;

   printf(“1. Проверка орфографии\n”);

   printf(“2. Корректировка ошибок орфографии\n”);

   printf(“3. Вывод ошибок орфографии на экран\n”);

 printf(“       Сделайте ваш выбор:  “);

 do  {

       ch = getche();     /* чтение клавиатуры  */

       switch (ch)   {

           case ‘1’ :

             check_spelling();

             break;

          case ‘2’ :

             correct_errors();

             break;

          case ‘3’ :

             display_errors();

             break;

       }

   }  while (ch!=’1’ && ch!=’2’ && ch=’3’);

}

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

  1.  Оператор  break

Оператор break имеет два назначения. Первое – это окончание работы оператора switch. Второе – это принудительное окончание цикла, минуя стандартную проверку условия. Данное значение здесь и рассматривается.

Когда оператор break встречается в теле цикла, цикл немедленно заканчивается и выполнение программы переходит на строку, следующую за циклом. Например:

#include  <stdio.h>

main(void)

{

  int  t;

  for (t=0; t<100; t++)   {

     printf(“%d “, t);

     if (t = = 10) break;

  }

}

Данная программа выводит числа от 0 до 10 включительно и заканчивает работу, поскольку break  вызывает немедленный выход из цикла, минуя условие  t < 100.

Оператор break вызывает выход из самого внутреннего цикла. Например:

 for (t=0;  t<100;  ++t)   {

     count = 1;

    for( ; ; )  {

                   printf(“%d  “, count);

                   count ++;

                   if (count = = 10)  break;

               }

}

выводит  числа от 1 до 10 включительно 100 раз. Каждый раз, когда встречается break, контроль передается внешнему циклу for.

  1.  Оператор  continue

Работа оператора continue чем-то похожа на работу оператора break. Но вместо форсированного окончания continue переходит с следующей итерации цикла, пропуская оставшийся код цикла. Например, следующая процедура выводит только положительные числа:

do  {

    scanf(“%d”, &x);

    if (x<0)  continue;

    printf(“%d  “,  x);

}   while (x != 100);

В циклах while и dowhile оператор continue вызывает переход к проверке условия и затем продолжает работу цикла. В случае for выполняется часть увеличения, затем проверяется условие и, наконец, выполняется само тело цикла. Предыдущий пример может быть изменен для вывода только 100 чисел следующим  образом:

for (t=0; t<100; ++t)   {

    scanf(“%d”, &x);

    if (x<0)  continue;

    printf(“%d  “, x);

}

  1.  Варианты  задания
  2.  Вводить последовательность чисел до тех пор, пока их сумма не достигнет М(М вводится и больше 0).Ввести, какое количество чисел составили искомую сумму (саму сумму тоже).
  3.  Вводить последовательность до тех пор, пока не встретятся 3 подряд идущих положительных числа. Тогда прервать ввод и сообщить, сколько во введенной последовательности было:

а) всего чисел,

б) положительных чисел,

в) отрицательных чисел.

  1.   Вычислить приближенное значение бесконечной суммы с точностью до =0,0001.
  2.  Вычислить приближенное значение бесконечной суммы с точностью до =0,05.
  3.  Вычислить приближенное значение бесконечной суммы с точностью до =0,00005.
  4.  Вычислить приближенное значение бесконечной суммы с точностью до =0,0001.
  5.  Вычислить приближенное значение бесконечной суммы с точностью до =0,001.
  6.  Вычислить приближенное значение бесконечной суммы с точностью до =0,005.
  7.  Вычислить приближенное значение бесконечной суммы с точностью до =0,0005.
  8.  Вычислить приближенное значение бесконечной суммы с точностью до =0,01.

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


Лабораторная  работа  № 7

Тема: «Обработка одномерных  массивов. Сортировка массивов»

  1.  Цель  работы

1.1 Получение  практических  навыков в работе с одномерными массивами.

1.2 Знакомство  с  алгоритмами  упорядочения.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.

  1.  Постановка  задачи

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

  1.  Содержание отчета.

Тема и цель работы.

Схема алгоритма решения.

Текст  программы.

 Результаты  счета.

  1.  Общие  сведения

Массив – это совокупность переменных одного типа, к которым обращаются с помощью общего имени. Доступ к отдельному элементу массива может осуществляться с помощью индекса. В языке С  все массивы состоят из соприкасающихся участков памяти. Наименьший адрес соответствует первому элементу, наибольший адрес соответствует последнему элементу. Массивы могут иметь одну или несколько размерностей.

5.1 Одномерный  массив

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

тип  имя_переменной[размер];

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

 общее число байт = sizeof (базовый тип)*число элементов;

У всех массивов первый элемент имеет индекс 0. Поэтому, если написать

 Char  p[10];

То будет объявлен массив символов из 10 элементов, причем эти элементы адресуются индексом от 0 до 9. Следующая программа вводит целочисленный массив с клавиатуры и выводит его на дисплей:

 #include  <stdio.h>

main ( )

{ const int n=10;

    int  x[n];    /* резервирует место для 10 целочисленных элементов  */

    int  t;

    for (t=0; t<n; ++t)

    {

       printf(“Введите  %d-й элемент массива: “, t+1);

       scanf(“%d”, &x[t]);

    }

    for (t=0; t<n; ++t)

       printf(“%d  “, x[t];

 }

В  языке  С  отсутствует проверка границ массивов. Можно выйти за один конец массива и записать значение в какую-либо переменную, не относящуюся к массиву, или даже в код программы. Работа по проверке границ массива возлагается на программиста. Например, следует убедиться, что массив символов, куда осуществляется ввод, имеет достаточную длину для принятия самой длинной последовательности символов.

Одномерные массивы – это на самом деле списки информации одного типа.

Создание указателя на массив

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

int  sample [10];

Можно создать указатель на первый элемент массива, используя имя  sample. Следовательно, следующий фрагмент присваивает переменной  р  адрес первого элемента массива  sample:

int  *p;

int  sample[10];

p = sample;

Можно также получить адрес первого элемента массива с помощью оператора  &. Например:

p = sample;

и

p = &sample[0];

Приводят к одинаковому результату. Тем не менее запись &sample[0] в профессиональных программах практически не встречается.

5.3 Индексация с помощью указателей

Указатели и массивы тесно связаны между собой. Как объяснялось выше, имя массива без индекса – это указатель на первый элемент массива. Пусть имеется массив

char  p[100];

Выражение

 p = = &p[0];

выдает истину, поскольку адрес первого элемента и адрес массива совпадают.

Справедливо и обратное. Любой указатель может быть проиндексирован, как будто это массив. Например:

int  *p,  i[10];

p = i;

p[5] = 100;     /*  присвоение с помощью индекса  */

*(p+5) = 100;    /*  присвоение с помощью арифметики с указателями  */

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

  1.   Сортировка  

Рассмотрим массив целых или вещественных чисел  a1, a2, …, an . Пусть требуется переставить элементы этого массива так, чтобы после перестановки они были упорядочены по неубыванию a1  a2  an или по невозрастанию  a1  a2  an . Эта задача называется задачей сортировки  или упорядочения массива. Для решения этой задачи можно воспользоваться, например, следующими алгоритмами:

а) Найти элемент массива, имеющий наименьшее (наибольшее) значение, переставить его с  первым элементом. Затем проделать то же самое, начав со второго элемента и так далее. (Сортировка выбором)

б) Последовательным просмотром чисел  a1, a2, …, an  найти наименьшее i такое, что  ai > ai+1  или  ai < ai+1 . Поменять  ai и  ai+1   местами, возобновить просмотр с элемента  ai+1  и так далее. Тем самым самое наибольшее или наименьшее число передвинется на последнее место. Следующие просмотры следует начинать опять сначала, уменьшая на единицу количество просматриваемых элементов. Массив будет упорядочен после просмотра, в котором участвовали только первый  и второй элементы. (Сортировка обменами)

в) Просматривать последовательно  a2, …, an  и каждый новый элемент  вставлять  на подходящее место в уже упорядоченную последовательность a1, …, ai-1  . Это место определяется последовательным сравнением   ai с упорядоченными элементами a1, …, ai-1  . (Сортировка простыми вставками)

г) Сравнить элементы  a1 и  a2 и, если a1 > a2  (или a1< a2),  то эти элементы переставить. Далее сравнить элементы  а2 и а3 и, если  а2 > a3 (или а2 < a3), то их переставить. Далее сравнить элементы а3 и а4 и так далее до элементов an-1 и  an включительно. Далее эти действия повторить, начиная опять с первого элемента. Последним является контрольный проход, при котором не будет перестановок элементов.  (Сортировка по методу пузырька)

  1.  Методические указания.

Примечание. Размерности массивов задаются именованными константами.

Вариант 1

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) сумму отрицательных элементов массива;

2) произведение элементов массива, расположенных между максимальным и минимальным элементами. Упорядочить элементы массива по возрастанию.

Вариант 2

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) сумму положительных элементов массива;

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

Вариант 3

В одномерном массиве, состоящем из n целых элементов, вычислить:

1) произведение элементов массива с четными номерами;

2) сумму элементов массива, расположенных между первым и последним нулевыми элементами.

Преобразовать массив таким образом, чтобы сначала располагались все положительные элементы, а потом — все отрицательные (элементы, равные 0, считать положительными).

Вариант 4

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) сумму элементов массива с нечетными номерами;

2) сумму элементов массива, расположенных между первым и последним отрицательными элементами.

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

Вариант 5

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) максимальный элемент массива;

2) сумму элементов массива, расположенных до последнего положительного элемента.

Сжать массив, удалив из него все элементы, модуль которых находится в интервале [a,b]. Освободившиеся в конце массива элементы заполнить нулями.

Вариант 6

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) минимальный элемент массива;

2) сумму элементов массива, расположенных между первым и последним положительными элементами.

Преобразовать массив таким образом, чтобы сначала располагались все элементы, равные нулю, а потом — все остальные.

Вариант 7

В одномерном массиве, состоящем из n целых элементов, вычислить:

1) номер максимального элемента массива;

2) произведение элементов массива, расположенных между первым и вторым нулевыми элементами.

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

Вариант 8

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) номер минимального элемента массива;

2) сумму элементов массива, расположенных между первым и вторым отрицательными элементами.

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

Вариант 9

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) максимальный по модулю элемент массива;

2) сумму элементов массива, расположенных между первым и вторым положительными элементами.

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

Вариант 10

В одномерном массиве, состоящем из n целых элементов, вычислить:

1) минимальный по модулю элемент массива;

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

Вариант 11

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) номер минимального по модулю элемента массива;

2) сумму модулей элементов массива, расположенных после первого отрицательного элемента.

Сжать массив, удалив из него все элементы, величина которых находится в интервале [a,b]. Освободившиеся в конце массива элементы заполнить нулями.

Вариант 12

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) номер максимального по модулю элемента массива;

2) сумму элементов массива, расположенных после первого положительного

элемента.

Преобразовать массив таким образом, чтобы сначала располагались все элементы, целая часть которых лежит в интервале [a,b], а потом — все остальные.

Вариант 13

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) количество элементов массива, лежащих в диапазоне от А до В;

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

Вариант 14

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) количество элементов массива, равных 0;

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

Вариант 15

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) количество элементов массива, больших С;

2) произведение элементов массива, расположенных после максимального по

модулю элемента.

Преобразовать массив таким образом, чтобы сначала располагались все отрицательные элементы, а потом — все положительные (элементы, равные 0, считать положительными).

Вариант 16

В одномерном массиве, состоящем из n вещественных элементов, вычислить: 1) количество отрицательных элементов массива;

2) сумму модулей элементов массива, расположенных после минимального по модулю элемента.

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

Вариант 17

В одномерном массиве, состоящем из n целых элементов, вычислить:

1) количество положительных элементов массива;

2) сумму элементов массива, расположенных после последнего элемента, равного нулю.

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

Вариант 18

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) количество элементов массива, меньших С;

2) сумму целых частей элементов массива, расположенных после последнего отрицательного элемента.

Преобразовать массив таким образом, чтобы сначала располагались все элементы, отличающиеся от максимального не более чем на 20%, а потом — все остальные.

Вариант 19

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) произведение отрицательных элементов массива;

2) сумму положительных элементов массива, расположенных до максимального элемента.

Изменить порядок следования элементов в массиве на обратный.

Вариант 20

В одномерном массиве, состоящем из n вещественных элементов, вычислить:

1) произведение положительных элементов массива;

2) сумму элементов массива, расположенных до минимального элемента.

Упорядочить по возрастанию отдельно элементы, стоящие на четных местах, и элементы, стоящие на нечетных местах.


Лабораторная  работа  № 8

Тема: «Обработка  двухмерных  массивов»

  1.  Цель  работы

Получение  практических  навыков в работе с двухмерными массивами.

  1.  Техническое обеспечение

2.1  Персональная  ЭВМ  типа   IBM  PC/386  и  позднее.

  1.  Клавиатура.
    1.  Дисплей.
    2.  Принтер.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.

  1.  Постановка  задачи

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

  1.  Содержание отчета.

5.1 Тема и цель работы.

5.2 Схема алгоритма решения.

5.3 Текст  программы.

5.4 Результаты  выполнения программы

  1.  Общие  сведения

Массив – это совокупность переменных одного типа, к которым обращаются с помощью общего имени. Доступ к отдельному элементу массива может осуществляться с помощью индекса. В языке С  все массивы состоят из соприкасающихся участков памяти. Наименьший адрес соответствует первому элементу, наибольший адрес соответствует последнему элементу. Массивы могут иметь одну или несколько размерностей.

  1.  Двухмерные  массивы

Язык  С  позволяет создавать многомерные массивы. Простейшим видом многомерного массива является двухмерный массив. Двухмерный массив – это массив одномерных массивов. Двухмерный массив объявляется следующим образом:

тип  имя_массива[размер1][размер2];

Следовательно, для объявления двухмерного массива целых чисел с размером 10 и 20 следует написать:

 int  d[10][20];

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

Для доступа к элементу в 3 строке 5 столбце массива  d  следует использовать

 d[2][4] (Не забываем что в массивах индексация начинается с нуля)

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

 Пример.

#include  <stdio.h>

#include <conio.h>

main()

{

  int  i, j, num[3][4];

  char  ch;

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

  {

      printf(“Введите элементы  %d строки: “, i+1);

      for (j=0; j<4; j++)

          scanf(“%d”, &num[i][j]);

   }

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

  {

     for (j=0; j<4; j++)

         printf(“%d  “, num[i][j]);

     printf(“\n”);

  }

  return 0;

}

Двухмерные массивы можно представить в виде матрицы, где первый индекс отвечает за строку, а второй – за столбец. Это означает, что правый индекс изменяется быстрее левого, если двигаться по массиву в порядке расположения элементов в памяти. На рисунке 1 показано графическое представление двухмерного массива в памяти.

[0][0]

[0][1]

[0][2]

[0][3]

[0][4]

[0][5]

[0][6]

[0][7]

[1][0]

[1][1]

[1][2]

[1][3]

[1][4]

[1][5]

[1][6]

[1][7]

[2][0]

[2][1]

[2][2]

[2][3]

[2][4]

[2][5]

[2][6]

[2][7]

[3][0]

[3][1]

[3][2]

[3][3]

[3][4]

[3][5]

[3][6]

[3][7]

[4][0]

[4][1]

[4][2]

[4][3]

[4][4]

[4][5]

[4][6]

[4][7]

Рисунок  1 – Размещение двухмерного массива в памяти

 

Задание 2.

1. Дана целочисленная прямоугольная матрица. Определить количество строк, не содержащих ни одного нулевого элемента;

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

3. Дана целочисленная квадратная матрица. Определить  произведение элементов в тех строках, которые не содержат отрицательных элементов;

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

5. Дана матрица размера 5 x 4. Написать программу для вычисления I нормы матрицы: .

6. Найти наибольший элемент матрицы А(5х3) и номер строки и столбца, в котором он находится.

7. Вычислить сумму элементов каждой строки матрицы Х(4х3), определить наименьшее значение этих сумм и номер соответствующей строки.

8. Найти наибольшие элементы каждой строки матрицы Х(4х5) и записать их в массив Y.

9. Найти наибольший элемент главной диагонали матрицы А(4х4) и вывести на экран все строку, в которой он находится.

10. В массиве M[6*4] все числа различны. В каждой строке находится минимальный элемент, затем среди этих чисел выбирается максимальное. Напечатать номер строки массива М, в которой расположено выбранное число.

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

1. Дана целочисленная прямоугольная матрица. Определить:

количество строк, не содержащих ни одного нулевого элемента;

максимальное из чисел, встречающихся в заданной матрице более одного раза.

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

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

3. Дана целочисленная прямоугольная матрица. Определить:

количество столбцов, содержащих хотя бы один нулевой элемент:

номер строки, в которой находится самая длинная серия одинаковых элементов.

4. Дана целочисленная квадратная матрица. Определить:

произведение элементов в тех строках, которые не содержат отрицательных элементов;

максимум среди сумм элементов диагоналей, параллельных главной диагонали матрицы.

5. Дана целочисленная квадратная матрица. Определить:

сумму элементов в тех столбцах, которые не содержат отрицательных элементов;

минимум среди сумм модулей элементов диагоналей, параллельных побочной диагонали матрицы.

6. Дана целочисленная прямоугольная матрица. Определить:

сумму элементов в тех строках, которые содержат хотя бы один отрицательный элемент;

номера строк и столбцов всех седловых точек матрицы.

Примечание. Матрица А имеет седловую точку Aij, если Aij является минимальным элементом в i-й строке и максимальным в j-ом столбце.

7. Для заданной матрицы размером 88 найти такие k, что k-я строка матрицы совпадает с k-м столбцом.

Найти сумму элементов в тех строках, которые содержат хотя бы один отрицательный элемент.

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

Найти сумму элементов в тех столбцах, которые содержат хотя бы один отрицательный элемент.

9. Соседями  элемента  Aij  в  матрице  назовем  элементы   Akl   с  i-1  k  i+1, j-1  l  j+1, (k, l) (i, j). Операция сглаживания матрицы дает новую матрицу того же размера, каждый элемент которой получается как среднее арифметическое имеющихся соседей соответствующего элемента исходной матрицы. Построить результат сглаживания заданной вещественной матрицы размером 1010.

В сглаженной матрице найти сумму модулей элементов, расположенных ниже главной диагонали.

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

Найти сумму модулей элементов, расположенных выше главной диагонали.

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

Найти количество строк, среднее арифметическое элементов которых меньше заданной величины.

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

13. Осуществить циклический сдвиг элементов прямоугольной матрицы на n элементов вправо или вниз (в зависимости от введенного режима). n может быть больше количества элементов в строке или в столбце.

14. Осуществить циклический сдвиг элементов прямоугольной матрицы размерности MN вправо на k элементов следующим образом: элементы 1-й строки сдвигаются в последний столбец сверху вниз, из него – в последнюю строку справа налево, из нее – в первый столбец снизу вверх, из него – в первую строку; для остальных элементов – аналогично.

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

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

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

Найти номер первого из столбцов, не содержащих ни одного отрицательного элемента.

17. Путем перестановки элементов квадратной вещественной матрицы добиться того, чтобы ее максимальный элемент находился в левом верхнем углу, следующий по величине – в позиции (2,2), следующий по величине – в позиции (3,3) и т. д., заполнив таким образом всю главную диагональ.

Найти номер первой из строк, не содержащих ни одного положительного элемента.

18. Дана целочисленная прямоугольная матрица. Определить:

количество строк, содержащих хотя бы один нулевой элемент;

номер столбца, в котором находится самая длинная серия одинаковых элементов.

19. Дана целочисленная квадратная матрица. Определить:

сумму элементов в тех строках, которые не содержат отрицательные элементы;

минимум среди сумм элементов диагоналей, параллельных главной диагонали матрицы.

20. Дана целочисленная прямоугольная матрица. Определить:

количество отрицательных элементов в тех строках, которые содержат хотя бы один нулевой элемент;

номера строк и столбцов всех седловых точек матрицы.

Примечание. Матрица А имеет седловую точку Aij, если Aij является минимальным элементом в i-й строке и максимальным в j-ом столбце.


Лабораторная  работа  № 9

Тема: «Обработка строк»

  1.  Цель  работы

Получение  практических  навыков в работе со строками.

  1.  Техническое обеспечение

2.1  Персональная  ЭВМ  типа   IBM  PC/386  и  позднее.

  1.  Клавиатура.
    1.  Дисплей.
    2.  Принтер.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.

  1.  Постановка  задачи

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

  1.  Содержание отчета.

5.1 Тема и цель работы.

5.2 Схема алгоритма решения.

5.3 Текст  программы.

5.4 Результаты  выполнения программы

  1.  Общие  сведения

Строки

Строка представляет собой массив символов, заканчивающийся нуль-символом. Нуль-символ — это символ с кодом, равным 0, что записывается в виде управляющей последовательности '\0'. По положению нуль-символа определяется фактическая длина строки. Строку можно инициализировать строковым литералом :

char str[10] = "Vasia";

// выделено 10 элементов с номерами от 0 до 9

// первые элементы - 'V .   'а',   's',   ' i',   'а’,   '\0'

При вводе строк функция cin считывает последовательность введенных символов до первого пробела.

Поэтому для ввода строк состоящих из нескольких слов, используется метод getline объекта cin, который считывает n-1 или менее символов и записывает их в строковую переменную.

Пример использования:

#include<iostream.h>

int main()

{ const int n=80;

char str[n];  //объявление  строки

cin.getline(str,n);  //ввод строки

cout<<s<<endl;  //вывод строки

return 0;

}

Функции работы со строками.

Находятся в библиотеке string.h

Действие

Вид функции

Пример использования

1.Присваивание строк

char  *strcpy (char  *str1, const char  *str2)

используется для копирования содержимого str2 в  str1.

Следующая фрагмент кода копирует “hello” в строку str:

 char str[80];

strcpy(str,”hello”);

2. Длина строки

size_t   strlen (const char  *str)

возвращает длину строки. При определении длины строки нулевой символ не учитывается.

Данный фрагмент кода выводит на экран число 5.

strcpy(s,”hello”);

int n;

n=strlen(s);

cout<<n;

3. Функция соединения строк

char  *strcat (char  *str1, const char  *str2)

конкатенирует (соединяет в цепочку) строку str1 и копию строки str2. Строка str2 остается в первоначальном виде.

#include <iostream.h>

#include <string.h>

int  main(void)

{ char s1[80],s2[80];

cin.getline(s1,80);

cin.getline(s2,80);

strcat(s2,s1);

cout<<s2<<endl;

return 0;}

4. Поиск символа в строке.

char  *strchr (const  char  *str,  int ch)

возвращает указатель на первое вхождение символа  ch  в строку, на которую указывает str. Если символ ch не найден, возвращается нулевой указатель NULL.

Следующая программа выведет строку ”is a test”:

#include <iostream.h>

#include <string.h>

int  main(void)

{char *p;

p = strchr(“this is a test”,’ ‘);

cout<<p<<endl;

return 0;

}

5. Сравнение строк

char  *strcmp ( char *str1, char *str2)

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

Число  Значение

Меньше 0  str1 меньше, чем str2

Равно  0  str1 равна  str2

Больше 0  str1  больше, чем str2

Следующая функция используется для проверки пароля

char s[80];

cout<<“Введи  пароль: “;

cin.getline(s,80);

if(strcmp(s, “pass”)) {

cout<<“Неправильный пароль.”;

}

6. Поиск подстроки в строке

char   *strstr (char  *str1, char *str2)

возвращает указатель на первое вхождение в строку, на которую указывает str1, строки, указанной str2 . Если совпадений не обнаружено, возвращается нулевой указатель  NULL.

char *p;

char s1[80],s2[80];

cin.getline(s1,80);

cin.getline(s2,80);

p = strstr(s1,s2)

if(p) cout<<”Входит s2 в s1”;

else cout<<”Не входит s2 в s1”;

7. Выделение слов в строке

char   *strtok (char  *str1, char *str2)

возвращает указатель на следующую лексему в строке, на которую указывает str1. Символы из строки, на которую указывает str2, используются как ограничители, определяющие лексему. Если лексема не найдена, то возвращается NULL.

#include <iostream.h>

#include <string.h>

int  main(void)

{char *p;

char s[80];

int i;

cin.getline(s,80);

//выделение слова

p = strtok(s," \n");

i=1;

cout<<i<<" "<<p<<endl;

while(p = strtok(NULL," \n"))

{ i++;

cout<<i<<" "<<p<<endl;

}

return 0;}

Задание 1

1)  Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Подсчитать количество слов в данной строке.

2)  Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Подсчитать количество слов в строке, начинающихся с буквы “с”.

3) Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Найти длину самого короткого слова.

4) Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Подсчитать количество букв “a” в каждом слове данной строки.

5)  Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Подсчитать количество слов из 3 букв в данной строке.

6)  Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Подсчитать количество слов в строке, заканчивающихся на буквы “а”.

7) Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Найти длину самого длинного слова.

8) Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Подсчитать количество слов, содержащих букву “a”.

9)  Дана строка, состоящая из n символов. Группы символов, разделенные пробелами (одним или несколькими) и не содержащие пробелов внутри себя, будем называть словами. Проверить упорядочены ли слова в алфавитном порядке.

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


Лабораторная  работа  № 11

Тема: «Работа с функциями, возвращающими значения. Передача параметров по значению»

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

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  IBM  PC/286  и более поздних моделей.
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.

  1.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.

  1.  Постановка  задачи

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

  1.  Содержание отчета

5.1. Тема и цель работы.

5.2. Схема алгоритма решения задачи.

5.3. Текст программы.

5.4. Результаты выполнения программы.

  1.  Общие  сведения

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

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

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

#include подключение библ. файлов

объявление функции

int main()

{

объявление локальных переменных

вызов функции

}

определение функции

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

 тип имя ([ список_параметров ]);

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

тип имя ([ список_паранетров ])

{ тело функции:

  1.  объявление локальных переменных
  2.  операторы
  3.  return [выражение]

}

Рассмотрим составные части определения.

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

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

имя ( список аргументов);

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

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

Пример №1Написать программу для вычисления числа вычитаний

#include <iostream.h>

int fact(int ); // объявление функции

int main()

{

int n, m,c;

cin >>n;

cin >>m;

cout <<”C=”<< fact(n)/(fact(m)*fact(n-m)); // вызов функции

return 0;

  }

int fact(int a)  // определение функции

{

int i,  p;

if(a==0|| a==1) return 1;

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

p=p*i;

return p; //возврат значения р в точку вызова

}

Задание 1.

1)  Даны отрезки a, b, c  и  d. Для каждой тройки этих отрезков, из которых можно построить треугольник, вычислить площадь этого треугольника и вывести на экран.

2)  Даны действительные числа x, y, z. Вычислить выражение .

  1.  Даны длины a, b и c сторон некоторого треугольника. Найти медианы треугольника, сторонами которого являются медианы исходного треугольника. (Замечание: длина медианы проведенной к стороне a, равна .)

4) Даны действительные числа a, b, c. Получить

.

5) Даны действительные числа  s, t. Получить  h(s, t) + max(h2(st, st), h4(st, s + t)) + h(1, 1) ,

где .

6)  Даны действительные числа  a0, a1, a2, a3. Получить для  x = 1, 2, 3, 4  значения  p(x +1) – p(x), где

 p(y) = a3y3 + a2y2 + a1y + a0.

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

8) Дано действительное число y. Получить ,       где     .

9) Для вещественного числа  a > 0  вычислить величину

.

Корни   вычислять с точностью   = 0.0001 по следующей итерационной формуле:

,

приняв за ответ приближение  yn+1, для которого  |yn+1 yn| < .

10) Даны действительные числа a, b, c. Получить

.

Задача 2.

Параметры функции

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

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

  •  по значению
  •  по адресу.

Передача по значению

Синтаксис при вызове имя_ф(имя_фактичекого_параметра);

при определении и объявлении  тип имя_ф(тип имя_формального_параметра);

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

Передача по адресу

Используется 2 синтаксиса

1. с помощью ссылки.

при вызове имя_ф(имя факт. парам);

при определении и объявлении  тип имя_ф(тип &имя форм параметра);

2. с помощью указателя 

при вызове имя_ф(&имя факт. парам);

при определении и объявлении  тип имя_ф(тип *имя форм параметра);

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

При передаче по адресу в качестве фактических параметров нельзя использовать выражения, а только имена переменных

#include <iostream.h>

void f(int , int* . int& ):

int main(){

int i = 1. j = 2, k= 3;

cout <<"i  j  k\n":

cout << i <<'  '<< j <<'  '<< k <<'\n';  //1 2 3

f(i, &j, k);

cout << i <<'  '<< j <<'  '<< k <<'\n'; //1 3 4

return 0;}

void f(int i. int* j. int& k){

i++;  (*j)++; k++;}

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

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

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

1.

2

3

4

5

6

7

8

9

10  

Пример нахождения рекуррентной формулы

 

Необходимо найти такой множитель, что зная предыдущее значение можно найти последующее,

т.е an=T*an-1

Т.к.

то

Действительно, из формулы видим a0=1

Находим а1(n=1):

Находим а2(n=2):


Лабораторная  работа  № 12

Тема: «Обработка массивов с использованием указателей. Передача одномерных массивов в функции. Шаблоны функций»

  1.  Цель  работы
    1.  Получение навыков в написании программ с использованием указателей.
    2.  Изучение динамических массивов.
    3.  Изучение механизма передачи массива в функцию и передачи параметров по ссылке.
    4.  Изучение способов использования шаблонов функций.
  2.  Техническое  обеспечение
    1.  Персональная  ЭВМ  IBM  PC/286  и более поздних моделей.
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.
  3.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.
  4.  Постановка  задачи

Дано несколько массивов чисел (типы массивов различны). Длины массивов вводятся пользователем. Требуется для каждого массива выполнить заданные действия.

  1.  Содержание отчета

5.1. Тема и цель работы.

5.2. Схема алгоритма решения задачи.

5.3. Текст программы.

5.4. Результаты выполнения программы.

  1.  Общие  сведения

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

#include  <iostream.h>

#include  <time.h>

#include  <stdlib.h>

void  display (float *, int );

float  minim (float *, int );

int main (void)

{

  float t[10];

int i;

  srand(time(NULL));

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

   t[i] = 20.*rand()/RAND_MAX-10;

  display (t,10);

  cout<<"min="<<minim(t,10)<<endl;

  return  0;

}

//функция вывода на экран массива

void display (float *a, int k)

{

  int  j;

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

   cout<< a[j]<<'\t';

cout<<endl;

}

//функция поиска минимального элемента массива

float  minim (float *a, int k)

{

int i;

float min=a[0];

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

{

 if(a[i]<min)

  min=a[i];

}

return min;

}

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

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

//функция ввода элементов массива

void input (float *a, int k)

{

  int  j;

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

   cin>> a[j];

}

Методические указания

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

Все результаты данных функций выводятся в основной функции.

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

Вариант 1

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) номер минимального по модулю элемента массива;

2) сумму модулей элементов массива, расположенных после первого отрицательного элемента.

3) Сжать массив, удалив из него все элементы, величина которых находится в интервале [a,b]. Освободившиеся в конце массива элементы заполнить нулями.

Вариант 2

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) номер максимального по модулю элемента массива;

2) сумму элементов массива, расположенных после первого положительного

элемента.

3) Преобразовать массив таким образом, чтобы сначала располагались все элементы, целая часть которых лежит в интервале [a,b], а потом — все остальные.

Вариант 3

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) количество элементов массива, лежащих в диапазоне от А до В;

2) сумму элементов массива, расположенных после максимального элемента.

3) Упорядочить элементы массива по убыванию модулей элементов.

Вариант 4

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) количество элементов массива, равных 0;

2) сумму элементов массива, расположенных после минимального элемента.

3) Упорядочить элементы массива по возрастанию модулей элементов.

Вариант 5

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) количество элементов массива, больших С;

2) произведение элементов массива, расположенных после максимального по

модулю элемента.

3) Преобразовать массив таким образом, чтобы сначала располагались все отрицательные элементы, а потом — все положительные (элементы, равные 0, считать положительными).

Вариант 6

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) количество отрицательных элементов массива;

2) сумму модулей элементов массива, расположенных после минимального по модулю элемента.

3) Заменить все отрицательные элементы массива их квадратами и упорядочить элементы массива по возрастанию.

Вариант 7

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) количество положительных элементов массива;

2) сумму элементов массива, расположенных после последнего элемента, равного нулю.

3) Преобразовать массив таким образом, чтобы сначала располагались все элементы, целая часть которых не превышает 1, а потом — все остальные.

Вариант 8

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) количество элементов массива, меньших С;

2) сумму целых частей элементов массива, расположенных после последнего отрицательного элемента.

3) Преобразовать массив таким образом, чтобы сначала располагались все элементы, отличающиеся от максимального не более чем на 20%, а потом — все остальные.

Вариант 9

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) произведение отрицательных элементов массива;

2) сумму положительных элементов массива, расположенных до максимального элемента.

3) Изменить порядок следования элементов в массиве на обратный.

Вариант 10

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) произведение положительных элементов массива;

2) сумму элементов массива, расположенных до минимального элемента.

3) Упорядочить по возрастанию отдельно элементы, стоящие на четных местах, и элементы, стоящие на нечетных местах.

Вариант 11

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) сумму отрицательных элементов массива;

2) произведение элементов массива, расположенных между максимальным и минимальным элементами.

3) Упорядочить элементы массива по возрастанию.

Вариант 12

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) сумму положительных элементов массива;

2) произведение элементов массива, расположенных между максимальным по модулю и минимальным по модулю элементами.

3) Упорядочить элементы массива по убыванию.

Вариант 13

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) произведение элементов массива с четными номерами;

2) сумму элементов массива, расположенных между первым и последним нулевыми элементами.

3) Преобразовать массив таким образом, чтобы сначала располагались все положительные элементы, а потом — все отрицательные (элементы, равные 0, считать положительными).

Вариант 14

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) сумму элементов массива с нечетными номерами;

2) сумму элементов массива, расположенных между первым и последним отрицательными элементами.

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

Вариант 15

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) максимальный элемент массива;

2) сумму элементов массива, расположенных до последнего положительного элемента.

3) Сжать массив, удалив из него все элементы, модуль которых находится в интервале [a,b]. Освободившиеся в конце массива элементы заполнить нулями.

Вариант 16

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) минимальный элемент массива;

2) сумму элементов массива, расположенных между первым и последним положительными элементами.

3) Преобразовать массив таким образом, чтобы сначала располагались все элементы, равные нулю, а потом — все остальные.

Вариант 17

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) номер максимального элемента массива;

2) произведение элементов массива, расположенных между первым и вторым нулевыми элементами.

3) Преобразовать массив таким образом, чтобы в первой его половине располагались элементы, стоявшие в нечетных позициях, а во второй половине — элементы, стоявшие в четных позициях.

Вариант 18

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) номер минимального элемента массива;

2) сумму элементов массива, расположенных между первым и вторым отрицательными элементами.

3) Преобразовать массив таким образом, чтобы сначала располагались все элементы, модуль которых не превышает 5, а потом — все остальные.

Вариант 19

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) максимальный по модулю элемент массива;

2) сумму элементов массива, расположенных между первым и вторым положительными элементами.

3) Преобразовать массив таким образом, чтобы элементы, равные нулю, располагались после всех остальных.

Вариант 20

Ввести и обработать два одномерных массива, содержащие соответственно n целых и m вещественных компонентов. Вычислить:

1) минимальный по модулю элемент массива;

2) сумму модулей элементов массива, расположенных после первого элемента, равного нулю.

3) Преобразовать массив таким образом, чтобы в первой его половине располагались элементы, стоявшие в четных позициях, а во второй половине — элементы, стоявшие в нечетных позициях.


Лабораторная  работа  № 13

Тема: «Обработка матриц с использованием указателей»

  1.  Цель  работы
    1.  Получение навыков в написании программ с использованием указателей.

1.2  Получение навыков программирования некоторых операций над матрицами с использованием указателей.

  1.  Техническое  обеспечение
    1.  Персональная  ЭВМ  IBM  PC/286  и более поздних моделей.
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.
  2.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.
  3.  Постановка  задачи

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

5. Содержание отчета

5.1. Тема и цель работы.

5.2. Схема алгоритма решения задачи.

5.3. Текст программы.

5.4. Результаты выполнения программы.

  1.  Общие  сведения

Многомерный массив в языке С – это массив массивов, т. е. Массив, элементами которого являются массивы. Например, двухмерный массив есть массив, элементы которого одномерные массивы

const int n=5,m=6;

int  arr [n][m];

Массив arr состоит из n элементов. Каждый элемент – одномерный массив размерностью m. В памяти массив arr расположен следующим образом:

. . .

Первый

массив

из m элем-тов

Второй

массив

из m элем-тов

. . .

n - й

массив

из m элем-тов

. . .

Рассмотрим, как осуществлять доступ к элементам многомерного массива через указатель. Сделаем это на примере массива arr.

Объявим указатель и свяжем его с массивом  arr

int *ptr;

ptr = &arr[0][0];

Необходимо получить доступ к элементу  arr[i][j], или к j-му элементу i-й строки массива arr. Последовательно это вычисляется так:  

адрес первого массива arr    - ptr

адрес j-го элемента i-й строки, ptr + i*m + j

т. е. элемента arr[i][j]

T.е. к элементу с индексами arr[i][j] можно обратиться  *( ptr + i*m + j) или ptr[i*m+j].

Пример.

/* Сложение  двух матриц */

void  add_matr(float *matr1, float *matr2, int  n, int m)

{

  int i,j;

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

     for (j = 0; j < m; j++)

      *(matr1+i*m+j)=*(matr1+i*m+j) +*(matr2+i*m+j);// или matr1[i*m+j]=matr1[i*m+j] + matr2[i*m+j];

   out_matr(matr1, m, n);

}

  1.  Некоторые операции над матрицами

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

/* Ввод   матрицы  по  строкам  */

void input_matr (float *matr, int  n, int m)

{

  int  i, j;

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

{

     cout<<“\nвведите  элементы “<<i + 1<<”-й  строки:  “ ;

     for(j = 0; j < m; j++)   

        cin>>matr[ i*m + j];

 }

}

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

/* Вывод матрицы по строкам *.

void  out_matr(float *matr, int n, int m)

{

  int i, j;

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

{

      for (j = 0; j < m; j++)

          cout<<(matr[i*m + j]<<”  “;

      cout<<endl;

  }

  cout<<endl;

}

Операции с константами сводятся к сложению или вычитанию элементов матрицы aij с константой, например  х, или умножению aij*х  или делению aij/х  на константу.

Транспонированной матрицей  называется  матрица, у  которой столбцы и строки меняются местами, т. е. из матрицы размера  mn получатся матрица размером nm. Например, для  матрицы   А размером 34  это:

 

 

Нетрудно заметить, что транспонирование матрицы реализуется с помощью соотношения  .

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

.

Таким образом, элемент  сij  матрицы  С = АВ есть сумма произведений элементов i-й строки матрицы  А  на соответствующие элементы  i-го столбца матрицы  В.

  1.  Методические указания

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

7.2  При вводе, выводе и обработке матриц использовать указатели на массивы

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

1. Даны квадратные матрицы  А  и  В порядка  n. Получить матрицу  С = АВ  ВА.

2. Дана квадратная матрица  А порядка  n. Получить матрицу АВ+B, где элементы матрицы  В  вычисляются по формуле:

 

3. Даны квадратные матрицы  А  и  В порядка  n. Получить матрицу  С = АТ  ВТA, где  АТ  и  ВТ – транспонированные матрицы.

4. Даны квадратные матрицы  А  и  В порядка  n. Получить произведение  АВТ 

5. Даны квадратные матрицы  А  и  В порядка  n. Получить матрицу  А2 + В2.

6. Даны квадратные матрицы  А,  В  и  С порядка  n. Получить матрицу  (А+В)С.

7. Дана квадратная матрица  А порядка  n. Получить  матрицу  АТВТ, где  АТ  и  ВТ – транспонированные матрицы, а элементы матрицы  В вычисляются по формуле:

 

8. Даны квадратные матрицы  А  и  В порядка  n. Получить матрицу  А(ВЕ) + С, где  Е – единичная матрица порядка n, а элементы матрицы  С вычисляются по формуле:

     i, j = 1, 2, …, n.

9. Дана матрицы  А  и  В  размера  mn . Получить матрицу  АТ + ВТ, где АТ и ВТ – транспонированные матрицы.

10. Дана  квадратная матрица А  порядка  m. Получить матрицы  0.5(A + AT) и 0.5(ААТ), где  АТ – транспонированная матрица.


Лабораторная  работа  № 14

Тема: «Создание меню. Массив указателей на функции»

  1.  Цель  работы
    1.  Получение навыков в написании программ с использованием массива указателей на функции.
    2.  Научиться составлять программу определения корня трансцендентного уравнения с заданной точностью различными методоми.
    3.  Получение навыков написания программы с использованием меню.
  2.  Техническое  обеспечение
    1.  Персональная  ЭВМ  IBM  PC/286  и более поздних моделей.
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.
  3.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.
  4.  Постановка  задачи

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

5. Содержание отчета

5.1. Тема и цель работы.

5.2. Схема алгоритма решения задачи.

5.3. Текст программы.

5.4. Результаты выполнения программы.

Общие  сведения

Решение уравнения методом деления отрезка пополам (бисекций)

Существуют различные методы решения уравнения f(x) = 0. Из простых методов назовем метод Ньютона, метод хорд и метод деления пополам. Последние два метода характеризуются медленной сходимостью, но реализация их проста.

Для этих двух методов существенно, чтобы функция была непрерывна и ограничена в заданном интервале [a, b], внутри которого ищется корень. Предполагается также, что f(a) и f(b) имеют разные знаки.

Рассмотрим подробнее один из этих методов, а именно метод деления пополам, так как по сравнению с методом хорд данный метод характеризуется большей сходимостью. Этот метод состоит в выполнении итераций, начиная с отрезка [a, b] на оси абсцисс на котором  функция меняет знак, т.е. имеется точка пересечения графика функции с осью х (рисунок  1).

При заданной точности    метод состоит из таких шагов:

  1.  Вычислить  f(a)  и  f(b).
  2.  Положить  c = (a + b)/2  и  вычислить  f(с).
  3.  Если  f(с) = 0, то принять в качестве решения значение с, вывести его и прекратить вычисления, иначе перейти к шагу  4.
  4.  Если f(c) и f(a) имеют одинаковые знаки, то заменить a на c.
  5.  Если f(c) и f(b) имеют одинаковые знаки, то заменить b на c.
  6.  Если |b  a|   ( - заданная погрешность вычислений), то принять в качестве решения последнее значение с, вывести его и прекратить вычисления, в противном случае перейти к шагу 2.

Для определения значения конца отрезка b, на котором функция меняет знак, при заданном значении начала отрезка а используют следующий итерационный алгоритм:

  1.  Задают начальное значение  х = a + h. Здесь h – это  заданный шаг изменения х.
  2.  Вычислить значения f(a) и f(x).

Если f(a) и f(x) имеют разные знаки, то принять b = x и прекратить вычисления, иначе принять x = x + h  и  перейти к шагу  2.

Решение нелинейного уравнения методом хорд

Рассматриваемый метод так же, как и метод деления отрезка пополам, предназначен для уточнения корня на интервале [a, b], на концах которого левая часть уравнения f(x) = 0  принимает разные знаки. Значение начала интервала а вводится с клавиатуры.

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

В качестве нового интервала для продолжения итерационного процесса выбираем тот из двух [a, x1] или [x1, b], на концах которого функция  f(x) принимает значения с разными знаками.

Заканчиваем процесс уточнения корня, когда расстояние между очередными приближениями станет меньше заданной точности 

|xnxn-1| <

Рисунок  1 – Метод  хорд

Уравнение прямой линии, проходящей через точки  fa = f(a)  и  fb = f(b), запишем в общем виде

 y(x) = kx + c .

Коэффициенты k и c уравнения этой прямой определим из условий

 fa = ka + c ,

 fb = kb + c .

Вычитая левые и правые части последних соотношений, получим

 ,       c = faka .

Точку пересечения прямой y(x) с осью абсцисс получим, приравнивая y(x) нулю

 (1)

или

 . (2)

Метод  Ньютона (метод касательных)

Рассмотрим графическую иллюстрацию метода (рисунок 1). Предположим, каким-либо методом определено начальное приближение    к корню. В точке  x0 вычислим левую часть решаемого уравнения  f0 = f (x0), а также производную в этой точке  f  (x0) = tg . Следующее приближение к корню найдем в точке  x1, где касательная к функции f (x), проведенная из точки (x0, f0) пересекает ось абсцисс. Затем считаем точку  х1  в качестве начальной и продолжаем итерационный процесс. Из рисунка 1 видно, что таким способом можно приближаться к корню х*. При этом расстояние между очередным  xk+1 и предыдущим  xk приближениями к корню будет уменьшаться. Процесс уточнения корня закончим, когда выполнится условие

 |xk+1xk| < ,

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

Рисунок  1 – Метод  Ньютона

Из геометрических соотношений рисунка 1  получим основную формулу метода Ньютона

 x1 = x0f (x0) / f  (x0) .

В общем виде для  k-го шага итерационного процесса  последнее соотношение принимает вид

 xk+1 = xk f (xk) / f  (xk) .

Массивы указателей на функцию

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

void  menu(void)

{

char  ch;

printf(“1. Проверка орфографии\n”);

 printf(“2. Корректировка  ошибок\n”);

 printf(“3. Вывод ошибок на экран\n”);

 printf(“Сделайте ваш выбор:  “);

 do  {

 ch = getche();      /* Чтение  клавиатуры  */

 switch (ch)   {

  case  ‘1’:

   check_spelling();

   break;

  case  ‘2’:

   correct_errors();

   break;

  case  ‘3’:

   display_errors();

   break;

 }

}  while (ch != ‘1’  &&  ch != ‘2’  &&  ch != ‘3’);

}

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

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

void  check_spelling (void), correct_errors (void), display_errors (void), quit (void);

int  menu (void);

void  (*options[ ]) (void)  =  {

check_spelling,

correct_errors,

display_errors,

quit

} ;

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

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

 #include  <stdio.h>

#include  <stdlib.h>

#include  <conio.h>

#include  <string.h>

void check_spelling (void), correct_errors (void), display_errors (void), quit (void);

int  menu (void);

void  (*options []) (void)  =  {

check_spelling,

correct_errors,

display_errors,

quit

} ;

int  main(void)

{

 int  i;

 i = menu () ;     /*  получение  выбора  пользователя  *.

 (*options [i]) ( ) ;   /*  выполнение  */

return  0;

}

int  menu (void)

{

char  ch;

do   {

 printf(“1. Проверка орфографии\n”);

 printf(“2. Корректировка  ошибок\n”);

 printf(“3. Вывод ошибок на экран\n”);

 printf(“4. В ы х о д\n”);

 printf(“Сделайте ваш выбор:  “);

 ch = getche();

 printf(“\n”);

}  while (!strchr (“1234”, ch));

return  ch – 49;     /* преобразование к целочисленному эквиваленту */

}

void check_spelling (void)

{

printf(“In  check_spelling”);

}

void correct_errors (void)

{

printf(“In  correct_errors”);

}

void  display_errors (void)

{

printf(“In  display_errors”);

}

void  quit (void)

{

printf(“In  quit”);

exit(0);

}

Программа работает следующим образом. Сначала на экран выводится меню и пользователь вводит число, соответствующее его выбору. Поскольку введенное число представлено в ASCII-коде, то необходимо вычесть  49 (ASCII-код цифры 0) для получения двоичного числа. Данное значение затем возвращается в main () и используется как индекс массива  options – массива указателей на функцию. После этого вызывается соответствующая функция. Строковая функция strchr (“1234”, ch) возвращает указатель на первое вхождение символа  ch  в строку “1234”.

  1.  Методические указания

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

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

7.4  За начальное приближение x0 принять найденное значение конца отрезка  b, на котором заданная функция  f (x)  меняет знак. Алгоритм определения этого значения приведен в методических указанияx 

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

1) Найти корень уравнения

 ex – 2x – 10 = 0

с точностью   = 10-4  при заданном значении начала отрезка  а = 0.

2) Найти корень уравнения

 0.1exsin2x + 0.5 = 0

с точностью  e = 10-4  при заданном значении начала отрезка  а = 5.

 3) Найти корень уравнения

 

с точностью  e = 10-4  при заданном значении начала отрезка  а = -2.

4) Найти корень уравнения

 e0.724x+0.3 – 2.831 = 0

с точностью  e = 10-4  при заданном значении начала отрезка  а = 0.

5) Найти корень уравнения

 x + 0.5sin x  + 1 =0

с точностью  e = 10-4  при заданном значении начала отрезка  а = -1.

6) Найти корень уравнения

 xcos x  = 0

с точностью  e = 10-5  при заданном значении начала отрезка  а = 0.

7) Найти корень уравнения

 1.4xx  = 0

с точностью  e = 10-5  при заданном значении начала отрезка  а = 0.

8) Найти корень уравнения

 0.5xln |x|  = 0

с точностью  e = 10-5  при заданном значении начала отрезка  а = -1.

9) Найти корень уравнения

 x3 + sin x – 3.5x + 1 = 0

с точностью  e = 10-5  при заданном значении начала отрезка  а = 0.

10) Найти корень уравнения

 

с точностью  e = 10-5  при заданном значении начала отрезка  а = 0.

11) Найти корень уравнения

 (4 + x2)(exe-x) = 18

с точностью  e = 10-5  при заданном значении начала отрезка  а = 1.

12) Найти корень уравнения

 3x2cos 2x = 1

с точностью  e = 10-5  при заданном значении начала отрезка  а = 0.

13) Найти корень уравнения

 

с точностью  e = 10-4  при заданном значении начала отрезка  а = 0.

14) Найти корень уравнения

      

с точностью  e = 10-5  при заданном значении начала отрезка  а = 0.

15) Найти корень уравнения

   

с точностью  e = 10-4  при заданном значении начала отрезка  а = 1.


Лабораторная  работа  № 15

Тема: «Передача функций в качестве параметра функций»

  1.  Цель  работы
    1.  Получение навыков в написании программ с использованием указателей на функции.
    2.  Научиться составлять программу вычисления определенного интеграла методам средних прямоугольников и методом трапеций.
  2.  Техническое  обеспечение
    1.  Персональная  ЭВМ  .
    2.  Клавиатура.
    3.  Дисплей.
    4.  Печатающее устройство.
  3.  Программное обеспечение
    1.  Операционная  система  Windows
    2.  Система программирования  Visual C++ версия 6.0 или Borland  C++ версия 3.1 и более поздние версии.
  4.  Постановка  задачи

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

  1.  Содержание отчета

5.1. Тема и цель работы.

5.2. Схема алгоритма решения задачи.

5.3. Текст программы.

5.4. Результаты выполнения программы.

  1.  Общие  сведения
    1.  . Указатели на функции

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

Адрес фу