
Цели первой недели
- Ознакомиться с основными командами Linux
- Изучить основной синтаксис C и решить несколько задач
- Начать мыслить четче =)
IDE CS50
Для выполнения заданий CS50 предлагает IDE (Integrated Development Environment, интегрированную среду разработки) в «облаке». Чтобы ею воспользоваться, создайте аккаунт на платформе edX, и зарегистрируйтесь на оригинальный курс. После этого:1. Заходим на cs50.io, из списка выбираем edX, вводим логин и пароль, жмем Submit 2. Вводим данные своего edX-аккаунта, жмем Return to ID.CS50.NET.



Командная строка и запуск CS50 IDE
В нижней части окна CS50 IDE во вкладке Terminal есть терминальное окно или панель командной строки. Сюда можно вводить строковые команды: вы сможете делать то же самое, что и с оконным интерфейсом, например, запускать приложения, удалять и создавать файлы, инсталлировать ПО. Если вы никогда не работали с командной строкой, вероятно, такой способ покажется громоздким: нужно помнить команды, набирать их текстом вместо того, чтобы щелкать по иконкам и кнопкам. В какой-то мере так и есть, затем оконный интерфейс и придумали. Однако командная строка есть во всех ОС и её обожают админы. А всё потому, что порой без неё никак. В окне IDE в терминале вы увидите загадочную строку: username:~/workspace $ на месте «username» будет автоматически сгенерированное (на основе ваших регистрационных данных) имя. Кликните по окошку терминала, напечатайте:update50
Нажмите Enter. Команда просит систему обновиться. Вы увидите, как в терминале появляются строки, описывающие процесс установки. Не закрывайте CS50 IDE пока не увидите Update complete!.
После этого снова появится строка по умолчанию, та, что с вашим именем.
Работа в IDE
Создадим папку, где будут лежать ваши файлы. Кликните правой кнопкой мыши по ~/workspace (ваш корневой каталог) в левом верхнем углу CS50 IDE, выберите New Folder. Переименуйте папку в pset1(если вы ошиблись в имени, щелкните по вашей папке правой кнопкой и выберите Rename).


username:~/workspace $
Workspace — текущая рабочая директория (та, что открыта в рабочей среде). Тильда (~) указывает на корневую директорию (в ней лежит workspace). Обратите внимание, что workspace в терминале — то же самое, что и иконка ~/workspace в левом верхнем углу CS50 IDE.
Давайте попрактикуемся. Кликнете в каком-либо месте терминала и наберите в командной строке
ls
и нажмите Enter. Эти две строчные буквы — сокращение от "list" («список») — вызовут список файлов и папок, находящихся внутри текущей директории workspace. Среди всего прочего вы увидите и созданную вами pset1! Теперь откроем нашу папку с помощью команды. Набираем
cd pset1
или многословнее:
cd ~/workspace/pset1
Команда cd (change directory) меняет активную директорию, в нашем случае на
~/pset1
Активная строка поменялась на
username:~/workspace/pset1 $
Это подтверждает, что вы теперь находитесь в директории
~/workspace/pset1
(строка расшифровывается как «я нахожусь в pset1 внутри папки workspace, которая лежит в корневой папке, обозначаемой ~"). Теперь наберите
ls
Вы увидите файл hello.txt! Если вы кликнете по названию в терминале, ничего не произойдет: это текст, и он не выдает активной ссылки, но подтверждает, что hello.txt находится там, где должен. Наберите
cd
Если вы пишете только саму команду cd, но не подставляете аргумент (то есть имя папки, в которую ей нужно перейти), она вернет вас в корневую директорию по умолчанию. Таким образом, в активной строке вы увидите следующую картину:
username:~ $
Чтобы вернуться назад в папку pset1, наберите
cd workspace
и нажмите Enter. Затем
cd pset1
и снова Enter. Также вы можете заменить эти две команды одной, подлиннее:
cd workspace/pset1
Hello, C!
Наконец-то эта минута наступила! Начинаем программировать. Внутри нашей папки pset1 в IDE создаем файл под названием hello.c (расширение обязательно), открываем в новой вкладке (думаем, вы помните, как это делать из предыдущего параграфа). ВАЖНО! Буквы должны быть строчными, Linux чувствителен к регистру. Hello.c и hello.c — разные файлы. В правой части окна CS50 IDE набираем точь-в-точь такой текст, как вы видите ниже. Да, его можно скопировать, но полезнее — набрать.#include
int main(void)
{
printf("hello, world\n");
}
Буквы разного цвета потому, что в CS50 IDE работает подсветка синтаксиса. Она выделяет цветом блоки текста для лучшей читаемости. В самом файле цвета не сохраняются, они видны только в IDE. Если они есть, значит, IDE понимает C, а о том, что это именно C, вы сообщили в расширении файла (*.c). Если бы вы назвали тот же файл hello.txt, текст был бы одноцветный.
Убедитесь, что вы напечатали всё ровно так, как в примере, иначе поймаете первый баг=). Снова обращаем ваше внимание на разницу между строчными и прописными буквами. Символ \n переводит курсор на следующую строку, и введенный следом текст не слипнется с выведенным программой. Ах да, и о точке с запятой (;) не забывайте. Это важный разделитель операторов программы, C без них работать не захочет.
Нажмите File > Save (или комбинацию command- или Ctrl-s). Заметили, что звездочка перед названием файла исчезла? Если да, значит изменения сохранились. Кликните в любом месте по терминальному окну под вашим кодом и убедитесь, что вы внутри ~/workspace/pset1 (если это не так, кликните cd и нажмите Enter, затем cd workspace/pset1 и снова Enter). Ваша активная строка должна выглядеть так:
username:~/workspace/pset1 $
Убедимся, что файл hello.c находится ровно там, где должен. Набираем
ls
и жмем Enter. Вы видите и hello.c? Если нет, вернитесь на пару шагов назад и создайте файл в нужной директории еще раз.
… Теперь наступает торжественный момент: скрещиваем пальцы и… печатаем:
make hello
и скрещенными же пальцами жмем Enter. Именно hello, не hello.c. Если все, что вы после этого действа перед собой увидели — вторая активная строка, которая выглядит точь-в-точь, как предыдущая, значит, всё работает! Ваш исходный код был переведен в машинный или объектный код (то есть, в последовательности 0 и 1). Теперь этот код можно выполнить (то есть запустить программу!). Для этого печатаем:
./hello
в командной строке, жмем Enter. Если вы не меняли заключенный между "" текст, ниже вы увидите:
hello, world
Если вы теперь наберете команду
ls
и нажмете Enter, вы увидите новый файл hello, наряду с hello.c и hello.txt. У первого hello, должна быть звездочка после имени, которая сигнализирует о том, что это исполняемый файл, то есть такой, с помощью которого вы запускаете программу.
Баги?
Если после команды make, вы увидели ошибки, пришло время первой отладки! Надписи вроде «expected declaration» означают, что вы где-то допустили опечатку. Сверьте код с приведенным выше еще раз, только будьте очень внимательны ко всем деталям. Внимание! Описания ошибок выдаются на английском. Если непонятно, воспользуйтесь поисковиком, Google Translate или задайте вопрос в комментарии. Как только вы исправили ошибки, не забудьте сохранить ваш код с помощью File > Save (или command- или Ctrl-s), снова щелкнете по внутренней части терминального окна и наберитеmake hello
(Только предварительно убедитесь, что вы находитесь в директории ~/workspace/pset1). Если больше ошибок нет, запускайте программу, набирая команду
./hello
По идее перед вами должна возникнуть заветная фраза, заключенная в кавычки оператора printf, который командует «напечатай».
Если окно терминала кажется вам слишком маленьким, кликните по иконке заключенного в окружности плюса (+), расположенной рядом с hello.c.
Проверка на правильность
В CS50 IDE встроено приложение check50. Оно работает из командной строки и проверяет некоторые из программ на наличие ошибок. Если вы еще не там, перейдите в директорию ~/workspace/pset1 выполнив в терминале команду:cd ~/workspace/pset1
Теперь выполните
ls
вы увидите, по меньшей мере, файл hello.c. Убедитесь, что название файла выглядит именно так, а не, скажем, Hello.c или hello.C. Переименовать файл можно, выполнив команду
mv source destination
source — текущее имя файла, destination — новое имя файла. mv (от англ. move) — утилита для переименования. Если вы случайно назвали файл Hello.c, наберите строку:
mv Hello.c hello.c
Убедившись, что файл точно называется hello.c вызовем проверочную программу check50. Обратите внимание, что 2015.fall.pset1.hello —уникальный идентификатор для задачки “hello world”.
check50 2015.fall.pset1.hello hello.c
Если программа выполнена правильно, вы увидите:

:( hello.c exists
\ expected hello.c to exist
:| hello.c compiles
\ can't check until a frown turns upside down
:| prints "hello, world\n"
\ can't check until a frown turns upside down
Здесь check50 не нашел hello.c, и красный смайлик сигнализирует, что вы либо ошиблись в имени, либо загрузили файл не туда. Жёлтые «нейтральные» смайлы означают, что тесты не запустились. И откуда им запуститься, если программа не нашла файл, который нужно проверить?
Вот еще один вариант, который выскочит в том случае, если вы меняли текст, который должна вывести функция printf():
:) hello.c exists
:) hello.c compiles
:( prints "hello, world\n"
\ expected output, but not "hello, world"
check50 сообщает, что ожидалась строка hello, world\n, но появилось что-то другое.
check50 не считает баллы за прохождение курса, но проверяет, отличается ли результат выполнения задания от ожидаемого. И позволяет вам убедиться в этом прежде, чем подтвердить правильность задачи внутри курса (как это сделать, мы расскажем позднее).
Основы С: сравнение со Scratch
Hello world на Scratch и C:

#include
int main(void)
{
printf("hello, world\n");
}
представляет функцию, которая печатает «слова» спрайта в облачке комикса в Scratch, в C есть функция printf, которая делает то же самое, только без мультиков.
- main — по-английски — «главная». Точка входа в программу. То же самое, что
.
Бесконечный цикл

while (true)
{
printf("hello, world\n");
}
while (true) делает то же самое: цикл продолжает свою работу пока (while) значение true (булевское выражение «правда» или «единичка»). Такой цикл будет выполнятся бесконечно.
Цикл, выводящий фразу на экран 10 раз
Scratch
for (int i = 0; i < 10; i++)
{
printf("hello, world!\n");
}
i — переменная-счетчик, её значение меняет оператор инкремента i++, увеличивая его на 1 при каждом витке цикла. Изначально i присваивается значение 0 с помощью оператора присваивания =.
Внимание! Как и в Java, в C равенство обозначается ==, оператор присваивания =.
То есть, a = 5 означает, что переменной a присвоили значение 5, а (a= =5) означает булонское выражение (если а равно 5, то выражение правдиво, если не равно, то ложно).
Цикл остановится, когда i «дорастет» до 9. Несложно посчитать, цикл выполнится 10 раз.
Таким образом, если вам нужно повторить что-то определенное количество раз, в C вы задаете цикл for (int i = 0; i < 10; i++).
Еще один пример:

int counter = 0;
while (true)
{
printf("%i\n", counter);
counter++;
}
- counter сохраняет значение в C и Scratch. В С задаем int counter = 0 вместо
.
- Помечаем тип переменной как int для уточнения: i — целое число (от англ. integer, целый).
- Значок %i, который мы используем в printf в четвертой строке — заполнитель, говорящий о том, что мы должны напечатать десятичное целое, точно так же, мы говорим printf заменить заполнитель на значение, которое принимает переменная counter.
Булевы выражения

(x < y)
((x < y) && (y < z))
Условия


#include
Об этом позднее, в разделе «Библиотеки»
Условные операторы
Эти ребята проверяют, выполняется ли некоторое условие (логическое выражение, вопрос, на который можно ответить только «да» или «нет»), и если это так, то исполняют некоторые действия, привязанные к этому условию. Пример из жизни: если пошел дождь (при условии, что пошел дождь) и я на улице (я во время дождя нахожусь на улице), я открываю зонтик.if (условие)
{
//исполнить, если значение истинно
}
Усложненный вариант: если условие выполняется, сделать действие, если нет — сделать другое действие.
if (условие)
{
//выполнить действие
}
else
{
//выполнить другое действие, если условие ложно
}
Пример: если тебе больше 18, одобрить доступ. Если меньше, не одобрить.

Оператор выбора
switch (n)
{
case const1:
// если n равен const1, выполнить
break; // условие совершилось — выйти из выбора
case const2:
// если n равен const2, выполнить
break;
...
default:
// если n не равен ни одной из констант, выполнить
break;
}
Пример: если n = 50, напечатать "CS50 is Introduction to Computer Science I", если n = 51, напечатать "CS51 is Introduction to Computer Science II", иначе — напечатать "Sorry, I'm not familiar with that class!"
switch (n)
{
case 50:
printf("CS50 is Introduction to Computer Science I\n");
break;
case 51:
printf("CS51 is Introduction to Computer Science II\n");
break;
default:
printf("Sorry, I'm not familiar with that class!\n");
break;
}
Циклы
while: проверяет условие, затем исполняет действие, пока условие истинноwhile (условие)
{
// выполнять, пока истина
}
do/while отличается тем, что первый раз он исполняет действие без проверки условия, а затем только проверяет его. Если условие выполняется, он повторяет действие, пока условие не станет ложью.
do
{
) // выполнять, пока истина
}
while (условие);
Цикл for повторяет действие заданное количество раз


Основные типы данных в C

Библиотеки С
Вы, наверное, уже задались вопросом, что означает первая строка программы на C:#include
Какова её роль и можно ли обойтись без неё?
Строка #include делает очень важную вещь: она подключает библиотеки уже написанного кода к вашей программе.
Имя подключенной библиотеки идет в угловых скобках (<>) и носит расширение (.h). Если бы не было библиотек, то любое, самое элементарное действие, пришлось бы каждый раз описывать снова и снова. Подключенная нами библиотека Структура библиотек C
Когда программист пишет библиотеку, код распределяется по двум типам файлов — заголовочный файл (header, расширение *.h) и файл реализации (implementation, расширение *.c). Заголовочный файл содержит код, описывающий ресурсы библиотеки, которые вы можете использовать. То есть описания переменных, функций, структур, типов и прочее. Если вам интересно, что содержит та или иная библиотека, нужно заглянуть именно в заголовочный файл. В терминале CS50 IDE (и других средах Linux) вы можете вызвать приложение less для просмотра файлов и открыть с его помощью интересующую вас библиотеку:less /usr/include/stdio.h
Файл откроется прямо в терминале. Правда, для новичков он будет очень трудночитаемым.


#include <имя_библиотеки.h>
Если библиотека, которую вы хотите подключить, лежит в той же папке, что и ваша программа, подключайте её следующим образом:
#include “имя_библиотеки.h”
2.Присоединить бинарный файл для компиляции.
Это очень важный шаг, поскольку, как мы говорили выше, заголовочный файл не содержит реализации элементов библиотеки. Чтобы это сделать, нужно вызвать компилятор clang с флагом –l и идущим непосредственно за ним названием библиотеки. Например, компонуем библиотеку cs50:
clang hello –lcs50
Clang — один из компиляторов. Для компиляции можно также использовать уже знакомую вам программу make. По сути, она вызывает clang с определенными аргументами командной строки.
И снова Hello C: разбор синтаксиса простейших программ
Директива #include подключает библиотеку ввода/выводаint sqr(int a)
{
return a*a;
}
int sqr(int a) — название функции. В скобках — её аргумент a, это то, что подается на вход функции. Это как переменная в уравнении. То есть, если мы хотим узнать квадрат числа 5, то мы вызовем нашу функцию в виде sqr(5) и получим результат 25.
int — тип данных (от англ. integer — целые числа). Наша функция написана так, что мы не можем вызвать её с аргументом a = 5.5. Такая попытка выдаст ошибку, поскольку 5.5 — число дробное, а наше число должно быть целым. int перед именем функции означает тип, который должна эта функция возвращать. Он не обязательно совпадает с типом аргумента.
Пример: функция, которая отнимает от целого числа 0.5:
double bit_less(int a)
{
double b;
b = a – 0.5;
return b;
}
int main (void) — название главной функции. В одной программе может быть много функций, но, чтобы начать её выполнять, нужна функция под названием main. Слово void в скобках означает, что у этой функции нет аргументов.
Внимание! main всегда возвращает int, но return для неё не обязателен.
Пример функции не возвращающей значения:
void sayhello(void)
{
printf(“hello everyone!\n”);
}
При вызове функции в главной программе, она выведет приветствие.
Давайте напишем одну программу, в которой будет несколько функций. Тех, что мы уже создали выше. Две созданные нами функции вызовем через главную функцию main().
В C, как и любом языке, есть такой элемент, как комментарий или примечание в коле программы, предназначенное не для компьютера, а для понимания людей. Например, описание, что именно делает код. Компилятор комментариев не видит. Комментирование программ — очень важный момент, поскольку порой разобраться в чужом (и даже своем) коде очень сложно.
//пример однострочного комментария
/** а это –
многострочного **/
#include
//функция возведения в квадрат числа a
int sqr(int a)
{
return a*a;
}
//выводит приветствие
void test(void)
{
printf ("hello everyone!\n");
}
//главная функция
int main(void)
{
test();
printf("%d\n", sqr(5));
}
Почти всё, что есть в этой программе вы уже видели. Две функции — возведения в квадрат и приветствия и главная функция main, где мы последовательно вызываем эти две функции.
В результате выполнения программы у нас сначала выведется приветствие, на следующей строке — квадрат 5. Обратите внимание, функция test() вызывается с пустыми скобками, потому что её аргументы определены как void.
Еще немного о вводе/выводе в C
Вы, наверное, уже успели заметить странные символы %d и %f в скобках оператора printf. Дело в том, что функция printf выводит данные в следующем обобщенном виде:рrintf ("управляющая строка", аргумент1, аргумент2,...);
Управляющая строка содержит компоненты трех типов:
- символы, которые выводятся на экран дисплея;
- спецификаторы преобразования, которые вызывают вывод на экран очередного аргумента из последующего списка;
- управляющие символьные константы.
- с: значением аргумента является символ;
- d или i: десятичное целое число;
- f: десятичное число с плавающей точкой;
- s: строка символов.
scanf("%d", &a);
Давайте перепишем нашу программу так, чтобы пользователь сам вводил число, которое нужно возвести в квадрат.

ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
т.е. %i в функции printf будет означать вывести переменную с типом данных int ( 4 байта )
тогда по логике вещей
%d или %l ( long float ) в функции printf будет означать вывести переменную с типом данных double или long float, именно в этом случае будет без разницы какой из спецификаторов преобразования подставить в функцию printf т.к размеры этих переменных равны в кол-вах байт, а именно 8 байт.
Или я что-то пропустил?