Язык программирования с#: история, специфика, место на рынке

Содержание разделаIn this section

ЗаголовокTitle ОписаниеDescription
Пошаговое руководство. Создание стандартной программы на языке C++Walkthrough: Creating a Standard C++ Program Создайте консольное приложение Windows.Create a Windows console application.
Пошаговое руководство. Создание классических приложений Windows (C++)Walkthrough: Creating Windows Desktop Applications (C++) Создайте собственное классическое приложение для Windows.Create a native Windows desktop application.
Мастер классических приложений WindowsWindows Desktop Wizard Используйте мастер для создания новых проектов Windows.Use the wizard to create new Windows projects.
Библиотека шаблонных классов (ATL)Active Template Library (ATL) Использование библиотеки ATL для создания COM-компонентов в C++.Use the ATL library to create COM components in C++.
Microsoft Foundation Classes (MFC)Microsoft Foundation Classes (MFC) Использование MFC для создания крупных или небольших приложений Windows с помощью диалоговых окон и элементов управленияUse MFC to create large or small Windows applications with dialogs and controls
Общие классы ATL и MFCATL and MFC Shared Classes Используйте такие классы, как CString, которые являются общими в ATL и MFC.Use classes such as CString that are shared in ATL and MFC.
Доступ к даннымData Access OLE DB и ODBCOLE DB and ODBC
Текст и строкиText and Strings Различные типы строк в Windows.Various string types on Windows.
Ресурсы для создания игры с помощью DirectXResources for Creating a Game Using DirectX
Как использовать пакет SDK для Windows 10 в классическом приложении WindowsHow to: Use the Windows 10 SDK in a Windows Desktop Application Пакет Windows SDKWindows SDK
Работа с файлами ресурсовWorking with Resource Files Добавление изображений, значков, таблиц строк и других ресурсов в классическое приложение.How to add images, icons, string tables, and other resources to a desktop application.
Ресурсы для создания игры с использованием DirectX (C++)Resources for Creating a Game Using DirectX (C++) Ссылки на материалы по созданию игр на C++.Links to content for creating games in C++.
Как использовать пакет SDK для Windows 10 в классическом приложении WindowsHow to: Use the Windows 10 SDK in a Windows Desktop Application Содержит инструкции по настройке проекта для построения с помощью пакета SDK для Windows 10.Contains steps for setting up your project to build using the Windows 10 SDK.
Развертывание классических приложенийDeploying Native Desktop Applications Развертывание собственных приложений в Windows.Deploy native applications on Windows.

Приложения универсальной платформы WindowsUniversal Windows Platform apps

Универсальная платформа Windows (UWP) — это современный API Windows.The Universal Windows Platform (UWP) is the modern Windows API. Приложения UWP работают на любом устройстве Windows 10, используют XAML для пользовательского интерфейса и полностью поддерживают касание.UWP apps run on any Windows 10 device, use XAML for the user-interface, and are fully touch-enabled. Дополнительные сведения об универсальномконтроллере платформы Windows см. в статье что такое приложение универсальная платформа Windows (UWP) .For more information about UWP, see What’s a Universal Windows Platform (UWP) app? and Guide to Windows Universal Apps.

Исходная поддержка C++ для UWP состояла из (1) C++/CX, диалекта C++ с расширениями синтаксиса или (2) библиотеки среда выполнения Windows (WRL), основанной на стандартном C++ и COM.The original C++ support for UWP consisted of (1) C++/CX, a dialect of C++ with syntax extensions, or (2) the Windows Runtime Library (WRL), which is based on standard C++ and COM. C++/CX и WRL по-прежнему поддерживаются.Both C++/CX and WRL are still supported. Для новых проектов рекомендуется использовать c++/WinRT, который полностью основан на стандартном c++ и обеспечивает более высокую производительность.For new projects, we recommend C++/WinRT, which is entirely based on standard C++ and provides faster performance.

Лицензионное соглашение

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

Без письменного согласия автора ЗАПРЕЩАЕТСЯ:

  1. 1) публикация материалов в любой форме, в том числе размещение материалов на других Web-сайтах;
  2. 2) распространение неполных или измененных материалов;
  3. 3) включение материалов в сборники на любых носителях информации;
  4. 4) получение коммерческой выгоды от продажи или другого использования материалов.

Использование и скачивание материалов означает, что вы приняли условия этого лицензионного соглашения.

Связанные разделыRelated Sections

Расширения компонентов для платформ среды выполненияComponent Extensions for Runtime PlatformsСправочные материалы по использованию компилятора Microsoft C++ для платформы .NET.Reference material on using the Microsoft C++ compiler to target .NET.

Справочные сведения о сборке C/C++C/C++ Building ReferenceПараметры компилятора, параметры компоновщика и другие средства сборки.Compiler options, linker options, and other build tools.

Справочник по препроцессору C/C++C/C++ Preprocessor ReferenceСправочный материал по прагма-директивам, директивам препроцессора, предопределенным макросам и препроцессору.Reference material on pragmas, preprocessor directives, predefined macros, and the preprocessor.

Библиотеки Visual C++Visual C++ LibrariesСписок ссылок на начальные страницы ссылок для различных библиотек Microsoft C++.A list of links to the reference start pages for the various Microsoft C++ libraries.

Что делают выражения

Теперь давайте попробуем понять почему написанная программа приводит в итоге к миганию светодиода.

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

Это делается выражением в функции :

pinMode(13, OUTPUT);

Выражения бывают разными: арифметическими, декларациями, определениями, условными и т.д. В данном
случае мы в выражении осуществляем вызов функции. Помните? У нас есть свои функции и
, которые вызываются чем-то, что мы назвали «нечто». Так вот теперь мы вызываем функции,
которые уже написаны где-то.

Конкретно в нашем мы вызываем функцию с именем . Она устанавливает заданный по номеру пин
в заданный режим: вход или выход. О каком пине и о каком режиме идёт речь указывается нами в круглых
скобках, через запятую, сразу после имени функции. В нашем случае мы хотим, чтобы 13-й пин работал
как выход. означает выход, — вход.

Уточняющие значения, такие как и называются аргументами функции. Совершенно не обязательно,
что у всех функций должно быть по 2 аргумента. Сколько у функции аргументов зависит от сути функции,
от того как её написал автор. Могут быть функции с одним аргументом, тремя, двадцатью; функции могут
быть без аргументов вовсе. Тогда для их вызова круглые скобка открывается и тут же закрывается:

noInterrupts();

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

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

Перейдём к функции :

void loop()
{
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
    delay(900);
}

Она, как говорилось, вызывается сразу после . И вызывается снова и снова как только сама заканчивается.
Функция называется основным циклом программы и идеологически предназначена для выполнения полезной
работы. В нашем случае полезная работа — мигание светодиодом.

Пройдёмся по выражениям по порядку. Итак, первое выражение — это вызов встроенной функции .
Она предназначена для подачи на заданный пин логического нуля (, 0 вольт) или логической единицы (, 5 вольт)
В функцию передаётся 2 аргумента: номер пина и логическое значение. В итоге, первым делом
мы зажигаем светодиод на 13-м пине, подавая на него 5 вольт.

Как только это сделано процессор моментально приступает к следующему выражению. У нас это вызов функции .
Функция — это, опять же, встроенная функция, которая заставляет процессор уснуть на определённое время.
Она принимает всего один аргумент: время в миллисекундах, которое следует спать. В нашем случае это 100 мс.

Пока мы спим всё остаётся как есть, т.е. светодиод продолжает гореть. Как только 100 мс истекают, процессор
просыпается и тут же переходит к следующему выражению. В нашем примере это снова вызов знакомой нам встроенной
функции . Правда на этот раз вторым аргументом мы передаём значение . То есть устанавливаем
на 13-м пине логический ноль, то есть подаём 0 вольт, то есть гасим светодиод.

После того, как светодиод погашен мы приступаем к следующему выражению. И снова это вызов функции .
На этот раз мы засыпаем на 900 мс.

Как только сон окончен, функция завершается. По факту завершения «нечто» тут же вызывает её ещё раз
и всё происходит снова: светодиод поджигается, горит, гаснет, ждёт и т.д.

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

  1. Поджигаем светодиод
  2. Спим 100 миллисекунд
  3. Гасим светодиод
  4. Спим 900 миллисекунд
  5. Переходим к пункту 1

Таким образом мы получили Arduino с маячком, мигающим каждые 100 + 900 мс = 1000 мс = 1 сек.

Разбор кода

Теперь давайте приступим к разбору написанного нами кода:

  • Строка 1:

    #include <iostream>

    1 #include <iostream>

    Здесь мы указываем для C++, какие именно дополнительные функции мы хотим использовать. За это отвечает , где , в нашей программе, требуемый нами функционал. Этот модуль отвечает за ввод и вывод информации на экран и с него. В дальнейших уроках мы научимся использовать другие стандартные модули языка C++.

  • Строка 2:

    using namespace std;

    1 usingnamespacestd;

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

  • Строки 4-8:

    int main() { … }

    1 intmain(){…}

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

  • Строка 5:

    cout << «I love coding!» << endl;

    1 cout<<«I love coding!»<<endl;

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

  • Строка 7:

    return 0;

    1 return;

    Она отвечает за код ошибки, который вернет наша программа после своего выполнения. Сам код указывается после оператора . Код 0 означает что программа отработала корректно без каких-либо ошибок. При возникновении ошибки ваша программа будет возвращать другие значения отличные от нуля. По умолчаний программа возвращает 0. Так что данная строка не обязательна.

Как видите здесь нет ничего сложного, лишь пару шаблонных строк кода. Остальное же, ограничено лишь вашим воображением и знанием языка программирования. Пожалуй основы C++ мы изучили, осталось лишь подитожить все выше перечисленное.

10 курсов программирования для начинающих

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

1. «Основы программирования» от GeekBrains

Основы программирования – интенсив от онлайн-университета GeekBrains, который познакомит вас с профессией, узнаете об языках и направлениях в программировании, зададите все волнующие вас вопросы преподавателю.

2. «Старт в программировании» от Нетологии

Старт в программировании – базовый курс познакомит вас с языками программирования JavaScript и HTML. Более 20 часов практики.

Во время прохождения обучения вы создадите свою первую программу.

3. «Веб-разработчик с нуля до PRO» от SkillBox

Веб-разработчик с нуля до PRO – полноценное обучение от онлайн-университета SkillBox для тех, кто хочет заниматься разработкой сайтов и сервисов. Подходит для начинающих.

Веб-разработчик – одно из самых, на сегодняшний день, востребованных направлений в программировании. Средняя зарплата по официальной статистике составляет 50 000 – 80 000 рублей в месяц.

По завершению вы получите диплом об обучении.

4. «Введение в программирование (С++)»

Введение в программирование (С++) – курс от Академии Яндекса и Высшей школы экономики (НИУ ВШЭ) на обучающей платформе Stepik, состоящих из 12 уроков с видео, тестами и интерактивными задачами.

5. «Как стать программистом» от университета Mail.ru (GeekBrains)

Как стать программистом / Пошаговая инструкция по поиску работы – на этом курсе вас не научат программировать, а расскажут всё о профессии.

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

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

6. «PHP. Уровень 1 (Основы веб-разработки)» от GeekBrains

PHP. Уровень 1 – ещё один курс для начинающих с нуля от онлайн-университета GeekBrains, на котором вы узнаете основы языка PHP.

7. «HTML и CSS с нуля» от Fructcode

Интерактивный курс по HTML и CSS – пошаговая программа по изучению основ верстки сайтов.

Здесь вы можете получить доступ сразу к нескольким курсам (HTML/CSS, Bootstrap 3, PHP/MySQL, Linux/GIT, Codeigniter, Javascript/jQuery, Modern Javascript, Yii2 Фреймворк, Bootstrap 4, VueJS Фреймворк) за ежемесячную подписку. Вам не нужно покупать сразу всё обучение, платите помесячно и проходите уроки в своём темпе.

Школа даёт возможность просмотреть часть уроков бесплатно, чтобы вы могли ознакомиться с платформой обучения и подачей материала. Так выглядит личный кабинет.

8. «ВЕБ-разработчик 2020» от beONMAX

ВЕБ-разработчик 2020 — с нуля до результата – большой курс для начинающих веб-разработчиков. Освоите основные инструменты и технологии создания сайтов и приложений на HTML5, CSS3, Bootstrap 4, JavaScript.

9. «Основы С++» от Смотри и учись

Основы С++ – 12 лекций продолжительностью 13 часов. Разбираются базовые элементы языка, работа с файлами и функциями, структурное и объектно-ориентированное программирование.

10. «Программирование на Python для начинающих» от Михаила Русакова

Программирование на Python для начинающих –  неплохой курс по изучению основ языка Python. Автор оказывает поддержку при прохождении и отвечает на вопросы.

Облачные IDE

Большинство десктопных приложений перешли в «облако», поэтому нет ничего удивительного, что облачные среды также становятся популярными среди программистов. Не каждый сразу доверяет облачным IDE, но популярные инструменты вроде Github и Pastebin помогают привыкнуть к тому, что исходный код хранится не на локальной машине, а на стороннем сервере.

Cloud9

После нескольких минут работы в Cloud9 создаётся впечатление, что попал в рай для программистов. Интерфейс написан на JavaScript, а серверная часть — на NodeJS. Хотя Cloud9 облюбовали разработчики и дизайнеры интерфейсов, поддерживается подсветка синтаксиса C#, C++, Python, Perl, Ruby, Scala и некоторых других языков.

Встроенный режим Vim — приятный штрих, как и поддержка популярных систем контроля версий вроде Git, Mercurial и SVN. Благодаря наличию CSSLint и JSBeautify это одна из красивейших сред разработки.

Система платная, но есть бесплатный тарифный план.

Codeanywhere

Ещё один инструмент для создания приложений, который часто возглавляет списки лучших — Codeanywhere. Эта дружественная облачная IDE поддерживает подсветку кода HTML, CSS, JavaScript, PHP, MySQL и других языков. Благодаря наличию приложений для iOS, Android и BlackBerry, с помощью Codeanywhere программисты работают где угодно.

Кроме того, Codeanywhere поддерживает Dropbox и SFTP, которые помогают легко создавать резервные копии файлов проекта и обмениваться ими с коллегами. Это не самая полнофункциональная среда, но свою работу выполняет на отлично.

Система платная, но есть бесплатный тарифный план.

Eclipse Che

Eclipse Che — облачное рабочее пространство разработчика и встроенная IDE. Che предоставляет удалённую платформу с открытым исходным кодом для многопользовательского создания приложений.

Основные возможности:

  • рабочие пространства, включающие среды выполнения и IDE,
  • сервер рабочих мест с RESTful веб-сервисами,
  • облачная IDE,
  • плагины для языков, платформы и инструменты,
  • SDK для создания плагинов и сборок.

Eclipse Che имеет две сборки — однопользовательскую и многопользовательскую. В первой нет компонентов, которые предоставляют мультиарендность и разграничение прав доступа. В этом случае сервер остаётся без защиты, но для локальной разработки — это хороший выбор.

Многопользовательская предоставляет мультиарендность. Учётные записи пользователей и рабочие места изолированы, а для регистрации, управления и аутентификации используется механизм KeyCloak. Permissions API регламентируют доступ к объектам вроде пространств, стеков и организаций. Сведения о пользователях хранятся в базе данных, поддерживающей миграцию (PostgreSQL).

Neutron Drive

Создание универсальной облачной среды IDE с нуля — серьёзная задача, поэтому разработчики предпочитают создавать проекты на базе готовых решений с открытым исходным кодом. Neutron IDE основан на редакторе Ace code editor и объединяет функции SFTP-клиентов и браузерных редакторов, позволяя программистам редактировать на лету файлы на своих серверах из любой точки мира.

Благодаря поддержке настраиваемых горячих клавиш Vi и Emacs, а также визуальных тем TextMate, интерфейс этой облачной среды гибкий и адаптируется под пользователя.

Orion

Популярная среда Eclipse Java IDE — надёжная опора в мире разработки уже много лет. Orion — следующий шаг, в котором опыт Eclipse перенесли в облако. Пока больше применяется для front-end, поэтому среда ограничена по большей части HTML и JavaScript, но работа идёт, и функции добавляются. Помимо поддержки Firebug, огромный плюс — интуитивно понятный интерфейс в стиле Eclipse.

О точках с запятыми

Вы могли заинтересоваться: зачем в конце каждого выражения ставится точка с запятой? Таковы правила C++.
Подобные правила называются синтаксисом языка. По символу компилятор понимает где заканчивается
выражение.

Как уже говорилось, переносы строк для него — пустой звук, поэтому ориентируется он на этот знак препинания.
Это позволяет записывать сразу несколько выражений в одной строке:

void loop()
{
    digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900);
}

Программа корректна и эквивалентна тому, что мы уже видели. Однако писать так — это дурной тон. Код
гораздо сложнее читается. Поэтому если у вас нет 100% веских причин писать в одной строке несколько
выражений, не делайте этого.

О пустом месте и красивом коде

В языке C++ пробелы, переносы строк, символы табуляции не имеют большого значения для компилятора.
Там где стоит пробел, может быть перенос строки и наоборот. На самом деле 10 пробелов подряд,
2 переноса строки и ещё 5 пробелов — это всё эквивалент одного пробела.

Пустое пространство — это инструмент программиста, с помощью которого можно или сделать программу
понятной и наглядной, или изуродовать до неузнаваемости. Например, вспомним программу для мигания
светодиодом:

void setup()
{
    pinMode(5, OUTPUT);
}
 
void loop()
{
    digitalWrite(5, HIGH);
    delay(100);
    digitalWrite(5, LOW);
    delay(900);
}

Мы можем изменить её так:

void setup(
)
    {
pinMode(5, OUTPUT);
    }
 
        void loop
    () {
digitalWrite(5,HIGH);
delay(100
)
;
    digitalWrite(5,LOW);
    delay(900); }

Всё, что мы сделали — немного «поработали» с пустым пространством. Теперь можно наглядно видеть
разницу между стройным кодом и нечитаемым.

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

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

Плохо:

void loop()
{
digitalWrite(5, HIGH);
delay(100);
digitalWrite(5, LOW);
delay(900);
}

Хорошо:

void loop()
{
    digitalWrite(5, HIGH);
    delay(100);
    digitalWrite(5, LOW);
    delay(900);
}

2. Как и в естественном языке: ставьте пробел после запятых и не ставьте до.

Плохо:

digitalWrite(5,HIGH);
digitalWrite(5 , HIGH);
digitalWrite(5 ,HIGH);

Хорошо:

digitalWrite(5, HIGH);

3. Размещайте символ начала блока на новой строке на текущем уровне отступа или в конце предыдущей.
А символ конца блока на отдельной строке на текущем уровне отступа:

Плохо:

void setup()
{
    pinMode(5, OUTPUT); }
 
void setup()
    {
    pinMode(5, OUTPUT);
    }
 
void setup()
        {
    pinMode(5, OUTPUT);
        }

Хорошо:

void setup()
{
    pinMode(5, OUTPUT); 
}
 
void setup() {
    pinMode(5, OUTPUT); 
}

4. Используйте пустые строки для разделения смысловых блоков:

Хорошо:

void loop()
{
    digitalWrite(5, HIGH);
    delay(100);
    digitalWrite(5, LOW);
    delay(900);
    digitalWrite(6, HIGH);
    delay(100);
    digitalWrite(6, LOW);
    delay(900);
}

Ещё лучше:

void loop()
{
    digitalWrite(5, HIGH);
    delay(100);
 
    digitalWrite(5, LOW);
    delay(900);
 
    digitalWrite(6, HIGH);
    delay(100);
 
    digitalWrite(6, LOW);
    delay(900);
}

Методика

В программе предусмотрено изучение языка Си в
7-11 классах:

7 класс

Часть I представляет собой расширенный конспект курса
7 класса. Введение в язык Си строится на базе алгоритмической
подготовки, которую дети получили в 6 классе, работая с
исполнителями.

Основная задача — познакомить учащихся с основными
конструкциями языка Си: циклами, условными операторами,
процедурами. Весьма успешно проходит изучение разделов,
связанных с графикой, анимацией.

Для работы с графикой через браузер можно использовать
онлайн-сервис
Антона Деникина.

8 класс

Программа включает следующие разделы (в скобках указана часть конспекта):
Массивы (II), Работа с файлами (II), Символьные строки (II), Вращение объектов (III),
Моделирование (III)

Особое внимание уделяется изучению
алгоритмов работы с массивами, в том числе поиска, сортировки и т.п.
Дается понятие об эффективности вычислительных методов.. 9 класс

9 класс

Основное внимание уделяется изучению методов разработки
программ на языке Си. Учащиеся выполняют индивидуальное задание, в ходе которого
учатся строить графики на экране, знакомятся с преобразованиями
систем координат, изучают методы решения уравнений, знакомятся с численными
методами, учатся правильно оформлять программы (разделы 1-2 части III).
Одно из заданий посвящено использованию метода Монте-Карло для вычисления
площади сложной фигуры

Из новых разделов изучаются также
Матрицы (II), Массивы символьных строк (II). Вводится понятие
указателей и изучаются простейшие операции с ними.

10 класс

Изучения языка Си выходит на более серьезный уровень. Основные
темы — Управление памятью (II), Рекурсия (II), Структуры (II).
Предусмотрено изучение языка Паскаль в качестве второго языка программирования.
С этого момента алгоритмы на теоретических занятиях записываются
поочередно на двух языках.

11 класс

Изучаются не столько особенности языков, сколько
алгоритмы. Основные разделы — Численные методы (III), Моделирование (III),
Динамические структуры данных (IV)
.

Рейтинг IDE для С++ по данным Standard C++ Foundation

Первое место среди IDE у Visual Studio с 55.28% использующих его разработчиков, второе у Qt Creator — 24.41% разработчиков, третье место у CLion — 14.66%, четвертое место занимает Eclipse — 12.78% разработчиков, пятое место у XCode — 12.22% разработчиков, шестое место у Android Studio – 5.15%, седьмое у Code::Blocks – 4.85%.

Как мы видим многие разработчики для работы используют текстовые редакторы с различными расширениями функций или без них. В число таких входят: Vim — 37.93% разработчиков, Visual Studio Code — 25.77% разработчиков, Emacs (технически, это текстовый редактор с расширениями функционала до IDE) — 13.55%, Sublime — 12.78%.

Добавить комментарий

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

Adblock
detector