//пример 77.
Определим минимальное значение из вводимой последовательности натуральных чисел:
int main ()
{
int a, min;
printf (" min\n");
printf (" input, exit - 0 \n");
printf ("->");
scanf ("%d", & a);
min = a;
while (a > 0)
{
if (a < min) min = a;
printf ("->");
scanf ("%d", & a);
}
printf ("min: ");
printf ("%i \n", min);
printf ("\n exit - <enter>\n");
_getch();
return 0;
}
//пример 78.
Для заданных n, целых чисел с1, с2,..., сn и s1, s2,..., sn вычислить:
![]() |
int main()
{ double proizv = 1.; //переменная для вычисления произведения
double c=0, c1, s = 0, s1; //переменные для числителя и знаменателя
int n;
cout <<"n="; cin >> n; //вводим количество сомножителей
for (int i = 1; i <= n; i++)
{
cout <<"\nc" << i << "= "; cin >> c1; //ввод значения для числителя
cout <<"\ns" << i << "= "; cin >> s1; //ввод значения для знаменателя
c += c1; //вычисление очередного числителя
s += s1; //вычисление очередного знаменателя
proizv *= c/s; //вычисление произведения
}
cout << "\nproizv= " << proizv << '\n';
_getch();
return 0;
}
-----------------------------------------------------------------------------------------
Оптимизация программы
Оптимизация – преобразование исходного текста программы, при котором:
• результат выполнения остается неизменным,
• улучшаются некоторые характеристики программы (время выполнения, затраты оперативной памяти, размер исходного кода).
Оптимальность программы в значительной степени определяется ее алгоритмом. При оптимизации программы необходимо выявить ее фрагменты, являющиеся «основными потребителями» ресурса, а затем перепрограммировать их: например, схема Горнера преобразовывает алгоритм с целью сокращения количества выполняемых операций.
Большинство компиляторов сегодня выполняют сами некоторые виды оптимизации программы. И тем не мене, отметим некоторые приемы:
- Выделять общие подвыражения и вычислять их отдельно.
- При вычислении сумм с использованием циклов, общий множитель (при его наличии) необходимо выносить из цикла: это уменьшает количество умножений и увеличивает точность вычислений:
summa=0; for (int j = 1; j <= 1000; j++) summa += a*x[i]; | summa=0; for (int j=1; j <= 1000; j++) summa += x[i]; summa *= a; Это лучше!!!!! Объяснить почему |
- При программировании вложенных циклов следует иметь в виду, что затраты процессорного времени на выполнение таких конструкций могут зависеть от порядка следования вложенных циклов. По возможности, следует делать цикл с наибольшим числом повторений самым внутренним, а цикл с наименьшим числом повторений – самым внешним:
for (int j = 1; j <= 100000; j++) for (int k = 1; k <= 1000; k++) a=1; | for (int k = 1; k <= 1000; k++) for (int j = 1; j <= 100000; j++) a=1; Это лучше!!!!! Объяснить почему |
- Ветвящийся алгоритм описать как совокупность непересекающихся ветвей: описывать каждую из ветвей максимально структурировано и компактно, в частности, оформляя последовательности операторов, выполняющих некоторые алгоритмы, в виде составных операторов или в виде функций; завершать каждую из ветвей подходящим оператором завершения (break, continue, return, exit()).
Рассмотрим нахождение корней квадратного уравнения, как пример оптимизации алгоритма с ветвлением:
aх2 + bx + c = 0 (a, b, c – вещественные)
if (! a &&! b &&! c) выведем на экран: “Корней бесконечно много”;
if (! a &&! b && c) выведем на экран: “Корней нет”;
if (! a && b) выведем на экран: “Один вещественный корень”;
d = b*b – 4*a*c; вычислим дискриминант
if (d >= 0) выведем на экран: “Вещественные корни:”;
и найдем корни:
d1= sqrt (d);
х1= (-b + d1) /(2 *a);
х2= (-b - d1) /(2 *a);
if (d < 0) выведем на экран: “Комплексные корни:”;
и вычислим их:
dk = -b / (2 * a); //действ.часть
mk = sqrt (-d) / (2 * a); //мним. часть
Рассмотрим структуру программы:
//каждая ветвь завершается оператором return
double a, b, c, d, d1, x1, x2, dk, mk;
……….
/*_1_*/
if (!a &&!b &&!c)
{
cout << “Корней бесконечно много”;
_getch();
return 1;
}
/*_2_*/
if (!a &&!b && c)
{ ….
return 2;
}
/*_3_*/
if (!a && b)
{ ….
return 3;
}
d = b*b – 4*a*c; //вычисление дискриминанта
/*_4_*/
if (d >= 0) // если действительные корни
{ ….
return 4;
}
/*_5_*/
// если комплексные корни:
d = -b / (2 * a); //действ.часть
m = sqrt (-d) / (2 * a); //мним. часть
Return 0;
Без оператора return последовательность прохождения операторов будет:
_1_ à _2_ à _3_ à _4_ à _5_
-----------------------------------------------------------------------------------------
Дополнительные возможности организации ввода/вывода
Ввод/вывод в стиле С
Данные играют в программировании ключевую роль. Исполнение программы, как правило, начинается с получения извне программы данных для обработки путем запроса и ввода их с клавиатуры, чтения из каких-нибудь специальных устройств, генерации с определенными свойствами, обращения за данными к другим функциям. В процессе работы или по завершении исполнения программы ее результаты должны быть отображены на экране и/или сохранены для последующего использования.
Средства ввода-вывода С были новаторскими по отношению к другим языкам программирования:
· Они были отделены от языка программирования и вынесены в отдельную стандартную библиотеку, получившую название <stdio.h> (<cstdio> в стандарте С++).
· Удалось разработать и реализовать концепцию ввода-вывода, независимого от устройств. Несмотря на то, что устройства ввода-вывода имеют разные характеристики, система ввода-вывода С предоставляет программисту единый удобный интерфейс. Для этого используется абстрактное понятие «поток», относящееся к любому переносу данных от источника к приемнику. Поток – последовательность символов. Программа имеет дело не с устройствами или с файлами, а с потоками. Ввод информации (чтение из потока, извлечение) осуществляется из входного потока, вывод (помещение или включение в поток) программа производит в выходной поток. А уж поток можно связать и с устройством, и с файлом.
Вывод строк в С обеспечивает функция int puts(char *str). Функция записывает в стандартный поток вывода stdout ("привязан" к экрану) строку по указателю str.
Например: puts("lab_rabota_1");
Строка str должна иметь завершающий символ (ограничитель) ’\0’. Функция записывает в поток всю строку, за исключением символа ’\0’, и добавляет в конец символ ’\n’. При обнаружении ошибки возвращается EOF.
Форматный вывод сообщений, значений переменных или выражений в стандартный поток вывода stdout в С обеспечивает функция int printf(const char *format, arg-list) (от англ. print formatted, «печать форматированная»). Функции передается переменное число аргументов, но первым аргументом всегда является форматная (управляющая) строка, задающая способ форматирования данных. Форматная строка может содержать текст и спецификации формата (преобразования), начинающиеся со знака %. Она определяет выводимый текст и формат вывода значений аргументов, указанных в качестве остальных параметров функции после форматной строки. Выводимые значения, в соответствии со спецификатором формата, переводятся из двоичного кода, в котором они хранятся в памяти компьютера, в символьный вид. Фактически, результат вывода – это содержание форматной строки, в которой спецификаторы формата заменены на выводимые значения, представленные в указанном виде.
Формат оператора вывода:
int printf("управляющая строка", арг1, арг2, ….);