58100

Система программирования

Научная статья

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

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

Русский

2014-05-26

103 KB

0 чел.

Титов В.К.

§ 0. Система программирования.

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

Для некоторых языков программирования существует несколько систем программирования. Так, например, на Си можно программировать в системе Visual C++ или в системе C++ Builder. Думаем, со временем вы будете работать в какой либо из этих систем или другой по вашему вкусу. Но для начала лучше выбрать самую простую систему программирования, чтобы не отвлекаться на более сложные средства, которые нам для начального обучения не будут нужны. Такой простейшей системой программирования для языка Си является система Borland C++ Version 3.1 (сокращенно: BC 3.1). Эту систему можно скачать из Интернета по адресу:

http://www. …                                                                                      

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

Для наших учебных целей не нужно даже знать всех возможностей системы BC 3.1. Достаточно пока знать, как транслируется и одновременно запускается готовая программа (в меню: Run , или на клавиатуре: Ctrl+F9) и как просматривается окно результата (в меню: Window/Output , или на клавиатуре: Alt+F5). Но перед тем как оттранслировать и запустить готовую программу нужно дать ей имя (в меню: File/Save as …). К вашему имени автоматически прибавится расширение имени .cpp или вы сами можете добавить это расширение к имени через точку. Если вы добавите к имени расширение .c ,  то транслятор будет считать вашу программу написанной на чистом Си без дополнительных возможностей, присущих Си++ (транслятор может выдавать ошибки, которые не считаются ошибками в Си++).

После трансляции правильно написанной программы порождается выполняемый файл с тем же именем, с которым программа была сохранена в исходном файле, но с расширением  .exe .  Например, если вы сохранили программу с именем  prog1.cpp , то после ее запуска появится файл с именем  prog1.exe . Этот файл является самостоятельной выполняемой программой и его можно запускать уже независимо от BC 3.1.


§ 1. Первые программы.

Программа 0.

  

main(){ }

Это самая короткая программа на Си. Но, к сожалению, она ничего не делает. Если запустить эту программу, то транслятор будет считать ее правильной (не найдет в ней существенных ошибок) и создаст для нее выполняемый файл. Но запуск этого файла, как уже выполняемой программы, не даст никакого результата. (Интересно, что файл исходного текста этой программы состоит всего из 8 байт (8 символов), а полученный после его трансляции выполняемый файл будет занимать место более чем в 1000 раз больше. Это объясняется тем, что даже маленькая программа должна содержать все, что необходимо для выполнения любой программы.)

Слово main (переводится: главная) должно присутствовать в каждой программе на Си и Си++. Так называется функция, с которой должно начаться выполнение всей программы. Но в данном случае эта функция пустая.

Программа 1.

 

#include<stdio.h>

main() { printf(“Мы начинаем изучать Си”); }

В первой строке include (переводится: включить) означает, что к нашей программе будет подключена конкретная библиотека стандартных функций. В данном случае подключается библиотека ввода-вывода (std означает, что библиотека стандартная, i – первая буква слова input – ввод, а o – первая буква output – вывод). Подключаемый файл с именем stdio.h  позволяет осуществлять вызов конкретных функций из этой библиотеки (расширение имени h означает, что это головной (начальный) файл, от слова head – голова).  Оператор include собственно не относится к языку Си и выполняется перед трансляцией программы. Такие операторы обычно называют препроцессорными и перед ними ставится знак  #  (решетка).

Во второй строке идет сама программа на языке Си.

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

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

Все операторы в языке Си заканчиваются знаком  ;  (точка с запятой). В нашей программе в теле главной функции всего один оператор: оператор, вызывающий библиотечную функцию printf .  Эта функция печатает текст: Мы начинаем изучать Си  (print переводится: печатать). Это все, что делает программа 1: выводит указанный текст.

Текст после запуска программы выводится в окно вывода (Window/Output). Если запустить программу еще раз, выводимый текст присоединится к уже выведенному тексту в ту же строку.

Добавим к тексту в операторе   printf  двойной символ \n :        printf(“Мы начинаем изучать Си\n”);

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

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

#include<stdio.h>

#include<conio.h>

main() { clrscr();

             printf(“Мы начинаем изучать Си\n ”);

           }

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

Добавим еще одну функцию  getch() из этой же библиотеки в конце нашей программы и запустим программу в следующем виде:

 

#include<stdio.h>

#include<conio.h>

main() { clrscr();

             printf(“Мы начинаем изучать Си\n ”);

           getch();

           }

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

        

        Теперь составим программу, которая делает простейшие вычисления. Пусть нам надо вычислить следующее арифметическое выражение:

  5*7+3*8 .

Здесь знак  *  (звездочка) означает умножение, как принято в Си и других языках программирования.

       Это можно вычислить следующей программой:

Программа 2.

#include<stdio.h>

#include<conio.h>

main() { clrscr();

             printf(“Результат: %d \n ”, 5*7+3*8);

           getch();

           }

После запуска эта программа выдаст результат так:

Результат: 59

Что нового мы видим в этой программе?   В функции  printf  в скобках теперь стало два параметра, разделенные запятой. Первый параметр, называемый форматом, в двойных кавычках содержит текст. Но кроме обычного текста там два новых символа  %d, назовем это элементом формата.

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

Следующая программа выводит число 59 в двух форматах: в десятичном и в шестнадцатеричном.

Программа 3.

#include<stdio.h>

#include<conio.h>

void main ()

{clrscr ();

int a=59;

printf("%d  %X\n",a,a);

getch ();

}

Здесь переменной a присваивается значение  59 и затем значение этой переменной распечатывается в двух разных форматах. Элемент формата  %X соответствует выводу числа в шестнадцатеричном виде. После выполнения программы результат будет иметь вид:

59  3B

 int перед переменной a  (от  integer – целое) в программе означает, что переменная может иметь только целочисленное значение. А  void  перед main означает, что главная функция не выдает никакого значения для операционной системы.

Перейдем теперь к вычислительным задачам.

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

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

Y=X2 ,

для целых значений X  от 1 до 50. Тогда нам понадобится описать в программе эту функцию. Пусть наша программа должна будет печатать значения указанной функции так:

X=1, Y=1

X=2, Y=4

X=3, Y=9

X=4, Y=16

...

и так далее.

 

Программа 2.

#include<stdio.h>

#include<conio.h>

 

int f(int X) {return X*X;}

void main()

{ clrscr();

 for(int x=1; x<=50; x++)

printf(“X=%d, Y=%d\n”,x,f(x));

getch();

}

Что нового в этой программе? Во-первых мы видим, что включена еще одна стандартная библиотека conio.h. Из нее вызываются две стандартные функции clrscr() и  getch().

Первая из этих функций очищает окно вывода от результатов предыдущих вычислений (clrscr – это сокращение от clear screen – очистить экран). А вторая функция задерживает окно вывода до перехода к окну с программой (смысл функции getch() в дальнейшем будет разъяснен подробнее). (Попробуйте запустить эту программу в BC 3.1 без clrscr() или без getch() и почувствуйте разницу).

Но главное, что мы видим в этой программе, это описание нужной нам функции Y=X2 . Она описана строкой:

int f(int X) {return X*X;}

Здесь  f  - имя, которое мы дали этой функции, а X в круглых скобках – аргумент этой функции. В математике это должно быть записано так:  f(X)=X2 , но в Си, как мы видим, записывается по-другому.

Перед именем функции  f  и перед именем переменной X  стоит служебное слово int (сокращение слова integer , переводится целое), которое  означает, что аргумент функции и значения вычисляемой функции будут принимать только целые значения. Оператор  return (переводится: вернуть) в теле функции означает, что нужно вычислить выражение, стоящее после него, и вычисленное значение будет возвращено, как значение функции для заданного аргумента X.

Вызывается функция  f  , то есть, вычисляется и выдает значение, непосредственно в функции печати printf .

Сама функция printf  отличается от того, как она выглядела в программе 1. Там она имела всего один аргумент: текст, заключенный в двойные кавычки. Здесь эта функция имеет три аргумента, разделенные запятыми. Первый аргумент, также заключенный в двойные кавычки, говорит, как мы распечатываем выводимые данные, в каком формате (буква f  в слове printf означает, что печать форматная). А следующие аргументы показывают, какие данные мы выводим (в нашем случае:  x  и  f(x) ).

Запись X=%d, в первом аргументе функции printf  означает, что X= будет выведен на экран как есть, а вместо  %d

как в окошко вставится значение переменной  x , аналогично, Y=%d  означает, что после  вывода на экран Y= сразу вставится вычисленное значение функции  f(x).

Формат %d  означает, что значение, подставленное в это «окошко», будет представлено в десятичной форме (d – первая буква от decimal – десятичный). Так, например, при значениях x  равном 4 и  f(x) равном 16, указанный формат выдаст:

 X=4, Y=16

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

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

Заметим, что в этих скобках сама переменная x  вводится впервые и поэтому перед ней стоит слово int , означающее, что эта переменная будет целого типа, то есть будет принимать только целые значения. Далее, x=1 означает, что первоначальное значение x становится равным 1, с этим значением цикл исполнится первый раз. При повторном выполнении цикла x будет иметь значение на 1 больше. Об этом говорит выражение в операторе  for :   x++ . Операция  ++  в Си означает увеличение на 1. (Отсюда и произошло название языка Си++). А выражение x<=50  в операторе  for  говорит о том, что выполнение цикла должно повторяться, пока x не превзойдет 50. Если x станет больше 50, то выполнение цикла прекращается и происходит переход к следующим операторам. Таким образом, наша программа, распечатав последнюю строку:

X=50, Y=2500

закончит работу.

 

Давайте немного продвинемся к программам посложнее. Решим одну интересную задачу.

Еще в давние времена математиков интересовали свойства следующей бесконечной последовательности чисел:

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, … и так далее.

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

Например, 8=5+3, 13=8+5, 21=13+8, …

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

В математике числа этой последовательности принято называть числами Фибоначчи, по имени итальянского математика, жившего в XII-XIII  вв. и первого, кто опубликовал работу о свойствах этих чисел. И действительно, эти числа обладают очень интересными свойствами, и на эту тему есть целые книги.

Обозначим n-ый член этой последовательности через fn .

То есть f1=1, f2=1, f3=2, f4=3, f5=5, … и так далее.

Тогда каждое число Фибоначчи, начиная с третьего, вычисляется по формуле:

fn = fn-1 + fn-2 .

Составим программу вычисляющую последовательность чисел Фибоначчи.

Сначала решим, как в программе будем обозначать необходимые для вычисления переменные. Нам достаточно использовать три переменные, соответствующие формуле (1). Пусть  f  обозначает очередное вычисляемое число Фибоначчи, а два предыдущих числа, которые нужно сложить по формуле  (1), обозначим  f 1  и   f 2 (в языке Си индексная запись не допускается).

Тогда вычисление по формуле  (1) в программе будет выглядеть так:   f  = f 1 + f 2 .

Но чтобы по этой же формуле вычислить следующее число Фибоначчи, нужно число из   f 1   перенести  в  f 2 ,  а вычисленное на последнем шаге число перенести из   f   

 в    f 1 .  То есть в программе нужно циклически повторять три оператора:

  f  = f 1 + f 2;   f 2= f 1;   f 1 = f ;

Тогда на каждом шаге  в   f   будет вычислено очередное число Фибоначчи, которое и нужно после его вычисления выводить на печать.

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

Программа 5.

#include<stdio.h>

#include<conio.h>

void main ()

{  int f,f1=0,f2=1,n;

clrscr ();

for(n=1;n<=20;n++)

{  f=f1+f2;

    printf("f%d=%d \n ",n, f );

    f2=f1; f1=f;

 }

 getch ();

}

В программе мы задали начальные значения переменных:

f1=0  и   f2=1.

После запуска программа напечатает:

f1=1

f2=1

f3=2

f4=3

f5=5

f6=8

и так далее, а в конце будет:

f18=2584

f19=4181

f20=6765

В функции  printf  предусмотрено, что после буквы  f  идет номер числа  Фибоначчи (из переменной  n), а после знака = значение самого числа.

Чтобы вычислить  тысячное  число  Фибоначчи, эта программа должна будет вычислить все 999 предшествующих чисел  Фибоначчи. А можно ли вычислить сразу тысячное  число  Фибоначчи, не вычисляя предыдущие числа ряда Фибоначчи?

Оказывается можно! И такую формулу для вычисления любого числа  Фибоначчи по его номеру (n) , придумал французский математик  Бине в  XIX  веке.

Числа  Фибоначчи, несмотря на свою простоту, играют в математике очень важную роль и используются при решении многих практических задач. Свойствами этих чисел математики интересуются уже несколько столетий.

Формула Бине для вычисления чисел  Фибоначчи выглядит так:

              Fn=1/√5∙(((1+√5)/2)n-((1-√5)/2)n)

Составим программу, которая вычисляла бы числа  Фибоначчи по этой формуле:

Программа 6.

#include<stdio.h>

#include<math.h>

#include<conio.h>

int bine(int n)

{ float f=sqrt(5);

return (pow((1+f)/2,n)-pow((1-f)/2,n))/f;

}

void main ()

{int f,f1=0,f2=1,n=1;

clrscr ();

for(n=1;n<=20;n++)

    printf("f%d=%d \n ",n, bine(n));

getch ();

}

Теперь объединим в одну программу вычисление чисел  Фибоначчи двумя способами и сравним резкльтаты:

Программа 7.

#include<stdio.h>

#include<math.h>

#include<conio.h>

int bine(int n)

{ float f=sqrt(5);

return (pow((1+f)/2,n)-pow((1-f)/2,n))/f;

}

void main ()

{int f,f1=0,f2=1,n=1;

clrscr ();

for(n=1;n<=20;n++)

{  f=f1+f2;

    printf("n=%2d  f=%4d  fb=%4d\n",n,f,bine(n));

    f2=f1; f1=f;

 }

getch ();

}

Программа 8.

#include<stdio.h>

#include<math.h>

#include<conio.h>

long bine(int n)

{ double f=sqrt(5);

return (pow((1+f)/2,n)-pow((1-f)/2,n))/f;

}

void main ()

{long f,f1=0,f2=1; int n=1,N;

clrscr ();

 printf("Введите натуральное число <=46: N=");

 scanf("%d",&N);

for(n=1;n<=N;n++)

{  f=f1+f2;

    printf("n=%2d  f=%4ld  fb=%4ld\n",n,f,bine(n));

    f2=f1; f1=f;

 }

getch ();

}


Задача 1.

Найти зависимость в следующей последовательности чисел:

3, 5, 10, 18, 29, 43, …

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

Составить программу, вычисляющую 100 первых чисел этой последовательности.

Задача 2.

Для последовательности из задачи 1 вычислить 100-й член последовательности.