А. Богатырев - Руководство полного идиота по программированию (на языке Си), страница 7
Описание файла
PDF-файл из архива "А. Богатырев - Руководство полного идиота по программированию (на языке Си)", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 7 страницы из PDF
Руководство полного идиота<br> по программированию (на языке Си)--------++-------|=======================||+-|---> текущий оператор z = 6;|z = мусор||y = 12|+------+---------+|main()||x = 7 | v = 333 |+-----------------------+-----------+------+---------+----СТЕК ВЫЗОВОВ ФУНКЦИЙГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ--------++-------|=======================||z=6||y = 12|+------+---------+|main()||x = 7 | v = 333 |+-----------------------+-----------+------+---------+----СТЕК ВЫЗОВОВ ФУНКЦИЙГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ------------------------------------------------------------------------Наконец, в точке /* C */ будет вызвана функция func().Рассмотрим точку /* #c */ в ней.--------++-------|=======================||x = 777;||func();||=======================||+-|---> текущий оператор func();|z=6||y = 12|+------+---------+|main()||x = 7 | v = 333 |+-----------------------+-----------+------+---------+----СТЕК ВЫЗОВОВ ФУНКЦИЙГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕВ данном месте нас интересует - какие переменные видимы?Видимы:func::x = 777::v= 333И все.::xзаслонен локальной переменной.main::y, main::z невидимы, так как находятсяне на вершине стека вызовов функций------------------------------------------------------------------------Многие функции более естественно выражаются через рекурсию.Хотя, часто это приводит к излишним вычислениям по сравнению с итерациями(то есть циклами).
Вот пример - числа Фибоначчи.int fibonacci(int n){if(n==1 || n==2) return 1;/* else */return fibonacci(n-1) + fibonacci(n-2);}void main(){printf("20ое число Фибоначчи равно %d\n", fibonacci(20));}Поскольку тут отсутствует массив для запоминания промежуточныхрезультатов, то этот массив на самом деле неявно моделируетсяв виде локальных переменных внутри стека вызовов функций.Однако этот способ плох - в нем слишком много повторяющихсяfile:///Volumes/WININSTALL/assets/materials_informatiks.html44/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)действий. Добавим оператор печати - и посчитаем, сколько разбыла вызвана fibonacci(1) ?int called = 0;int fibonacci(int n){if(n==1){called++;return 1;} else if(n==2)return 1;return fibonacci(n-1) + fibonacci(n-2);}void main(){printf("20ое число Фибоначчи равно %d\n", fibonacci(20));printf("fibonacci(1) была вызвана %d раз\n", called);}Она была вызвана...
2584 раза!14.c/* Рисуем хитрую геометрическую фигуру */#include <stdio.h>const int LINES = 15;void draw(int nspaces, int nstars, char symbol){int i;for(i=0; i < nspaces; i++)putchar(' ');for(i=0; i < nstars; i++)putchar(symbol);}void main(){int nline, nsym;char symbols[3];/* Массив из трех букв */symbols[0] = '\\';symbols[1] = 'o';symbols[2] = '*';for(nline=0; nline < LINES; nline++){for(nsym = 0; nsym < 3; nsym++)draw(nline, nline, symbols[nsym]);/* Переход на новую строку вынесениз функции в главный цикл */putchar('\n');}}15.c/* Задача:нарисовать таблицу видакоткоткоткошкаfile:///Volumes/WININSTALL/assets/materials_informatiks.htmlкошкакот45/6803.06.2015Андрей Богатырев. Руководство полного идиота<br> по программированию (на языке Си)коткоткошкакошкакот...Где идет последовательностькот, кот, кот, кошка, кошка...повторяющаяся много раз и располагаемая по 6 зверей в строку.*/#include <stdio.h>/* магическая строка *//* Объявление глобальных переменных.В данном случае - констант.*/int TOMCATS= 3;int CATS= 2;int ANIMALS_PER_LINEint LINES= 25;= 6;/* три кота *//* две кошки *//* шесть зверей в каждой строке *//* число выводимых строк *//* и нам понадобится еще одна переменная - общее число зверей.Ее мы вычислим через уже заданные, поэтому тут мы ее объявим...но вычислить что-либо можно только внутри функции.В нашем случае - в функции main().*/int ANIMALS;/* общее число зверей */int nth_in_line = 0;/* номер зверя в текущей строке *//* Эта переменная не может быть локальной в функции, так как* тогда она уничтожится при выходе из функции.
Нам же необходимо,* чтобы ее значение сохранялось. Поэтому переменная - глобальная.*//* Функция, которая считает число зверей в одной строкеи либо переводит строку, либо переводит печать вследующую колонку (табуляцией).*/void checkIfWeHaveToBreakLine(){nth_in_line++; /* текущий номер зверя в строке (с единицы) */if(nth_in_line == ANIMALS_PER_LINE){/* Если строка заполнена зверьми... */putchar('\n');/* новая строка */nth_in_line = 0; /* в новой строке нет зверей */} else {putchar('\t');/* в следующую колонку */}}void main(){int nanimal;int i;/* номер зверя *//* счетчик*/ANIMALS = ANIMALS_PER_LINE * LINES;nanimal = 0;while(nanimal < ANIMALS){for(i=0; i < TOMCATS; i++){/* Оператор printf() выводит СТРОКУ СИМВОЛОВ.СТРОКА заключается в двойные кавычки(не путать с одиночными для putchar().*/printf("кот");file:///Volumes/WININSTALL/assets/materials_informatiks.html46/6803.06.2015Андрей Богатырев. Руководство полного идиота<br> по программированию (на языке Си)nanimal++;/* посчитать еще одного зверя *//* и проверить - не надо ли перейти на новую строку ? */checkIfWeHaveToBreakLine();}for(i=0; i < CATS; i++){printf("кошка");nanimal++;/* посчитать еще одного зверя *//* и проверить - не надо ли перейти на новую строку ? */checkIfWeHaveToBreakLine();}}/* putchar('\n'); */}16.c/*Та же задача, но еще надо печатать номер каждого зверя.Ограничимся пятью строками.*//* магическая строка */#include <stdio.h>int TOMCATS= 3;int CATS= 2;int ANIMALS_PER_LINEint LINES= 5;int ANIMALS;int nth_in_line = 0;= 6;/* три кота *//* две кошки *//* шесть зверей в каждой строке *//* число выводимых строк *//* общее число зверей *//* номер зверя в текущей строке */void checkIfWeHaveToBreakLine(){nth_in_line++;if(nth_in_line == ANIMALS_PER_LINE){putchar('\n');nth_in_line = 0;} elseprintf("\t\t");/* @ *//* Одинокий оператор может обойтись без {...} вокруг него */}void main(){int nanimal;int i;ANIMALS = ANIMALS_PER_LINE * LINES;nanimal = 0;while(nanimal < ANIMALS){for(i=0; i < TOMCATS; i++){/* Формат %d выводит значение переменной типа intв виде текстовой строки.Сама переменная должна быть в списке после формата(список - это перечисление переменных через запятую).Переменных ИЛИ выражений (формул).Давайте выводить по ДВЕ табуляции -file:///Volumes/WININSTALL/assets/materials_informatiks.html47/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)это место отмечено в функции checkIfWeHaveToBreakLine()как @.Еще раз внимание - один символ мы выводим какputchar('a');Несколько символов - какprintf("abcdef");Одиночные кавычки - для одной буквы.Двойные кавычки - для нескольких.*/printf("кот%d", nanimal);nanimal++;checkIfWeHaveToBreakLine();}for(i=0; i < CATS; i++){printf("кошка%d", nanimal);nanimal++;checkIfWeHaveToBreakLine();}}}17.c/* Задача: напечатать корни из чисел от 1 до 100.Новая информация:Нам понадобится новый тип данных - ДЕЙСТВИТЕЛЬНЫЕ ЧИСЛА.Это числа, имеющие дробную часть (после точки).Как мы уже знаем, целые - это int.буква - это char.действительное число - это double.(есть еще слово float, но им пользоваться не рекомендуется).Для вычисления корня используется итерационный алгоритм Герона.q = корень из x;q[0] := x;q[n+1] := 1/2 * ( q[n] + x/q[n] );Главное тут не впасть в ошибку, не клюнуть на q[n] и незавести массив.
Нам не нужны результаты каждой итерации,нам нужен только конечный ответ. Поэтому нам будет вполнедостаточно ОДНОЙ, но изменяющейся в цикле, ячейки q.*/#include <stdio.h>/* Еще одно новое ключевое слово - const. Обозначает константы.В отличие от переменных, такие имена нельзя изменять.То есть, если где-то потом попробовать написать epsilon = ... ;то это будет ошибкой.*/const double epsilon = 0.0000001;/* точность вычислений *//* Функция вычисления модуля числа */double doubleabs(double x){file:///Volumes/WININSTALL/assets/materials_informatiks.html48/6803.06.2015Андрей Богатырев. Руководство полного идиота<br> по программированию (на языке Си)if(x < 0) return -x;elsereturn x;}/* Функция вычисления квадратного корня */double sqrt(double x){double sq = x;/* Такая конструкция есть просто склейка двух строк:double sq;sq = x;Называется это "объявление переменной с инициализацией".*/while(doubleabs(sq*sq - x) >= epsilon){sq = 0.5 * (sq + x/sq);}return sq;}void main() {int n;for(n=1; n <= 100; n++)printf("sqrt(%d)=%lf\n",n, sqrt((double) n));}/*Здесь в операторе printf() мы печатаем ДВА выражения.ФОРМАТЗНАЧЕНИЕ------------%d-n%lf-sqrt((double) n)По формату %d печатаются значения типа int.По формату %c печатаются значения типа char.По формату %lf (или %g) печатаются значения типа double.Что значит "напечатать значение выражения sqrt(xxx)" ?Это значит:- вызвать функцию sqrt() с аргументом, равным xxx;- вычислить ее;- возвращенное ею значение напечатать по формату %lf,то есть как действительное число.Заметьте, что тут возвращаемое значение НЕ присваиваетсяникакой переменной, мы не собираемся его хранить.Точно так же, как в операторе x = 12 + 34;12 и 34 не хранятся ни в каких переменных,а операторprintf("%d\n", 12);печатает ЧИСЛО 12, а не переменную.Точно так же, как можно писатьdouble z;file:///Volumes/WININSTALL/assets/materials_informatiks.html49/6803.06.2015Андрей Богатырев.