Задачи 1 недели
1. Заходим на cs50.io, из списка выбираем edX, вводим логин и пароль, жмем Submit 2. Вводим данные своего edX-аккаунта, жмем Return to ID.CS50.NET. 3. Ждем: создается ваше виртуальное пространство. 4. Готово! содержит функции ввода/вывода. Именно она позволяет нам использовать функцию printf () для вывода на экран. То есть, если бы мы не написали строку #include , но оставили в теле программы функцию printf (), при попытке запуска мы бы получили ошибку! Потому что без этой библиотеки компилятор не знает, что такое printf ().
Есть библиотеки стандартные, они составляют словарный запас языка. Функция printf() не встроена в компьютер, но входит в стандартную библиотеку языка C. То есть некий программист ранее написал её и включил в библиотеку. Теперь другие могут ею пользоваться, не изобретая велосипед. Чтобы компилятор её «понял», подключаем .
Есть и другие стандартные библиотеки, используемые в процессе прохождения CS50. Например, библиотека строк, где описаны операции со строками (определение длины, сложение и прочее).
По сравнению с другими популярными языками программирования, количество стандартных библиотек C очень невелико. Но есть самописные, чаще всего — более узкоспециализированные библиотеки. Так, библиотека была создана специально для студентов CS50.
Самое время сделать важное замечание: помимо написания программ, решения задач с помощью собственного кода, хороший разработчик обладает еще одним важным навыком: знанием инструментов, уже написанных и умением использовать их (чужие библиотеки), чтобы не тратить время на изобретение «колеса».
Так, если вы находитесь в процессе решения нудной или сложной задачи, которая при этом кажется довольно распространенной, приучайтесь задавать себе вопрос: «а не написал ли её решение кто-нибудь другой?» Велики шансы, что так оно и есть, и вы можете найти эту функцию в существующей библиотеке.
В технических терминах, библиотека — это двоичный файл, полученный путем объединения в коллекцию объектных файлов, используя компоновщик. Объектные файлы — это те файлы с расширением (*.o), которые вы получаете при компиляции приложений.
.
Программы в C состоят из функций, а те — из операторов и переменных. Функция — это кусок кода, в котором уже есть или подаются какие-то данные, а какие-то данные получают в результате её исполнения.
Фигурные скобки { } ограничивают тело функции — описание того, что она должна делать.
printf() из стандартной библиотеки stdio выводит любую строку на экран. Строки заключаются в двойные кавычки, а символ “\n” означает перевод курсора на новую строку.
Пример: функция «посчитать квадрат целого числа». Передаем функции данные, в нашем случае — число, которое нужно возвести в квадрат. Затем в ней прописывается алгоритм умножения числа на самое себя, и результат этого умножения она выдает на выходе.
Цели первой недели
- Ознакомиться с основными командами Linux
- Изучить основной синтаксис C и решить несколько задач
- Начать мыслить четче =)
IDE CS50
Для выполнения заданий CS50 предлагает IDE (Integrated Development Environment, интегрированную среду разработки) в «облаке». Чтобы ею воспользоваться, создайте аккаунт на платформе edX, и зарегистрируйтесь на оригинальный курс. После этого:1. Заходим на cs50.io, из списка выбираем edX, вводим логин и пароль, жмем Submit 2. Вводим данные своего edX-аккаунта, жмем Return to ID.CS50.NET. 3. Ждем: создается ваше виртуальное пространство. 4. Готово!
Командная строка и запуск CS50 IDE
В нижней части окна CS50 IDE во вкладке Terminal есть терминальное окно или панель командной строки. Сюда можно вводить строковые команды: вы сможете делать то же самое, что и с оконным интерфейсом, например, запускать приложения, удалять и создавать файлы, инсталлировать ПО. Если вы никогда не работали с командной строкой, вероятно, такой способ покажется громоздким: нужно помнить команды, набирать их текстом вместо того, чтобы щелкать по иконкам и кнопкам. В какой-то мере так и есть, затем оконный интерфейс и придумали. Однако командная строка есть во всех ОС и её обожают админы. А всё потому, что порой без неё никак. В окне IDE в терминале вы увидите загадочную строку: username:~/workspace $ на месте «username» будет автоматически сгенерированное (на основе ваших регистрационных данных) имя. Кликните по окошку терминала, напечатайте:update50
Нажмите Enter. Команда просит систему обновиться. Вы увидите, как в терминале появляются строки, описывающие процесс установки. Не закрывайте CS50 IDE пока не увидите Update complete!.
После этого снова появится строка по умолчанию, та, что с вашим именем.
Работа в IDE
Создадим папку, где будут лежать ваши файлы. Кликните правой кнопкой мыши по ~/workspace (ваш корневой каталог) в левом верхнем углу CS50 IDE, выберите New Folder. Переименуйте папку в pset1(если вы ошиблись в имени, щелкните по вашей папке правой кнопкой и выберите Rename). Затем кликаем правой кнопкой по папке pset1, выбираем New File. Появляется файл Untilted, переименуем его в hello.txt. Дважды кликнете по hello.txt. В CS50 IDE справа вы увидите новую вкладку и поле, где можно печатать. Если вы это сделали, обратите внимание на появившуюся перед названием файла на вкладке символ звездочки (*) — индикатор того, что в файл были внесены, но не сохранены, изменения. Сохраните файл, зайдя в меню *File > Save или с помощью клавиш command + S (на машинах Apple) или Ctrl + S (на ПК). Звездочка должна исчезнуть. Давайте проверим, лежит ли файл там, где должен. Сделаем это с помощью командной строки, пора к ней привыкать:). Как и ранее, активная строка в терминале выглядит так: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
Если программа выполнена правильно, вы увидите:
Зеленые смайлики означают, что тест пройден. Также можете видеть URL внизу вывода check50, но он нужен только сотрудникам (впрочем, если интересно, заходите!).
check50 запускает 3 теста: существует ли файл hello.c, компилируется ли hello.c и выдает ли приложение строку, в которой написан текст "hello, world\n".
Если вы увидите грустные красные смайлики, значит у вас баг.
:( 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 — по-английски — «главная». Точка входа в программу. То же самое, что .
Бесконечный цикл
в переводе на C: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++).
Еще один пример:
И то же самое в переводе на C:
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
Файл откроется прямо в терминале. Правда, для новичков он будет очень трудночитаемым.
Чтобы выйти из less, нажмите q на клавиатуре. Заголовочный файл не содержит код функций, что служит примером очень важного понятия — сокрытия данных или инкапсуляции. Пользователю системы незачем знать «внутренности» библиотек, ему достаточно, чтобы она работала. Если вы прошерстите stdio.h, то не найдете там реализации printf(), хотя как её использовать, вы уже знаете.
Это сделано для того, чтобы защитить данные от вмешательства, которое порой может плохо отразиться на системе. Так, если кто-то изменит реализацию функции printf() в библиотеке, это отразится на всех тех программах, которые её используют.
Любознательным будет интересно, где спрятана реализация. Согласно конвенции (соглашения, принятые в мире программирования) такой код хранят в файле с расширением (*.c). После компиляции библиотеки на основе двух файлов с одинаковым именем, но разным расширением создается объектный файл, который собран так, чтобы создать файл с двоичным кодом библиотеки.
Автор библиотеки передает программисту, который хочет её использовать, два файла — с двоичным кодом, а также заголовочный файл. Таким образом, файл с исходным кодом программисту не нужен. Точнее, он может быть нужен, если программист хочет что-то поменять в самой библиотеке и перекомпилировать её под собственные нужды.
Чтобы воспользоваться функциями библиотеки в своей программе нужно проделать следующее:
1. Включить заголовочный файл в программу с помощью строки #include
В случае стандартных библиотек достаточно указать имя библиотеки в угловых скобках:
#include <имя_библиотеки.h>имя_библиотеки.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);
Давайте перепишем нашу программу так, чтобы пользователь сам вводил число, которое нужно возвести в квадрат.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
эта b нигде не используется и вообще ненужны 2 эти строки
В чём может быть проблема?
Заранее спасибо