А. Богатырев - Руководство полного идиота по программированию (на языке Си), страница 4
Описание файла
PDF-файл из архива "А. Богатырев - Руководство полного идиота по программированию (на языке Си)", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 4 страницы из PDF
*/void drawOneLine(int nspaces, int nsymbols){int i;for(i=0; i < nspaces; i++)putchar(' ');for(i=0; i < nsymbols; i++)putchar('+');putchar('\n');}void main(){int nline;/* номер строки */for(nline=0; nline < LINES; nline++)drawOneLine(LINES - nline - 1, nline*2 + 1);/* Мы нарисовали треугольник.Теперь нам нужен перевернутый треугольник.Пишем цикл по убыванию индекса.С данного места номера строк отсчитываются в обратном порядке:от LINES-2 до 0*/for(nline=LINES-2; nline >= 0; nline--)drawOneLine(LINES - nline - 1, nline*2 + 1);}file:///Volumes/WININSTALL/assets/materials_informatiks.html23/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)11.c/* А теперь рисуем ромб, используя математические формулы. */#include <stdio.h>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);putchar('\n');}void main(){int LINES = 21;int MIDDLELINE = LINES/2 + 1;int nline;/* середина ромба */for(nline=0; nline < MIDDLELINE; nline++)draw(MIDDLELINE - nline -1, nline*2+1, 'A');/* У следующего цикла for() нет инициализацииначального значения индекса.Начальное nline наследуется из предыдущего цикла,таким, каким оно осталось после его окончания, то естьравным MIDDLELINE.*/for( ; nline < LINES; nline++)draw(nline - MIDDLELINE + 1, (LINES - 1 - nline) * 2 + 1, 'V');}* 12_ARRAYS.txt *МАССИВЫМассив - это несколько пронумерованных переменных,объединенных общим именем.Все переменные имеют ОДИН И ТОТ ЖЕ ТИП.Рассмотрим ПОЛКУ с N ящиками,пусть имя полки - var.Тогда кажждый ящик-ячейка имеет имяvar[0]var[1]...var[N-1]Нумерация идет с НУЛЯ.-------/ var ///------------------------------------------- -----------------file:///Volumes/WININSTALL/assets/materials_informatiks.html24/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)|||||||||| .... ... ||||||||------------------------------------------- -----------------/ var[0] / / var[1] / / var[2] // var[N-1] /----------------------------------Массив объявляется так:int var[N];здесь N - его размер, число ячеек.Это описание как бы объявляет N переменных типа int с именамиvar[0] ... var[N-1];В операторах для обращения к n-ому ящичку (где 0 <= n < N)используется имя ящикаvar[n]где n - целое значение (или значение целой переменной,или целочисленного выражения), "индекс в массиве".Эта операция [] называется "индексация массива".Индексация - есть ВЫБОР одного из N ящиков при помощи указания целого номера.var- массив (N ячеек)n- выражение (формула), выдающая целое значение в интервале 0..N-1var[n] - взят один из элементов массива. Один из всех.n- номер ящика - называется еще и "индексом" этой переменной в массиве.Пример:int var[5];/* 1 */var[0] = 2;var[1] = 3 + var[0];var[2] = var[0] * var[1];var[3] = (var[0] + 4) * var[1];/* 2 *//* 3 *//* 4 *//* 5 */printf("var третье есть %d\n", var[3]);В ходе этой программы элементы массива меняются таким образом:/* 1 *//* 2 *//* 3 *//* 4 *//* 5 */var[0]var[1]var[2]var[3]var[4]-----------------------------------------------мусормусормусормусормусор2мусормусормусормусор25мусормусормусор2510мусормусор251030мусорКак видим, каждый оператор изменяет лишь ОДНУ ячейку массива за раз.Массив - набор переменных, которые не ИМЕНОВАНЫ разными именами,вроде var0, var1, var2, ...а ПРОНУМЕРОВАНЫ под одним именем:var[0], var[1], var[2], ...Индекс - часть ИМЕНИ ПЕРЕМЕННОЙ.На самом деле индексация - это1) выбор элемента в массиве2) справа от присваиваний и в выражениях - еще и разыменование,file:///Volumes/WININSTALL/assets/materials_informatiks.html25/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)то есть взятие вместо имени переменной - значения, в ней хранящегося.--------------------------------------------------------------------Если в переменную не было занесено значение,а мы используем эту переменную,то в ней лежит МУСОР (любое, непредсказуемое значение).printf("var4 есть %d\n", var[4]);напечатает все что угодно.Поэтому переменные надо всегда инициализировать(давать им начальное значение).Глобальные переменные автоматически инициализируются нулем,если мы не задали иначе.Локальные переменные не инициализируются автоматически, и содержат МУСОР.--------------------------------------------------------------------Массивы НЕЛЬЗЯ присваивать целиком, язык Си этого не умеет.int a[5];int b[5];a = b; /* ошибка */Также нельзя присвоить значение сразу всем элементам (ячейкам) массива:a = 0; /* ошибка */не делает того, что нами ожидалось, а является ошибкой.Для обнуления всех ячеек следует использовать цикл:int i;for(i=0; i < 5; i++)a[i] = 0;/* для каждого i присвоить a[i] = 0; */--------------------------------------------------------------------СВЯЗЬ МАССИВОВ И ЦИКЛОВ=======================Вследствие этого массивы приходится копировать (и инициализировать)поэлементно, в цикле перебирая все (или часть) ячейки массива.int i;for(i=0; i < 5; i++)a[i] = b[i];В данном случае индекс цикла служит также и индексом в массиве.Индексы в массиве идут с НУЛЯ.Пример инициализации:int index, array[5];for(index=0; index < 5; index++)array[index] = index * 2 + 1;илиint index, array[5];file:///Volumes/WININSTALL/assets/materials_informatiks.html26/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)index = 0;while(index < 5){array[index] = index * 2 + 1;index++;}/* В массиве будет: { 1, 3, 5, 7, 9 } */ИНДЕКСдля массивов номер "ящика/ячейки" в массиве.для циклов номер повторения цикла, счетчик.Мы должны изменять его САМИ.Обычно массивы и циклы совмещаются так:индекс цикла есть индекс в массиве;то есть индекс цикла используется для перебора всехэлементов массива:int a[N], i;for(i=0; i < N; i++)...a[i]...--------------------------------------------------------------------Примеры:int a[5];a[0] = 17;a[0] += 4;a[0]++;--------------------------------------------------------------------Пример: числа Фибоначчи.Задаются математическими формулами:f[1] = 1f[2] = 1f[n+2] = f[n+1] + f[n]Вот программа:-----------------#include <stdio.h>#define N 20/* магическая строка *//* сколько первых чисел посчитать */void main(){int fibs[N], index;fibs[0] = 1;fibs[1] = 1;/* индексы отсчитываются с нуля!!! *//* Тут показано, что индекс элемента массива может вычисляться */for(index=2; index < N; index++)fibs[index] = fibs[index-1] + fibs[index-2];/* Распечатка в обратном порядке */for(index = N-1; index >= 0; index--)printf("%d-ое число Фибоначчи есть %d\n",index+1,fibs[index]);}Здесь мы видим новый для нас оператор #definefile:///Volumes/WININSTALL/assets/materials_informatiks.html27/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)Он задает текстуальную ЗАМЕНУ слова N на слово 20,в данном случае просто являясь эквивалентомconst int N = 20;К несчастью размер массива не может быть задан при помощи переменной,а вот при помощи имени, определенного в #define - может.СТРОКИСтроки есть массивы БУКВ - типа char,оканчивающиеся спецсимволом \0char string[20];string[0] = 'П';string[1] = 'р';string[2] = 'и';string[3] = 'в';string[4] = 'е';string[5] = 'т';string[6] = '\0';printf("%s\n", string);%s - формат для печати СТРОК.Никакие другие массивы не могут быть напечатаныцеликом одним оператором.char string[20];string[0] = 'П';string[1] = 'р';string[2] = 'и';string[3] = 'в';string[4] = 'е';string[5] = 'т';string[6] = '\n';string[7] = '\0';/* Перевод строки - тоже буква */printf("%s", string);или даже простоprintf(string);Такие массивы можно записать в виде строки букв в ""char string[20] = "Привет\n";Оставшиеся неиспользованными символы массива от string[8] до string[19]содержат МУСОР.ПОЧЕМУ ДЛЯ СТРОК ИЗОБРЕЛИ СИМВОЛ "ПРИЗНАК КОНЦА"?=================================================Строка - это ЧАСТЬ массива букв.В разное время число букв в строке может быть различным,лишь бы не превышало размер массива (тогда случится сбой программы).Значит, следует где-то хранить текущую длину строки (число использованныхfile:///Volumes/WININSTALL/assets/materials_informatiks.html28/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)символов). Есть три решения:(1)В отдельной переменной. Ее следует передавать во всефункции обработки данной строки (причем она может изменяться).char str[32];/* массив для строки */int slen;/* брать первые slen букв в этом массиве */...func(str, &slen); /* ДВА аргумента для передачи ОДНОЙ строки */...Этот подход работоспособен, но строка разбивается на дваобъекта: сам массив и переменную для его длины. Неудобно.(2)Хранить текущую длину в элементе str[0],а буквы - в str[1] ... итд.Плохо тем, что в str[0] можно хранить лишь числа от 0 до 255,и если строка длиннее - то такой подход неприменим.(3)Не хранить длину НИГДЕ, а ввести символ-признак конца строки.Теперь вfunc(str);/* ОДИН аргумент - сам массив */передается только сам массив, а его текущая длина может бытьпри нужде вычислена при помощи некоей функции, вроде такой:int strlen(char s[]){int counter = 0;while(s[counter] != '\0')counter++;return counter;/* функция от массива букв/* счетчик и одновременно индекс*/*//* пока не встретился признак конца текста *//* посчитать символ*//* сколько символов, отличных от '\0' */}Тут никаких ограничений нет.
Именно этот подход и был избранв языке Си, хотя в принципе можно самому пользоваться и другими.На самом деле в языке есть такая СТАНДАРТНАЯ функция strlen(s)(вам не надо писать ее самому, ее уже написали за вас).--------------------------------------------------------------------ИНИЦИАЛИЗАЦИЯ ГЛОБАЛЬНОГО МАССИВА=================================Массив, заданный вне каких-либо функций, можно проинициализироватьконстантными начальными значениями:int array[5]= { 12, 23, 34, 45, 56 };char string[7] = { 'П', 'р', 'и', 'в', 'е', 'т', '\0' };Если размер массива указан БОЛЬШЕ, чем мы перечислим элементов,то остальные элементы заполнятся нулями (для int) или '\0' для char.int array[5] = { 12, 23, 34 };Если мы перечислим больше элементов, чем позволяет размер массива это будет ошибкой.int a[5] = { 177, 255, 133 };Операция индексации массива a[] дает:при nзначение выражения a[n] естьfile:///Volumes/WININSTALL/assets/materials_informatiks.html29/6803.06.2015Андрей Богатырев.
Руководство полного идиота<br> по программированию (на языке Си)--------------------------------------------1не определено (ошибка: "индекс за границей массива")01771255213330405не определено (ошибка)* 13_FUNCS.txt *КАК ПРОИСХОДИТ ВЫЗОВ ФУНКЦИИ============================Пусть у нас описана функция, возвращающая целое значение./* ОПРЕДЕЛЕНИЕ ФУНКЦИИ func(). *//* Где func - ее имя. Назвать мы ее можем как нам угодно. */int func(int a, int b, int c){int x, y;...x = a + 7;...b = b + 4;...return(некое_значение);}Здесьa, b, cx, y- аргументы функции (параметры)- локальные переменныеТочка вызова - находится внутри какой-то другойфункции, например функции main()main(){int zz, var;...var = 17;zz = func(33, 77, var + 3) + 44;...}Когда выполнение программы доходит до строкиzz = func(33, 77, var + 3) + 44;1) Происходит ВЫЗОВ ФУНКЦИИ func()(a)Этот пункт мы увидим ниже.(b)Создаются переменные с именами a, b, c, x, y;(c)Переменным-аргументам присваиваются начальные значения,которые берутся из точки вызова.В точке вызова перечислен список (через запятую) выражений (формул):func(выражение1, выражение2, выражение3)file:///Volumes/WININSTALL/assets/materials_informatiks.html30/6803.06.2015Андрей Богатырев.