- Регистрация
- 13.04.2019
- Сообщения
- 800
- Благодарностей
- 547
- Баллы
- 93
Всех приветствую, на связи Brabus
В этой статье, надеюсь, я дам понять новичкам, что c# - это не что-то заумное и сложное, а не трудный, и самое главное - оооочень нужный навык, если вы хотите расти в зенопостере и деньгах. Статья подойдёт тем людям, кто уже хорошо владеет стандартными кубиками зенопостера.
Я и на кубиках умею, зачем вообще нужен c#?!
Что вы будете делать, когда захотите создать действительно большой проект с множеством ответвленний и подветвленний, который без c# займет у вас пару тысяч кубиков или когда вам понадобиться то, что не закладывалось в стандартный функционал зенопостера. Например, мне нужно нагенерировать много картинок, или написать автоинсталятор pmta для сервера, или сделать шаблон для использование sms-сервиса, которого нет в зенопостере (можно и на кубиках post/get, но мне удобнее кодом, суть вы поняли).
Почему именно эта статья?
Удобство моей статьи будет в том, что я буду разбирать какую-то тему, приводить реальный примеры из моих ботов, а так же его аналог на зено-кубиках.
Почему я уверен, что начать изучать кодинг на c# - это не трудно?
Осмелюсь предположить, что кто-нибудь из читающих краем глаза видел один из моих топиков на зенолабе, посвященный рассылкам. Если вы его не видели, то он посвящен боту для рассылок, написанному почти на 100% на языке c#.
Скорее всего интересующиеся люди подумали, что автор - это кодер со стажем. А на самом деле автором был я - человек с гуманитарным образованием, который начал изучать программирование за пару месяцев до создание этого бота. Сейчас, конечно, багаж знаний в 100 раз больше, но тогда его не было.
Посмотрев на свои рабочие шаблоны со стороны - я выделил минимальный набор знаний по c#, который поможет начать писать свои кусочки кода, или даже редактировать имеющиеся. Как показывает практика, самое трудное - это начать, т.к. люди не понимают что им нужно, а что не нужно для старта. Бегают между сотнями статьями, поглощая знания, которые им еще рановато поглощать, хотя простой процедурный код может легко закрыть их потребности.
И так, что нужно знать, чтобы начать писать свои снипеты?
Типов переменных в c# много, пока я писал это предложение - я вспомнил больше 10 штук. Но для начала работы нам понадобится всего 2 - это int и string
int - может хранит целочисленные значения в диапазоне от -2147483648 до 2147483647. С головой хвататет чтобы записать, например, число выполнений какого либо действия, или паузу при ожидании, или привязать к какому-нибудь счетчику выполнений
string - может хранит текстовую информацию. Прекрасно подойдет, например, для сохранения результата парсинга со страницы, или когда вам нужно взять строчку из файла, или нужно сохранить результат post/get запроса. Значение у переменных типа string записываетя в ковычках " ".
У переменных есть название (так же, как и в зенопостере). Именно по названию мы обращаемся к переменным. Название переменной должно быть таким, чтобы через 5 лет вы зашли в свой код и сразу вспомнили, зачем нужна эта переменная. Переменные принято называть английскими словами, с маленькой буквы, без пробелов.
Заметили точку с запятой в конце строки? Отлично, т.к. в конце любой завершённой строчки кода нужно ставить точку с запятой.
Аналог на zenno-кубиках
Разработчики зенолаба сделали большое удобство - в переменные c# можно помещать значиния из среды зенопостера. Представим, что в вашем шаблоне есть переменная dom, которая хранит дом-модель сайта, как её можно перенести в c#?
Домашнее задание
• Загуглить какие еще бывают типы переменных (просто загуглить для ознакомления)
• Загуглить арифметические операции с переменными в c#
Еще один понятный пример
Представьте полку с книгами - это был бы одномерный массив с типом данных "книга". Теперь представьте шкаф с книгами - это будет двумерных массив с типом данных "книга". Теперь представьте комнату со шкафами с книгами - это будет многомерный массив с типом данных "книга".
Какого же типа будет массив из таблицы умножения?
Тип int, т.к. таблица умножения состоит из целочисленных значений. Да, у массивов, как и у переменных, есть свой тип данных.
Если визуализировать массив в виде таблички (или в виде строки, или в виде столбца), то станет понятно, что массив состоит из ячеек. Чтобы мы могли как-то взаимодействовать с ячейками - нам нужен номер ячейки, а точнее её индекс.
Вспоминаем аналогию с полками книг. Если у Вас длина полки ограничена 5ью книгами, то больше на неё мы поставить не можем.
Вы наверно задумались, почему я сказал про вторую ячейку, а написал цифру 1? Потому что в программировании отсчет идет с нуля, а не с единицы.
Пример из практики
У меня в боте для рассылок есть шаг, где на аккаунте нужно проверить Входящие на наличие письма с жалобой от mail.ru.
Как это сделать?
Для начала нужно куда-то удобно сохранить все входящие письма, чтобы потом поочередно их проверить.
Куда же их можно сохранить?
В одномерный массив. Можно конечно было бы для каждого письма создать свою собственную переменную, но это тоже самое, что вместо пылесоса вы будете собирать рис с пола пинцетом.
Какой тип данных будет у массива?
У массива будет тип данных string, т.к. письма - это текстовая информация.
В строке под номер 1155 я создаю одномерный массив с названием resultInbox и типом данных string, и складываю в него все письма, которые нашлись с помощью регулярного выражения в переменной getInbox, где getInbox - это переменная типа string, которая хранит результат обычного гет-запроса. И как напоминалку я оставил сам себе комментарий в строке 1154
Графическое представление массива
Домашнее задание
• Загуглить, что такое двумерные массивы (просто загуглить для ознакомления)
• Создайте одномерный массив, в котором бы вы хранили возраст членов своей семьи (в кубике c#)
• Создайте одномерный массив, в котором бы вы хранили имена членов своей семьи (в кубике c#)
Банальный пример условного оператор из жизни
Если на улице идет дождь - взять с собой зонт, иначе возьмем с собой очки.
- У нас есть условие и есть действие, которое мы выполним, если условие верно.
В с# есть два типа таких конструкций: if...else и switch...case. Поговорим про более популярный - if...else
if - перевод с англ. "если"
else - перевод с англ. "иначе"
Изменим пример с зонтом из жизни
if на улице идет дождь, то возьмем зонт, else не будем брать зонт, а возьмем очки.
Давайте представим, что вы написали парсер погоды. В переменную с названием weather типа string вы сохраняете одно из двух вохможных значений: "будет дождь" или "будет солнечно". Заранее мы не можем знать, что выдаст наш парсер, но мы будем готовы к любому исходу, благодаря условным операторам.
Заметили фигурные скобочки, двойное равно и двойной слеш? Я тоже заметил!
В фигурные скобочки { } почти всегда оборачиваются различные конструкции, чтобы четко определить начало и конец конструкции.
Двойное равно == используется для сравнения (оператор сравнения). Это такойже оператор сравнения, как и операторы больше/меньше > <
Двойной слеш // - именно так можно писать небольшие комментарии к своему коду. Я всегда комментирую свой код, чтобы потом легко вспомнить что делает кусок кода, когда через 2 месяца мне нужно будет что-нибудь поправить в нём.
Аналог на zenno-кубиках
Данный пример можно было написать и по другому, но так делать не корректно
Почему не корректно?
Потому что у нас всего 2 предсказанных исхода, и правильнее использовать просто конструкцию if...else
Другой пример. Представьте, что вам нужно сравнить два числа
Давайте попробуем сделать следующее сравнение
После выполнения такого кусочка кода получаем злое уведомление об ошибке. Помните, что нельзя складывать переменные разных типов данных? Сравнивать их тоже нельзя. А что делать если сильно захотелось сравнить разные типы данных? Это останется в ДЗ со звездочкой.
Реальный пример из практики
В моём боте пользователь может выбрать, формировать текст письма из обычного txt файла, или из html-файла. Заранее я не знаю, что выберет пользователь, поэтому с помощью условного оператора if...else я подготовился к обоим вариантам
Переменная needHtmlFile указывается во сходных настройках, с помощью галочки
Если галочка нажата, то переменная needHtmlFile примет значение "True", иначе она будет "False". Именно поэтому я сравниваю её с "True".
Дословно код делает слудующее
Если(if) пользователь выбрал "Использовать html-файлы для письма", то парсим папку с залитыми html-файлами, выбираем из них случайный и распарсиваем html-файл. Иначе(else) мы берем текст и файла "Текст.txt".
Заметили небольшую паскалку?
Я специально не закрашивал строку 597. В этой строке я объявляю одномерный массив htmlFiles с типов string и сохраняю в этот массив пути ко всем файлам, которые нашлись в директории folderHtmlFilePath. Путь к файлу - это текстовая информация, поэтому у массива тип string
Чтобы пользоваться условными операторами нужно понять, что компилятор (штука, которая проверяет и выполняет ваш код), не понимает такие слова, как "верно" и "неверно", но зато она знает такие понятия как "истина" и "ложь", а точнее true и false. Кстати, поздравляю! Вы только что открыли новый тип данных bool, который может принимать значение true или false.
Блок-схема if...else
Домашнее задание
• Загуглите 2 конструкции if..else_if...else и switch...case (просто загуглить для ознакомления)
• Загуглите какие бывают операторы сравнения в с#
• Создайте имитированный кусочек кода, который бы выводил в лог следующую информацию: "сегодня на улице больше 0 градусов" и "сегодня на улице меньше 0 градусов". Для примера воспользуйтесь моим имитированным примером с зонтом и очками.
• Создайте имитированный кусочек кода, который бы выводил в лог следующую информацию: "пора завтракать", "пора обедать" и "пора ужинать", если вы знаете, что завтракать можно ровно в 8 или 9 или 10 часов утра, обедать можно ровно в 13 или 14 часов дня, ужинать можно ровно в 18 или 19 или 20 часов вечера
• *Загуглите про конвертацию типов данных из string в int
Дословно мы сделали следующие:
1) Начинаем цикл и объявляем переменную с названием i типа int со значением 0
2) Цикл нужно выполнять до тех пор, пока переменная i меньше 10ти
3) В конце кажого шага цикла (итерации) прибавлять к переменной i единицу, i++ - это тоже самое, что i = i + 1;
Результатом выполнения данного кода будет следующее
Аналог на zenno-кубиках
Реальный пример из практики
В моём боте каждый аккаунт делает заданное число отправок. Реализовано это с помощью цикла for. Переменная c названием sendAmount с типом int хранит число отправок, которое должен сделать аккаунт. Для примера пусть это будет 20 писем.
int sendAmount = 20;
for (int i = 0; i < sendAmount; i++) {
//тут у меня большой блок кода, который отвечает за отправку одного сообщения
}
На строке под номером 485 начинается цикл for и заканчивается только через пару тысяч строк кода.
Блок-схема цикла for
Домашнее задание
• Напишите кусочек кода, который поочередно выведет в лог имена членов вашей семьи (подсказка: используйте связку массив + цикл, к ячейкам массива можно обращаться по их индексу (порядковому номеру))
• Загуглите следующие конструкции: foreach, while и do...while (просто загуглить для ознакомления)
Аналог на zenno-кубиках
Оператор goto позволяет переместить выполнение програмы в другое место кода. Zenno-аналогом являются стрелочки от кубика к кубику. С помощью стрелочки мы можем перевести выполнение шаблона в любое удобное место - тоже самое делает оператор goto
Метод Contains позволяет проверить наличие одной строки в другой строке. Получается некий аналог быстрого регулярного выражения.
Пример из практики
В моём боте есть проверка входящих писем на предупреждение от mail.ru, что письмо не доставлено адресату. В этом предупреждении есть фраза "Ваше письмо не доставлено". Вместо того, чтобы городить регулярные выражения - я воспользоватлся методом Contains()
Дословно код делает следующее
Если(if) в письме содержится словосочетание "Ваше письмо не доставлено", то мы делаем кусок кода, который это предусматривает.
Конструкция lock используется при многопоточном выполнении шаблона и накладывает некое ограничение на выделенный кусок кода. Когда один поток начнет выполнять кусок кода, обернутый в lock - все другие потоки будут ждать своей очереди, чтобы тоже начать выполнять этот код. Если грубо округлить - мы делаем кусок кода однопоточным.
Данная конструкция очень полезна при использовании глобальных переменных и действиях, которые зависят от глобавльных переменных.
Пример из практики
В моём боте можно отправлять письма себе на контрольные почты, чтобы отслеживать рассылку. Делать отправку себе на контрольную почту можно раз в N отправок. Чтобы считать общее число отправок во всех потоках - используется глобальная переменная (переменная, которая работает одновременно во всех потоках). Это будет некий счетчик, доступный всем потокам. Когда поток совершает отправку - он будет прибавлять к этому счетчику +1 (и так в каждом потоке при каждой отправке письма)
К примеру я задал отправлять контрольное письмо себе через каждые 100 отправок. Потоки отправляют письма и вот-вот будет 100-ая отправка.
100-ая отправка, условно, выпадает на 4й поток и он должен сделать отправку себе на контрольную почту. Но в эту же секунду отправку делает, условно, 3й поток и увеличивает счетчик на +1.
Только что у 4го потока была информация, что сделано ровно 100 отправок, но в дело вмешался 3й поток и исправил счетчик на +1 и счетчик получился равен 101. Получается, что 4й поток не сделает отправку на контрольную почту, счетчик ведь уже прошел число 100
Как решать данную проблему? С помощью конструкции lock мы можем сделать так, чтобы потоки не вмешивались в работу друг друга при работе с счетчиком
Представим ситуацию, что у вас есть достоточно большой и сложный кусок кода, который потенциально может выдавать ошибки (в програмировании они называются исключения (от англ. "Exception").
Заранее вы не всегда знаете, какие это могут ошибки. Вдруг пользователеть вашего бота в графе, где нужно указать число отправок с аккаунта, напишет "привет, как дела?". Вместо .txt файла с базой адресатов он укажет путь к смешной картинке с котиками. Или хостинг с прокси, который использует пользователь для отправки писем - внезапно упадет из-за ddos атаки и прокси перестанут работать.
Такие сценарии невозможно предсказать и поэтому необходимо использовать конструкцию try...catch
ЗавершениеНа этом я заканчиваю свою статью. Надеюсь вы заметили в ДЗ повторяющуюся фразу "загуглите", т.к. умение нормально гуглить спасает любого програмиста почти на любой стадии его развития.
Если что-то недопоняли, то велком в комментарии задавать вопросы и скидывать свои ДЗ. Не обещаю, что у всех, но я постараюсь отвечать на вопросы и проверять ваши ДЗ (скорее всего через пару недель я уже не смогу отвечать на вопросы и проверять ДЗ, поэтому поторопитесь).
Бота, которого я приводил как пример вы можете посмотреть вот тут. Топик с ботом я создавал будучи неопытным кодером, но всё получилось нормально - главное не боятся начать.
Если вы хорошо усвоите материал из данной статьи, то в будущем вы просто будете накладывать на этот фундамент новые знания, тем самым - улучшая скил в кодинге и решая всё более трудные задачи.
С наилучшими пожеланиями, Ваш Brabus
Telegram: https://t.me/brabus_bots_channel
В этой статье, надеюсь, я дам понять новичкам, что c# - это не что-то заумное и сложное, а не трудный, и самое главное - оооочень нужный навык, если вы хотите расти в зенопостере и деньгах. Статья подойдёт тем людям, кто уже хорошо владеет стандартными кубиками зенопостера.
Я и на кубиках умею, зачем вообще нужен c#?!
Что вы будете делать, когда захотите создать действительно большой проект с множеством ответвленний и подветвленний, который без c# займет у вас пару тысяч кубиков или когда вам понадобиться то, что не закладывалось в стандартный функционал зенопостера. Например, мне нужно нагенерировать много картинок, или написать автоинсталятор pmta для сервера, или сделать шаблон для использование sms-сервиса, которого нет в зенопостере (можно и на кубиках post/get, но мне удобнее кодом, суть вы поняли).
Почему именно эта статья?
Удобство моей статьи будет в том, что я буду разбирать какую-то тему, приводить реальный примеры из моих ботов, а так же его аналог на зено-кубиках.
Почему я уверен, что начать изучать кодинг на c# - это не трудно?
Осмелюсь предположить, что кто-нибудь из читающих краем глаза видел один из моих топиков на зенолабе, посвященный рассылкам. Если вы его не видели, то он посвящен боту для рассылок, написанному почти на 100% на языке c#.
Скорее всего интересующиеся люди подумали, что автор - это кодер со стажем. А на самом деле автором был я - человек с гуманитарным образованием, который начал изучать программирование за пару месяцев до создание этого бота. Сейчас, конечно, багаж знаний в 100 раз больше, но тогда его не было.
Посмотрев на свои рабочие шаблоны со стороны - я выделил минимальный набор знаний по c#, который поможет начать писать свои кусочки кода, или даже редактировать имеющиеся. Как показывает практика, самое трудное - это начать, т.к. люди не понимают что им нужно, а что не нужно для старта. Бегают между сотнями статьями, поглощая знания, которые им еще рановато поглощать, хотя простой процедурный код может легко закрыть их потребности.
На простом языке объясню, что такое ООП (объектно-ориентированное программирование) и процедурное программирование.
(Спойлер - ООП нам пока не нужно)
ООП - это методология программирования, при которой программа представлена в виде каких-либо объектов (сущностей). У объектов есть свои характеристики (свойства), объекты умеют что-то делать (методы) и эти объекты взаимодействуют друг с другом так, как мы это зададим (с помощью методов и свойств). ООП - это мастхев при разработки действительно больших ПО (програмное обеспечение). С этим понятием вы скорее всего сталкивались, если начинали изучать язык. Так вот, в 95% случаев (на старте изучения) - вам вообще не нужно знать, что такое ООП
Наш выбор - это процедурное программирование. Глубо говоря - это когда программа банально выполняется сверху вниз и в конце даёт результат.
(Спойлер - ООП нам пока не нужно)
ООП - это методология программирования, при которой программа представлена в виде каких-либо объектов (сущностей). У объектов есть свои характеристики (свойства), объекты умеют что-то делать (методы) и эти объекты взаимодействуют друг с другом так, как мы это зададим (с помощью методов и свойств). ООП - это мастхев при разработки действительно больших ПО (програмное обеспечение). С этим понятием вы скорее всего сталкивались, если начинали изучать язык. Так вот, в 95% случаев (на старте изучения) - вам вообще не нужно знать, что такое ООП
Наш выбор - это процедурное программирование. Глубо говоря - это когда программа банально выполняется сверху вниз и в конце даёт результат.
И так, что нужно знать, чтобы начать писать свои снипеты?
Переменные
Переменные - это ячейки памяти, в которых хранится какая-либо информация. Переменные в зенопостере - это тоже самое, что и переменные в c#. В c# у переменных есть свой тип (целочисленный тип int, текстовый тип string, логический тип bool и т.д.). К слову - в зенопостере у переменных тоже есть свой тип (как минимум во входных настройках).Типов переменных в c# много, пока я писал это предложение - я вспомнил больше 10 штук. Но для начала работы нам понадобится всего 2 - это int и string
int - может хранит целочисленные значения в диапазоне от -2147483648 до 2147483647. С головой хвататет чтобы записать, например, число выполнений какого либо действия, или паузу при ожидании, или привязать к какому-нибудь счетчику выполнений
string - может хранит текстовую информацию. Прекрасно подойдет, например, для сохранения результата парсинга со страницы, или когда вам нужно взять строчку из файла, или нужно сохранить результат post/get запроса. Значение у переменных типа string записываетя в ковычках " ".
У переменных есть название (так же, как и в зенопостере). Именно по названию мы обращаемся к переменным. Название переменной должно быть таким, чтобы через 5 лет вы зашли в свой код и сразу вспомнили, зачем нужна эта переменная. Переменные принято называть английскими словами, с маленькой буквы, без пробелов.
Создали целочисленную переменную с названием number с типом int и задали ей значение 5:
int number = 5;
Создали строковую переменную с названием word с типом string и задали ей значение "Hello world!";:
string word = "Hello world!";
Аналог на zenno-кубиках
Создали переменные с названием number1 и number2 с типом int и задали им значения 5 и 10, а затем создали переменную number3 и записали в неё результат сложения первых двух переменных:
int number1 = 5;
int number2 = 10;
int number3 = number1 + number2; //переменная number3 будет хранить значение 15
C#:
/*Создали переменные с названием word1 и word2 с типом string и задали им значения "Hello " и "wolrd!",
а затем создали переменную word3 и записали в неё результат сложения первых двух переменных*/
string word1 = "Hello ";
string word2 = "wolrd!";
string word3 = word1 + word2; //переменная word3 будет хранить значение "Hello world!"
Попробуем сложить переменные с типом int и string:
int number = 5;
string word = "Hello world!";
string number_word = number + word; //получаем ошибку, может попробуем сделать финальную переменную number_word типом int?
int number_word = number + word; //получаем ошибку! Во-первых нельзя складывать переменные с разными типами данных, во вторых ранее мы уже создавали переменную с именем number_word;
Пример использование zenno-переменных в c# коде:
//Я всегда называю zenno-переменный и переменные и c# одинакого, чтобы было легче работать с ними
string dom = project.Variables["dom"].Value; //создали переменную dom в c# и сохранили в неё значение из zenno-переменно dom
//По дефолту zenno-переменные имеют тип string, поэтому мы можем даже сделать так:
string dom = "hello! " + project.Variables["dom"].Value;
• Загуглить какие еще бывают типы переменных (просто загуглить для ознакомления)
• Загуглить арифметические операции с переменными в c#
Массивы
Массивы - это объединенная кучка данных (одного и того же типа данных). Массивы бывают одномерные и многомерные. Пример двумерного массива - таблица умножения. Если же мы возьмем отдельно 1 строчку или 1 столбец из таблицы умножения - это будет одномерный массив. Бываю еще массивы, состоящие из массивов, но нам это пока не нужно.Еще один понятный пример
Представьте полку с книгами - это был бы одномерный массив с типом данных "книга". Теперь представьте шкаф с книгами - это будет двумерных массив с типом данных "книга". Теперь представьте комнату со шкафами с книгами - это будет многомерный массив с типом данных "книга".
Какого же типа будет массив из таблицы умножения?
Тип int, т.к. таблица умножения состоит из целочисленных значений. Да, у массивов, как и у переменных, есть свой тип данных.
Если визуализировать массив в виде таблички (или в виде строки, или в виде столбца), то станет понятно, что массив состоит из ячеек. Чтобы мы могли как-то взаимодействовать с ячейками - нам нужен номер ячейки, а точнее её индекс.
Создание одномерного массива с типом данных int, размером в 5 ячеек. Больше 5ти значений в него мы поместить не сможем:
int[] array = new int[5];
C#:
//Создание одномерного массива с типом данных int и его инициализация 5тью значениями. Т.к. размер массива не был сразу прописан, то можно было бы добавить и больше значений
int[] array = new int[] { 1, 3, 5, 7, 9 };
//Создадим переменную и запишем в неё значение второй ячейки массива array
int number = array[1]; //в переменную number будет записано число 3
Можно еще вот так::
int[] array;
array = new int[] { 1, 3, 5, 7, 9 };
Создание одномерного массива с типом данных string и его инициализация 7ю значениями. Т.к. размер массива не был сразу прописан, то можно было бы добавить и больше значений:
string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
У меня в боте для рассылок есть шаг, где на аккаунте нужно проверить Входящие на наличие письма с жалобой от mail.ru.
Как это сделать?
Для начала нужно куда-то удобно сохранить все входящие письма, чтобы потом поочередно их проверить.
Куда же их можно сохранить?
В одномерный массив. Можно конечно было бы для каждого письма создать свою собственную переменную, но это тоже самое, что вместо пылесоса вы будете собирать рис с пола пинцетом.
Какой тип данных будет у массива?
У массива будет тип данных string, т.к. письма - это текстовая информация.
В строке под номер 1155 я создаю одномерный массив с названием resultInbox и типом данных string, и складываю в него все письма, которые нашлись с помощью регулярного выражения в переменной getInbox, где getInbox - это переменная типа string, которая хранит результат обычного гет-запроса. И как напоминалку я оставил сам себе комментарий в строке 1154
Графическое представление массива
Домашнее задание
• Загуглить, что такое двумерные массивы (просто загуглить для ознакомления)
• Создайте одномерный массив, в котором бы вы хранили возраст членов своей семьи (в кубике c#)
• Создайте одномерный массив, в котором бы вы хранили имена членов своей семьи (в кубике c#)
Условные операторы
Условные операторы (от слова "условие") - это конструкции, которые позволяют выполнять или не выполнять какие-либо действия, в зависимости от заранее заданных условий. Если заданное условие верно (или наоборот - неверно), то выполняется какое-либо действие.Банальный пример условного оператор из жизни
Если на улице идет дождь - взять с собой зонт, иначе возьмем с собой очки.
- У нас есть условие и есть действие, которое мы выполним, если условие верно.
В с# есть два типа таких конструкций: if...else и switch...case. Поговорим про более популярный - if...else
if - перевод с англ. "если"
else - перевод с англ. "иначе"
Изменим пример с зонтом из жизни
if на улице идет дождь, то возьмем зонт, else не будем брать зонт, а возьмем очки.
Давайте представим, что вы написали парсер погоды. В переменную с названием weather типа string вы сохраняете одно из двух вохможных значений: "будет дождь" или "будет солнечно". Заранее мы не можем знать, что выдаст наш парсер, но мы будем готовы к любому исходу, благодаря условным операторам.
C#:
string weater = "В этом месте будет результат парсинга";
if (weater == "будет дождь") {
project.SendInfoToLog("Будет дождь, поэтому возьмите зонт"); //project.SendInfoToLog - это вывод информации в лог
}
else {
project.SendInfoToLog("Будет солнечно, поэтому возьмите очки");
}
В фигурные скобочки { } почти всегда оборачиваются различные конструкции, чтобы четко определить начало и конец конструкции.
Двойное равно == используется для сравнения (оператор сравнения). Это такойже оператор сравнения, как и операторы больше/меньше > <
Двойной слеш // - именно так можно писать небольшие комментарии к своему коду. Я всегда комментирую свой код, чтобы потом легко вспомнить что делает кусок кода, когда через 2 месяца мне нужно будет что-нибудь поправить в нём.
Аналог на zenno-кубиках
Данный пример можно было написать и по другому, но так делать не корректно
C#:
if(weater == "будет дождь") {
project.SendInfoToLog("Будет дождь, поэтому возьмите зонт");
} //оператор else писать не обязательно
if(weater == "будет солнечно") {
project.SendInfoToLog("Будет солнечно, поэтому возьмите очки");
}
Потому что у нас всего 2 предсказанных исхода, и правильнее использовать просто конструкцию if...else
Другой пример. Представьте, что вам нужно сравнить два числа
C#:
int number1 = 5;
int number2 = 10;
if(number1 > number2) {
project.SendInfoToLog("Число number1 больше");
}
else {
project.SendInfoToLog("Число number2 больше");
}
Давайте попробуем сделать следующее сравнение
C#:
string number1 = "5";
int number2 = 10;
if(number1 > number2) {
project.SendInfoToLog("Число number1 больше");
}
else {
project.SendInfoToLog("Число number2 больше");
}
Реальный пример из практики
В моём боте пользователь может выбрать, формировать текст письма из обычного txt файла, или из html-файла. Заранее я не знаю, что выберет пользователь, поэтому с помощью условного оператора if...else я подготовился к обоим вариантам
Переменная needHtmlFile указывается во сходных настройках, с помощью галочки
Если галочка нажата, то переменная needHtmlFile примет значение "True", иначе она будет "False". Именно поэтому я сравниваю её с "True".
Дословно код делает слудующее
Если(if) пользователь выбрал "Использовать html-файлы для письма", то парсим папку с залитыми html-файлами, выбираем из них случайный и распарсиваем html-файл. Иначе(else) мы берем текст и файла "Текст.txt".
Заметили небольшую паскалку?
Я специально не закрашивал строку 597. В этой строке я объявляю одномерный массив htmlFiles с типов string и сохраняю в этот массив пути ко всем файлам, которые нашлись в директории folderHtmlFilePath. Путь к файлу - это текстовая информация, поэтому у массива тип string
Чтобы пользоваться условными операторами нужно понять, что компилятор (штука, которая проверяет и выполняет ваш код), не понимает такие слова, как "верно" и "неверно", но зато она знает такие понятия как "истина" и "ложь", а точнее true и false. Кстати, поздравляю! Вы только что открыли новый тип данных bool, который может принимать значение true или false.
Блок-схема if...else
Домашнее задание
• Загуглите 2 конструкции if..else_if...else и switch...case (просто загуглить для ознакомления)
• Загуглите какие бывают операторы сравнения в с#
• Создайте имитированный кусочек кода, который бы выводил в лог следующую информацию: "сегодня на улице больше 0 градусов" и "сегодня на улице меньше 0 градусов". Для примера воспользуйтесь моим имитированным примером с зонтом и очками.
• Создайте имитированный кусочек кода, который бы выводил в лог следующую информацию: "пора завтракать", "пора обедать" и "пора ужинать", если вы знаете, что завтракать можно ровно в 8 или 9 или 10 часов утра, обедать можно ровно в 13 или 14 часов дня, ужинать можно ровно в 18 или 19 или 20 часов вечера
• *Загуглите про конвертацию типов данных из string в int
Циклы
Цикл - это конструкция, которая позволяет выполнять нужный кусок кода несколько раз подряд. Прекрасно подходит, чтобы построчно перебрать файл и найти в нём нужную информацию, или перебрать все элементы, которые нашлись на странице с помощью регулярных выражений, или чтобы перебрать массив. Существует несколько конструкций цикла: for, foreach, while, do...while. Для начала нам понадобятся только 1 - это for
C#:
for(int i=0; i < 10; i++) {
System.Threading.Thread.Sleep(1000); //в этой строке делаем паузу в 1000 милисекунд = 1 секунда
}
//С помощью данного кода мы сделали паузу 10 раз по 1 секунде.
1) Начинаем цикл и объявляем переменную с названием i типа int со значением 0
2) Цикл нужно выполнять до тех пор, пока переменная i меньше 10ти
3) В конце кажого шага цикла (итерации) прибавлять к переменной i единицу, i++ - это тоже самое, что i = i + 1;
C#:
//Давайте попробуем сделать вывод в лог чисел от 0 до 10
for (int i=0; i < 10; i++) {
project.SendInfoToLog(i);
}
//Получем ошибку, т.к. функция project.SendInfoToLog может выводить информацию только типа string. Поэтому нужно кое что поправить
for (int i=0; i < 10; i++) {
project.SendInfoToLog(i.ToString());
}
//Функция ToString() преобразует тип int в тип string. Т.е. у нас будут не числа 1, 2, 3, 4... а строчки "1", "2", "3", "4"...
Аналог на zenno-кубиках
Реальный пример из практики
В моём боте каждый аккаунт делает заданное число отправок. Реализовано это с помощью цикла for. Переменная c названием sendAmount с типом int хранит число отправок, которое должен сделать аккаунт. Для примера пусть это будет 20 писем.
int sendAmount = 20;
for (int i = 0; i < sendAmount; i++) {
//тут у меня большой блок кода, который отвечает за отправку одного сообщения
}
На строке под номером 485 начинается цикл for и заканчивается только через пару тысяч строк кода.
Блок-схема цикла for
Домашнее задание
• Напишите кусочек кода, который поочередно выведет в лог имена членов вашей семьи (подсказка: используйте связку массив + цикл, к ячейкам массива можно обращаться по их индексу (порядковому номеру))
• Загуглите следующие конструкции: foreach, while и do...while (просто загуглить для ознакомления)
Полезные возможности в c#
Данный раздел можно считать со звездочкой. Тут я приведу пример полезных конструкций, которые очень часто использую сам.Регулярные выражения
Пример регулярного выражения на c#:
string getRequestResult = project.Variables["getRequestResult"].Value;
string regexResult = Regex.Match(getRequestResult, @"(?<=html).*(?=</div>)").ToString();
Оператор goto
Пример использованию оператору goto:
//тут какая-то строчка кода
//тут какая-то строчка кода
goto nextStep;
//тут какая-то строчка кода
//тут какая-то строчка кода
//тут какая-то строчка кода
//тут какая-то строчка кода
nextStep:
//тут какая-то строчка кода
//тут какая-то строчка кода
//тут какая-то строчка кода
//тут какая-то строчка кода
Метод Contains()
Пример использования метода Contains():
string inboxMessage = project.Variables["inboxMessage"].Value;
if(inboxMessage.Contains("Ваше письмо не доставлено")){
//выполняем кусок кода, который предуспотрен для данного случая
}
Пример из практики
В моём боте есть проверка входящих писем на предупреждение от mail.ru, что письмо не доставлено адресату. В этом предупреждении есть фраза "Ваше письмо не доставлено". Вместо того, чтобы городить регулярные выражения - я воспользоватлся методом Contains()
Дословно код делает следующее
Если(if) в письме содержится словосочетание "Ваше письмо не доставлено", то мы делаем кусок кода, который это предусматривает.
Конструкция lock
Конструкция lock:
lock(SyncObject) {
//тут нужный кусок кода
}
Данная конструкция очень полезна при использовании глобальных переменных и действиях, которые зависят от глобавльных переменных.
Пример из практики
В моём боте можно отправлять письма себе на контрольные почты, чтобы отслеживать рассылку. Делать отправку себе на контрольную почту можно раз в N отправок. Чтобы считать общее число отправок во всех потоках - используется глобальная переменная (переменная, которая работает одновременно во всех потоках). Это будет некий счетчик, доступный всем потокам. Когда поток совершает отправку - он будет прибавлять к этому счетчику +1 (и так в каждом потоке при каждой отправке письма)
К примеру я задал отправлять контрольное письмо себе через каждые 100 отправок. Потоки отправляют письма и вот-вот будет 100-ая отправка.
100-ая отправка, условно, выпадает на 4й поток и он должен сделать отправку себе на контрольную почту. Но в эту же секунду отправку делает, условно, 3й поток и увеличивает счетчик на +1.
Только что у 4го потока была информация, что сделано ровно 100 отправок, но в дело вмешался 3й поток и исправил счетчик на +1 и счетчик получился равен 101. Получается, что 4й поток не сделает отправку на контрольную почту, счетчик ведь уже прошел число 100
Как решать данную проблему? С помощью конструкции lock мы можем сделать так, чтобы потоки не вмешивались в работу друг друга при работе с счетчиком
Конструкция try...catch
Пример конструкции try...catch:
try {
//тут кусок кода, который потенциально может выдать какую-либо ошибку
}
catch (Exception e) {
//тут обработка потенциальной ошибки
}
Заранее вы не всегда знаете, какие это могут ошибки. Вдруг пользователеть вашего бота в графе, где нужно указать число отправок с аккаунта, напишет "привет, как дела?". Вместо .txt файла с базой адресатов он укажет путь к смешной картинке с котиками. Или хостинг с прокси, который использует пользователь для отправки писем - внезапно упадет из-за ddos атаки и прокси перестанут работать.
Такие сценарии невозможно предсказать и поэтому необходимо использовать конструкцию try...catch
Завершение
Если что-то недопоняли, то велком в комментарии задавать вопросы и скидывать свои ДЗ. Не обещаю, что у всех, но я постараюсь отвечать на вопросы и проверять ваши ДЗ (скорее всего через пару недель я уже не смогу отвечать на вопросы и проверять ДЗ, поэтому поторопитесь).
Бота, которого я приводил как пример вы можете посмотреть вот тут. Топик с ботом я создавал будучи неопытным кодером, но всё получилось нормально - главное не боятся начать.
Если вы хорошо усвоите материал из данной статьи, то в будущем вы просто будете накладывать на этот фундамент новые знания, тем самым - улучшая скил в кодинге и решая всё более трудные задачи.
С наилучшими пожеланиями, Ваш Brabus
Telegram: https://t.me/brabus_bots_channel
- Тема статьи
- Другое
- Номер конкурса статей
- Семнадцатый конкурс статей
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.