суббота, декабря 20

Серия постов

Серия постов про то как стать программистом. Больше философии, чем науки. Но может быть именно в этом дело.

Раз, два, три, четыре.

P.S. текст написал не я.

вторник, августа 28

Решение квадратных уравнений

Со школы всем известный алгоритм нахождения корней квадратных уравнений. Воспользуемся классическим алгоритмом (без всяких выкрутасов с комплексными числами и с борьбой с потерей точности).

Алгоритм нахождения корней квадратного уравнения:
1) Есть квадратное уравнение вида ax^2+bx+c=0, требуется найти такие x, чтобы уравнение становилось истинным;
2) Находим дискриминант уравнения по формуле D=b^2-4ac;
3) Если дискриминант меньше нуля (D<0), то действительных корней у данного уравнения не существует.
4) В ином случае уравнение имеет два решения x1=[-b-sqrt(d)]/2a, x2=[-b+sqrt(d)]/2a.

Вот программа на С++:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
cout << "Input a, b, c: ";
double a, b, c;
cin >> a >> b >> c;
double D = b * b - 4 * a * c;
if (D < 0)
cout << "No solutions." << endl;
else
{
double x1 = (-b - sqrt(D)) / (2 * a);
cout << "x1 = " << x1 << endl;
double x2 = (-b + sqrt(D)) / (2 * a);
cout << "x2 = " << x2 << endl;
}
return 0;
}


Новое, что мы узнали здесь, это оператор if. С помощью оператора if компьютер делает выбор, какой кусок кода ему выполнять.

В общем случае оператор if имеет два варианта. Первый вариант:

if (условие) действие

Если условие истинно, то компьютер выполнит действие, в противном случае действие сделано не будет. Если нужно совершить несколько действий, то их нужно заключить в фигурные скобки.

Второй вариант, вариант с альтернативой:

if (условие)
действие1;
else
действие2;

Если условие истинно, то компьютер выполнит действие1, в противном случае будет выполнено действие2. Если нужно совершить несколько действий, то их нужно заключить в фигурные скобки.

воскресенье, мая 6

Научим компьютер читать стихи

Есть такой забавный стишок:
    99 bottles of beer on the wall, 
99 bottles of beer.
Take one down and pass it around,
98 bottles of beer on the wall.

98 bottles of beer on the wall,
98 bottles of beer.
Take one down and pass it around,
97 bottles of beer on the wall.

<...>

1 bottle of beer on the wall,
1 bottle of beer.
Take one down and pass it around,
No more bottles of beer on the wall.

No more bottles of beer on the wall,
No more bottles of beer.
Go to the store and buy some more,
99 bottles of beer on the wall.

Переводиться на русский язык это стихотворение вот так:
    99 бутылок пива на стене, 
99 бутылок пива!
Возьми одну, пусти по кругу,
98 бутылок пива на стене!

98 бутылок пива на стене,
98 бутылок пива!
Возьми одну, пусти по кругу,
97 бутылок пива на стене!

<...>

1 бутылка пива на стене,
1 бутылка пива!
Возьми одну, пусти по кругу,
Никаких бутылок пива на стене.

Никаких бутылок пива на стене!
Никаких бутылок пива!
Пойди в магазин и купи еще,
99 бутылок пива на стене!

Научим компьютер читать такой стишок. Нет ничего проще, вот текст программы.

#include <iostream>
int main()
{
std::cout << " 99 bottles of beer on the wall, \n";
std::cout << " 99 bottles of beer. \n";
std::cout << " Take one down and pass it around, \n";
std::cout << " 98 bottles of beer on the wall. \n\n";

std::cout << " 98 bottles of beer on the wall, \n";
std::cout << " 98 bottles of beer. \n";
std::cout << " Take one down and pass it around, \n";
std::cout << " 97 bottles of beer on the wall. \n\n";

/*---*/

std::cout << " 1 bottle of beer on the wall, \n";
std::cout << " 1 bottle of beer.\n";
std::cout << " Take one down and pass it around, \n";
std::cout << " No more bottles of beer on the wall.\n\n";

std::cout << " No more bottles of beer on the wall, \n";
std::cout << " No more bottles of beer.\n";
std::cout << " Go to the store and buy some more, \n";
std::cout << " 99 bottles of beer on the wall.\n\n";

std::cin.get();

return 0;
}

Я, естественно, не стал приводить полностью текст программы. Программа работает и это самое главное. Но у нее есть небольшой минус: текст программы огромный. Это черевато вот чем. Предположим, мы решим стишок показать детям, и захотим сделать детский вариант, заменив пиво на молоко. Нам придется перелапативать весь текст. Как пели в фильме Айболит 66: «нормальные герои всегда идут в обход». Существует такое понятие как цикл. Мы попросим компьютер повторить стишок 99 раз, изменяя только число.

#include <iostream>
int main()
{
int i = 99;
while (i > 2)
{
std::cout << " "<< i <<" bottles of beer on the wall, \n";
std::cout << " "<< i <<" bottles of beer. \n";
std::cout << " Take one down and pass it around, \n";
std::cout << " "<< i - 1 <<" bottles of beer on the wall. \n\n";

i--;
}

std::cout << " 2 bottles of beer on the wall, \n";
std::cout << " 2 bottles of beer. \n";
std::cout << " Take one down and pass it around, \n";
std::cout << " 1 bottle of beer on the wall. \n\n";

std::cout << " 1 bottle of beer on the wall, \n";
std::cout << " 1 bottle of beer.\n";
std::cout << " Take one down and pass it around, \n";
std::cout << " No more bottles of beer on the wall.\n\n";

std::cout << " No more bottles of beer on the wall, \n";
std::cout << " No more bottles of beer.\n";
std::cout << " Go to the store and buy some more, \n";
std::cout << " 99 bottles of beer on the wall.\n\n";

std::cin.get();

return 0;
}

Цикл формируется с помощью ключевого слова while. В общем виде он выглядит вот так:

while (/*условие*/)
{
/*список действий*/
}

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

Такой список действий иногда называют «телом цикла».


Компьютер будет выполнять тело цикла до тех пор пока будет истинно условие цикла.

В нашем случае, в случае со стишком, условие такое — i > 2, в фигурных скобках мы выводим текст стишка и после этого уменьшаем значение переменной i на единичку с помощью команды i--. Перед циклом while мы заводим переменную i с типом int и присваиваем этой переменной значение 99.

Тип int это тип целого числа. В переменных такого типа могут храниться целые числа. Например: 0, 1, 2, 100, -20.


Тут можно выделить три основных момента это инициализация (int i = 99), условие при котором тело цикла выполняется (i < 2), и способ изменения состояния цикла (i--). Очень часто программисты забывают какой либо из этих моментов, например, я часто забываю последний момент (i--). Для таких склеротиков как я, придумали цикл for. В общем виде он выглядит вот так:

for (/*инициализация*/; /*условие*/; /*изменение состояния цикла*/)
{
/*список действий */
}

Все основные моменты цикла находятся в одном месте и перечисленны через точку с запятой. Вот текст программы с использованием цикла for:

#include <iostream>
int main()
{
for (int i = 99; i > 2; i--)
{
std::cout << " "<< i <<" bottles of beer on the wall, \n";
std::cout << " "<< i <<" bottles of beer. \n";
std::cout << " Take one down and pass it around, \n";
std::cout << " "<< i - 1 <<" bottles of beer on the wall. \n\n";
}

std::cout << " 2 bottles of beer on the wall, \n";
std::cout << " 2 bottles of beer. \n";
std::cout << " Take one down and pass it around, \n";
std::cout << " 1 bottle of beer on the wall. \n\n";

std::cout << " 1 bottle of beer on the wall, \n";
std::cout << " 1 bottle of beer.\n";
std::cout << " Take one down and pass it around, \n";
std::cout << " No more bottles of beer on the wall.\n\n";

std::cout << " No more bottles of beer on the wall, \n";
std::cout << " No more bottles of beer.\n";
std::cout << " Go to the store and buy some more, \n";
std::cout << " 99 bottles of beer on the wall.\n\n";

std::cin.get();
return 0;
}

Литература: статья на Википедии «99 бутылок пива».

понедельник, апреля 16

Научим компьютер вежливости

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

Давайте напишем программу, которая спрашивает ваше имя, а потом здоровается.

Вот примерный диалог:
What is your name?
>Dorogusik
Hello, Dorogusik.

Значком > я показал, где происходил ввод пользователя.
Выводить текст на экран мы уже научились. Это делается вот так:

cout << "My text";

Чтобы считать текст с клавиатуры, можно использовать вот такую связку:

cin >> ...;

Вот только, где же этот текст будет храниться. Нам нужен какой-то «ящичек» в котором будет храниться введенный нами текст. И такие хранилища в C++ есть, они называются «переменными». В C++ в переменную можно класть данные только определенного типа. Есть переменные в которые можно класть только текст, есть переменные в которые можно класть целые числа, а в другие переменные можно класть вещественные числа.
Вещественные числа - проще говоря, это числа с десятичной точкой, например, 0.1; 3.14159265; 0.3333; 2.718281828459045 и т.п.

Чтобы завести переменную, нужно сначала выбрать, какого она будет типа, и придумать ей название (дать переменной имя). В нашем примере в переменной будет храниться текст, для хранения текста в C++ есть тип, он называется string (строка). В этой переменной мы хотим хранить имя человека, так что с выбором имени для переменной проблем нет так и назовем переменную name. Итак чтобы завести переменную нам нужно будет добавить такую строчку.

std::string name;

И еще выше мы должны будем подключить библиотеку для работы со строками вот такой строкой:

#include <string>

Все знания для того чтобы написать программу у нас есть. Вот так будет выглядеть наша программа.

#include <iostream>
#include <string>
int main()
{
std::string name;
std::cout << "What is your name?\n";
std::cin >> name;
std::cout << "Hello, ";
std::cout << name;
std::cout << ".\n";
return 0;
}

воскресенье, апреля 15

Поговорим об ошибках

Человек такое существо, которое не может делать все идеально, обязательно где-нибудь да и ошибется. Компьютер же наоборот, как ему скажешь, так он и будет делать с точностью до последней буквы. Понятно, что все программное обеспечение делается для человека и программисты стараются как то предупредить человеческие ошибки. Например, проверка орфографии. Я вот сейчас печатаю текст и компьютер подчеркивает красным неправильные слова. Или корзина — если ты удалил по ошибке нужный файл, то потом ты его сможешь из корзины восстановить.

Когда пишешь программу: ошибки неизбежны. Например, после инструкции забыли поставить точку с запятой (;), или в начале Escape последовательности вместо обратного слеша (\) поставили прямой слеш (/). Компилятор вас не поймет и выдаст сообщение об ошибки, мне бы хотелось чтобы вы сразу же нашли общий язык с компилятором. К сожалению, компилятор выдает сообщения на английском языке. Я постараюсь дать перевод наиболее распространенных сообщений.

Сообщение: error C2143: syntax error : missing ’x’ before ’yyy’
Перевод: ошибка C2143: синтаксическая ошибка : пропущен ’x’ до ’yyy’
Пояснение: нужно посмотреть назад от указанной строчки и найди, где же вы пропустили ’x’. Такая ошибка может возникнуть, если вы забыли поставить закрывающую скобку, или точку с запятой, или кавычку или еще чего-нибудь. Так же может быть, что вы перепутали открывающий символ, например, вместо фигурной скобки ’{’ поставили круглую ’(’.

Сообщение: error C2065: ’xxx’ : undeclared identifier
Перевод: ошибка C2065: ’xxx’ : необъявленный идентификатор
Пояснение: это значит, что компилятор не знает такого слова, скорее всего вы набрали его с ошибкой.

Сообщение: error C2664: ’xxx’ : cannot convert parameter n from ’yyy’ to ’zzz’
Перевод: ошибка C2664: ’xxx’ : не могу преобразовать n-ый параметр из ’yyy’ в ’zzz’
Пояснение: скорее всего вы что-то не то написали внутри круглых скобок.

Сообщение: error C2039: ’xxx’ : is not a member of ’yyy’
Перевод: ошибка C2039: ’xxx’ : не является членом ’yyy’
Пояснение: cкорее всего вы ошиблись в написании ’xxx’.

Чтобы попасть на строчку с ошибкой, нужно нажать клавишу F8.


Помимо таких ляпов, как опечатки — забыл поставить точку с запятой, скобку и т.д. — существуют ошибки, которые компилятор отловить не может. Такие ошибки называются «логическими». Например, вы захотели посчитать сколько будет 2+2, но перепутали цифры и написали 2+3, в итоге вы получили неверный результат. Компилятор не может знать, что вы хотели посчитать, он посчитает, что вы его попросили посчитать. Современные компиляторы достаточно умны, чтобы отлавливать некоторые логические ошибки. Он их оформляет как предупреждение (warning). Советую обращать внимание на такие предупреждения, я думаю, в 99% такое предупреждение будет ошибкой.

Попробуйте, как-нибудь покорежить текст программы «Hello, world!» и посмотреть, как будет реагировать на такие изменения компилятор.

суббота, апреля 14

Разбор программы «Hello, world!»

Рассмотрим более пристально программу «Hello, world!» из предыдущего поста.
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
std::cin.get();
return 0;
}

Первая строчка
#include <iostream>
говорит компилятору, что мы будем использовать стандартный ввод и вывод. «include» переводится с английского как «включение». Директива «#include» — команда компилятору подключить (включить) библиотеку, в нашем случае это библиотека «iostream». «iostream» это сокращение от «input output stream» (поток ввода и вывода). Треугольные скобки означают, что мы будем использовать стандартную библиотеку.

Следущая строчка
int main()
объявляет функцию main. О функциях я буду говорить позже. Функция main самая главная функция в программе C++. С английского она так и переводиться «главная». С этой функции начинается выполнение программы. То что пойдет дальше в фигурных скобках выполняется программой, после ее компиляции и запуска.

Первая строчка после открывающей фигурной скобки
std::cout << "Hello, world!\n";
— команда вывода сообщения на экран. std означает, что мы будем пользоваться стандартными объектами. std::cout это стандартный поток вывода. Две открывающие треугольные скобочки (<<) команда вывести. Тексты в C++ заключаются в двойные кавычки ("). Обратите внимание на два символа в конце текста "Hello, world!\n" обратная косая черта и n такая последовательность называется Escape последовательность (читается: эскейп последовательность). \n означает перевод строки.
Все Escape последовательности начинаются с обратной косой черты (\).

Все команды в C++ заканчиваются точкой с запятой (;).

Следующая строка, мы уже знаем, ожидает ввода клавиши Enter. По аналогии, мы понимаем что std::cin это стандартный поток ввода.

И последняя строчка в блоке с фигурными скобками
return 0;
В ней дается команда на завершение функции main и в конечном итоге команда на завершение программы, причем при завершении программы будет возвращен ноль. Это число передается тому, кто запустил программу. Говорят так: «программа возвращает число». Ноль, обычно, означает успешное завершение программы, какое-то другое число означает ошибку в программе.

среда, апреля 11

Hello, world!

Многие учебники по программированию принято начинать с программы, которая выводить на экран надпись «Hello world!» В переводе с английского «Привет мир!» Не будем отходить от традиции. Вот эта программа.
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
Чтобы эта программа заработала под Visual C++, нужно будет немного повозиться.

Запустите Visual C++. В прошлом посте, я писал, что программа может состоять из нескольких файлов, в Visual C++ их принято объединять в один проект. Поэтому сначала мы создадим пустой проект, и потом в него будем добавлять файлы. Для создания пустого проекта, зайдите в меню File (Файл), затем выберите New (Новый) и Project (Проект). В диалоге New project (Новый проект) выберите Win32 в левой части окна, и Win32 Console Application (Консольное приложение Win32) в правой части окна.

Далее задайте имя проекта, например, «Hello» и при необходимости измените папку, в которой проект будет сохранен.



В появившемся диалоговом окне в Application Settings (Установки приложения), оставьте без изменений выбранный пункт Console application (Консольное приложение), и выберите пункт Empty project (Пустой проект), потом нажмите кнопку Finish.



Надо теперь в наш новый проект добавить файлы. Мы добавим только один файл. Для этого зайдите в меню Project, затем выберите Add New Item (Добавить новый элемент). Выберите тип файла C++ File (Файл C++). В поле Name (Имя) введите «Hello». И нажмите кнопку Add (Добавить).



Теперь можно печатать текст нашей программы.

Для запуска программы нажмите F5, что означает откомпилировать, слинковать и запустить. Часто процесс откомпилировать и слинковать называют одним словом build (построить, собрать).

После чего ваша первая программа должна выдать окошко с фразой «Hello, world!».

Скорее всего вы увидете только черное окно, которое сразу же закроется. Увидеть, то что программа написала на этом окне «Hello, world!», вы скорее всего не успеете. Чтобы что-то увидеть, вам придеться добавить одну строчку. Окончательный вид программы вот такой.

#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
std::cin.get();
return 0;
}
Теперь программа выведет на экран фразу «Hello, world!» и будет ждать нажатия клавиши Enter.

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

Литература: netcode, Википедия.