Мануал по написанию программ


Загрузить PDF


Загрузить PDF

Итак, у вас появилась идея для отличной программы, однако вы и понятия не имеете, как ее реализовать? Не беда, поможем. Правда, придется потратить немало времени на то, чтобы выучить язык программирования, но это нормально. Скажем даже более, многие успешные программисты — самоучки. Выучив основы, вы сможете создавать простые программы, тратя на это минимум времени. Создание более сложных программ, конечно, является более серьезной задачей, но, как говорится, терпение и труд все перетрут!

  1. Изображение с названием Apply for an Entrepreneurial Grant Step 2

    1

    Определитесь с тем, какой язык программирования вы выучите первым. Если раньше вы не программировали, то начинать надо с чего-то простого, рассчитанного на новичков — тем не менее позволяющего добиться поставленных целей. Есть десятки языков программирования, у каждого из них свои области применения, свои задачи и особенности. Вот несколько из них:[1]

    • C — один из самых старых языков программирования. Знакомство с С позволит упростить изучение C++ и Java.
    • C++ — один из самых популярных языков программирования в наши дни, особенно в плане разработки программного обеспечения. Правда, на то, чтобы выучить С++, уйдет время, а на то, чтобы еще и научиться им пользоваться, уйдет еще больше… Но это окупит себя!
    • Java — еще один очень популярный язык программирования, который может работать почти что в любой операционной системе.
    • Python — один из простейших языков программирования, чьи основы можно выучить за пару дней. Тем не менее это весьма мощный язык, задействованный для создания множества серверных и веб-приложений.
  2. Изображение с названием Program Software Step 2

    2

    Подготовьте среду разработки. Чтобы начать программировать, вам нужно не так уж и много — и это «среда разработки». Впрочем, что именно под этим понимается, зависит от выбранного языка программирования.

    • Редактор кода — почти что любому программисту будет удобнее работать в специальном текстовом редакторе — редакторе кода. Можно, конечно, и в «Блокноте» работать, но без подсветки синтаксиса и подстановок это будет весьма печальный опыт. Среди популярных редакторов кода можно назвать Notepad++, TextMate и JEdit.
    • Компилятор — при работе со многими языками программирования (С, Java и так далее) код программы сначала надо «собрать» — скомпилировать, только потом его можно будет запустить. Соответственно, придется установить компилятор, если в выбранном вами языке программирования без него не обойтись. К слову, большинство компиляторов поможет вам отлавливать «баги» — ошибки программы.
    • IDE (Integrated Development Environment, интегрированная среда разработки) — в некоторых языка программирования и редактор кода, и компилятор, и модуль отладки — все объединено в одну-единственную интегрированную среду разработки. Скачать IDE можно, как правило, с сайта языка программирования.
  3. Изображение с названием Program Software Step 3

    3

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

    • Заинтересовались? Зайдите на Udemy, Khan Academy, Codecademy, Code.org и другие аналогичные ресурсы.[2]
  4. Изображение с названием Program Software Step 4

    4

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

  5. Изображение с названием Program Software Step 5

    5

    Чтобы выучить основы, создавайте простые программы. Раз уж вы начали писать код сами, то начните с азов. Напишите несколько программ, скажем, на вывод строки или подсчет простенького уравнения. Отрабатывайте все это — пригодится позже, во время работы над более сложными программами. Экспериментируйте, старайтесь сломать даже собственные программы.

  6. Изображение с названием Program Software Step 6

    6

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

  7. Изображение с названием Get Rich Step 16

    7

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

    Реклама

  1. Изображение с названием Apply for an Entrepreneurial Grant Step 8

    1

    Подготовьте «дизайн-документ». Дизайн-документ — это детальное описание разрабатываемой программы, и именно его необходимо сделать первым делом, чтобы потом, уже по ходу работы, вы могли сверяться с ним и заложенными в нем целями. Именно дизайн-документ позволит вам сделать то, что вы хотели, а не что-либо иное.

    • Все, что вы хотите реализовать в программе, должно быть перечислено на страницах дизайн-документа.
    • Кроме того, дизайн-документ должен учитывать и пользователя, точнее то, как он будет работать с программой.
  2. Изображение с названием Do Research Step 5

    2

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

  3. Изображение с названием Defend Against Appropriation of Name or Likeness Claims Step 15

    3

    Определитесь с архитектурой программы. Цели будут определять средство… то есть архитектуру. Если знать и понимать, каким задачам какая архитектура соответствует, то процесс разработки пойдет куда эффективнее.[4]

  4. Изображение с названием Program Software Step 11

    4

    Начните с программы по схеме «1-2-3». Это простейший тип программ, их задача — позволить вам адаптироваться к языку программирования. Если в общем, то программы «1-2-3» запускают, спрашивают у пользователя какие-нибудь данные, затем выводят результат, на чем и заканчиваются.

    • Следующим шагом в схеме «1-2-3» будет так называемый REPL (Read-Execute-Print Loop). Проще говоря, это возврат к первому шагу программы после вывода результата вычислений.
    • Подумайте о программах типа Pipeline. Они характеризуются тем, что трансформируют вводимые пользователем данные и работают последовательно. Данный тип подходит для программ, которые требуют минимум взаимодействия с пользователем — скажем, RSS-ридеры. Такая программа будет представлять собой несколько классов с общим циклом.

    Реклама

  1. Изображение с названием Apply for a Marriage Certificate in Dwarka Step 10

    1

    Сделайте акцент на какой-то одной функции программы. Точнее сказать, прототип — это всегда основная функция программы. Допустим, вы создаете программу-органайзер — тогда основной функцией будет календарь и возможность добавлять события.

  2. Изображение с названием Accept Mistakes and Learn from Them Step 18

    2

    Добейтесь того, чтобы прототип работал без сбоев. Прототип должен быть таким, чтобы им можно было пользоваться вместо разрабатываемой программы. Прототип станет основой, фундаментом всему, так что работать он должен соответственно. Иными словами, каждая функция прототипа должна работать безукоризненно.

    • В прототип можно вносить срочные изменения и тестировать их.
    • Разумеется, задача тестирования прототипа требует участия сразу многих людей.
    • Прототип может и будет меняться, это факт.
  3. Изображение с названием Write a Book Report Step 6

    3

    Не бойтесь перерабатывать прототип снова и снова. В этом его суть — сначала эксперименты, потом релиз. Именно на примере прототипа вы сможете увидеть, все ли работает так, как надо. Если же прототип оказывается неудачным — не беда, просто перепишите его с нуля, начните все заново. Лучше так, поверьте.

    Реклама

  1. Изображение с названием Program Software Step 15

    1

    Создайте базу псевдокода. Это станет своего рода скелетом вашего проекта и основой для будущей работы. Псевдокод отличается от обычного кода тем, что… не «компилится» (не обрабатывается в компиляторе), зато прекрасно читается программистами и помогает понять, что должно происходить на том или ином шаге работы программы.

    • Псевдокод, впрочем, использует тот же синтаксис, что и обычный код, поэтому писать псевдокод надо так же, как и программу.
  2. Изображение с названием Become a Software Engineer Step 2

    2

    Усовершенствуйте прототип. Можете взять сам прототип, можете взять псевдокод — в любом случае суть в том, чтобы сделать прототип лучше, совершеннее, быстрее!

  3. Изображение с названием Program Software Step 17

    3

    Начните работу над кодом программы. Вот, собственно, мы и добрались до сути. Именно работа над кодом программы и займет бо́льшую часть времени, не говоря уже про бесчисленные компиляции, не менее бесчисленные тесты и поиски багов… Если над вашей программой работает целая команда, то стоит начать с псевдокода, чтобы все шло равномерно.

  4. Изображение с названием Program Software Step 18

    4

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

    Реклама

  1. Изображение с названием Become a Software Engineer Step 4

    1

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

    • Этот этап работы над программой часто называют «альфа-тестированием».
  2. Изображение с названием Become a Software Engineer Step 5

    2

    Протестируйте финальную версию программы. Итак, все функции, какие только должно были быть в программе, в нее добавлены. Что теперь? Теперь снова тесты. Долгие, придирчивые, тщательные тесты — и работа над ошибками, разумеется. Сейчас вашу программу должно тестировать даже большее количество человек, чем ранее.

    • Часто данный процесс называют бета-тестированием.
  3. Изображение с названием Be an Effective Supervisor Step 4

    3

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

    Реклама

  1. Изображение с названием Apply for an Entrepreneurial Grant Step 1

    1

    Подумайте, что вам нужно. Это будет зависеть от программы, так что подумайте, нужны ли вам, скажем, аудиозаписи? Графика? Контент? Задумайтесь об этом до релиза.

  2. Изображение с названием Succeed in Network Marketing Step 2

    2

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

  3. Изображение с названием Prepare for a Job Interview Step 10

    3

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

    Реклама

  1. Изображение с названием Program Software Step 25

    1

    Подумайте, не стоит ли выпустить вашу программу под лицензией открытого кода. Тогда и другие люди смогут получить доступ к исходному коду программы, вносить в него изменения и улучшения. Правда, по такой лицензии вы вряд ли получите доход от программы — вы же не сможете ее продавать, код-то открытый. В чем же резон? В помощи сообщества, которое, если заинтересуется вашей программой, может превратить ее в истинный шедевр.

  2. Изображение с названием Market a Product Step 1

    2

    Подготовьтесь к продажам вашей программы. Для этого вам нужен интернет-магазин типа «витрина», чтобы покупатели могли, заплатив, скачать программу и начать ею пользоваться. Учтите, впрочем, что программы, за которые платят деньги, должны работать идеально!

    • В зависимости от того, что у вас за программа, вы можете продавать еще множество услуг.
  3. Изображение с названием Write a Grant Proposal Step 16

    3

    Продолжайте поддерживать выпущенную программу обновлениями. Скорее всего, после релиза вы увидите поток сообщений о всевозможных ошибках и багах. Это нормально. Вам нужно ранжировать эти сообщения по степени важности и начать решать соответствующие проблемы, а затем выпускать обновления для программы — так называемые «патчи».

    • Хотите не растерять покупателей и стяжать себе добрую славу? Выпускайте патчи почаще.
  4. Изображение с названием Enjoy Being Alone Step 14

    4

    Займитесь рекламой вашей программы. Если о ней никто не будет знать, то никто ей и пользоваться не будет. Отправляйте сообщения на тематические сайты, раздавайте бесплатную пробную версию, напишите пресс-релиз, делайте все необходимое, чтобы о вашей программе узнали!

    Реклама

Об этой статье

Эту страницу просматривали 125 420 раз.

Была ли эта статья полезной?

Первый опыт написания полноценной программы

Время на прочтение
17 мин

Количество просмотров 16K

Каждый начинающий программист мечтает реализовать свой собственный проект. Не написать простенький код, по заданию преподавателя, а воплотить в жизнь свои идеи. Так и я, изучая C++ 3-4 месяца, решился попробовать разработать макет электронного журнала для преподавателей.

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

По итогу, пришел к выводу, что в программе потребуется реализовать:

  1. Регистрацию (Reg),

  2. Авторизацию (Authon),

  3. Выбор группы (GroupSelection),

  4. Возможность выставлять оценки (Grades),

  5. Возможность выставлять посещаемость (Attendance),

  6. Возможность писать комментарии к датам (Comment),

  7. Возможность устанавливать dedlin’ы (Deadline).

Для понимания логики работы программы, отражения принципов взаимодействия с ней, упрощения дальнейшего написания кода, была создана полная блок-схема.

блок-схема программы

блок-схема программы

Аналогично, были созданы блок схемы для каждой функции.

авторизация

авторизация
регистрация
регистрация
выбор группы
выбор группы
выставление оценок
выставление оценок
простановка посещаемости
простановка посещаемости
написание комментариев к датам
написание комментариев к датам
установка dedlin’ов
установка dedlin’ов

Написание кода программы

Первым шагом написания программы является добавления необходимых заголовочных файлов, а именно:

  1. iostream — заголовочный файл с классами, функциями и переменными для организации ввода-вывода.

  2. string —  это заголовочный файл для взаимодействия с
    классами string (строками).

  3. fstream — заголовочный файл, включающий набор классов, методов и функций, которые предоставляют интерфейс для чтения/записи данных из/в файл.

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

std::string nameofgroup;

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

Класс данных о преподавателе – DataofTeature.

class DataofTeature
{
public:
	std::string name; //имя преподавателя
	std::string surname; //фамилия преподавателя
	std::string patronymic; //отчество преподавателя
	std::string login; //логин преподавателя
	std::string password; //пароль преподавателя
};

Класс данных о студенте – DataofStudent.

class DataofStudent
{
public:
	std::string group; //название группы студента
	std::string name; //имя студента
	std::string surname; //фамилия студента
};

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

Reg

Функция Reg реализует полноценную регистрацию, с записью данных о пользователе в текстовый файл.

В ходе выполнения функции, пользователю предлагается ввести ФИО, логин и пароль. После получения программой логина, проверяется его наличие в системе, если логин совпадает с ранее записанным в базу логинов, то пользователя предлагается ввести логин повторно. Как только программа получает ФИО, пароль и уникальный логин, происходит запись логина в базу для логинов (при открытие базы данных используется режим открытия ios_base::app, позволяющий открыть файл для записи в конец файла, при этом, сохраняя ранее записанные данные), создание специализированного файла для регистрационных данных пользователя, и запись в него ФИО, аналогично создается специальный файл для хранения логина и пароля конкретного пользователя. Формирования уникальных файлов происходит по принципу сложения строк. Например, path=path+teature1.login+txt, где path-путь к директории, в которой хранятся файлы программы, teature1.login – уникальный логин пользователя, txt- строка, хранящая в себе “.txt”.

void Reg()
{
	std::string path = "C:\\journal\\regdata", datalog = "C:\\journal\\logdata.txt", txt = ".txt", user = "C:\\journal\\", delfile = "C:\\journal\\delfile.txt"; //объявление переменных типа string
	bool flag = 1; //объявление переменной типа bool
	DataofTeature teature1; //объявление переменной класса DataofTeature
	std::ofstream fout; //объявление переменной класса ofstream
	std::ifstream fin; //объявление переменной класса ifstream
	std::cout << "\t\t\tРегистрация:\n"; //ввод даных, необходимых для регистрации
	std::cout << "Введите фамилию: ";
	std::cin >> teature1.surname;
	std::cout << "Введите имя: ";
	std::cin >> teature1.name;
	std::cout << "Введите отчество: ";
	std::cin >> teature1.patronymic;
	std::cout << "Введите логин: ";
	std::cin >> teature1.login;
	while (flag)
	{
		bool flag2 = 0;
		fin.open(datalog);
		if (fin.is_open())
		{
			std::string data = "";
			while (!fin.eof())
			{
				std::getline(fin, data);
				if (teature1.login == data)		//проверка на существование данного логина в файле
				{
					flag2 = 1;
					flag = 1;
				}
			}
		}
		else
		{
			std::cout << "ERROR"; //Файл не удалось создать или открыть
		}
		if (flag2)
		{
			std::cout << "Данный логин уже существует, придумайте другой логин: "; //прозьба ввести логин повторно, если введенный до этого уже существует
			std::cin >> teature1.login;
			flag = 1;
		}
		else
		{
			flag = 0; //изменение булевой переменной для выхода из цыкла
		}
		fin.close();
	}
	path = path + teature1.login + txt; //формирование пути, для создания файла с ФИО аккаунта
	fout.open(path);
	if (fout.is_open())
	{
		fout << teature1.surname << "\n";
		fout << teature1.name << "\n";			//запись данных в файл
		fout << teature1.patronymic << "\n";
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fout.close();
	std::cout << "Введите пароль: ";
	std::cin >> teature1.password;		//ввод пароля
	fout.open(datalog, std::ios_base::app); //открыть файл для записи в конец файла
	if (fout.is_open())
	{
		fout << teature1.login << "\n"; //запись данных в файл
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fout.close();
	user = user + teature1.login + txt; //формирование пути хранения логина и пароля
	fout.open(user); //открытия файла
	if (fout.is_open())
	{
		fout << teature1.login << "\n";
		fout << teature1.password << "\n";		//запись данных в файл
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fout.close();
}

Authon

Функция Authon реализует авторизацию пользователя в программу.

В ходе выполнения функции, пользователю предлагается ввести логин и пароль. Следом идет проверка наличия логина в базе логинов, если логина в базе нет, пользователю
предлагается ввести логин повторно. Получив логин, программа открывает
специализированный файл пользователя, получая к нему путь, методом сложения
строк. В этом файле проверяется верность пароля, если пароль не совпадает, то
предлагается ввести пароль повторно. Как только все данные проверены, программа
открывает файл с ФИО пользователя и выводит на экран приветствие, используя ФИО
пользователя.

void Authon()
{
	std::string path = "C:\\journal\\regdata", datalog = "C:\\journal\\logdata.txt", txt = ".txt", user = "C:\\journal\\", delfile = "C:\\journal\\delfile.txt", login, password, filelog = ""; //объявление переменных типа string
	DataofTeature teature1; //объявление переменной класса DataofTeature
	std::ifstream fin; //объявление переменной класса ifstream
	bool flag = 1; //объявление переменной типа bool
	std::cout << "\t\t\tАвторизация:\n";
	std::cout << "Введите логин: ";
	std::cin >> login;			//ввод логина
	while (flag)
	{
		bool flag2 = 0;
		fin.open(datalog);		//проверка наличия логина в базе логинов
		if (fin.is_open())
		{
			while (!fin.eof())
			{
				std::getline(fin, filelog);
				if (login == filelog)
				{
					flag = 0;
					flag2 = 0;
					break;
				}
				else
				{
					flag2 = 1;
				}
			}
		}
		else
		{
			std::cout << "ERROR"; //Файл не удалось создать или открыть
		}
		if (flag2)
		{
			std::cout << "Такого логина не существует, введите логин повторно: \n";			//просьба ввести логин повторно
			std::cin >> login;
		}
		fin.close();
	}
	user = user + login + txt; //формирования пути нахождения файла с логинами и паролями
	flag = 1;
	std::cout << "Введите пароль: ";		//ввод пароля
	std::cin >> password;
	while (flag)
	{
		bool flag2 = 0;
		fin.open(user);
		if (fin.is_open())
		{
			while (!fin.eof())
			{
				std::getline(fin, filelog);
				if (password == filelog)
				{								//проверка верности пароля
					flag = 0;
					flag2 = 0;
					break;
				}
				else
				{
					flag2 = 1;
				}
			}
		}
		else
		{
			std::cout << "ERROR"; //Файл не удалось создать или открыть//
		}
		if (flag2)
		{
			std::cout << "Пароль введен не верно, попробуйте еще раз: \n";		//просьба ввести пароль повторно
			std::cin >> password;
		}
		fin.close();
	}
	std::cout << "Добро пожаловать ";
	path = path + login + txt;
	fin.open(path);
	if (fin.is_open())
	{
		std::string data = "";					//вывод приветствия на экран
		while (!fin.eof())
		{
			std::getline(fin, data);
			std::cout << data << " ";
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fin.close();
	std::cout << "\n";
}

GroupSelection

Функция реализует полноценный выбор группы в программе.

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

void GroupSelection()
{
	DataofStudent stud1; //объявление переменных класса DataofStudent
	std::string allgroup = "", path = "C:\\journal\\allgroup\\allgroup.txt", delfile = "C:\\journal\\allgroup\\delfile.txt", path2 = "C:\\journal\\allgroup\\", txt = ".txt", choice = ""; //объявление переменных типа string
	bool flag = 1; //объявление переменных типа bool
	std::ifstream fin; //объявление переменной класса ifstream
	std::ofstream fout; //объявление переменной класса ofstream
	std::cout << "Полный список групп: \n";
	fin.open(path);
	if (fin.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data);		//вывод а экран полного списка групп
			std::cout << "\t\t\t" << data << "\n";
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть//
	}
	fin.close();
	std::cout << "Введите название группы, которую хотите открыть: ";
	std::cin >> stud1.group;	//ввод название необходимой группы
	while (flag)
	{
		bool flag2 = 1;
		fin.open(path);
		if (fin.is_open())
		{
			std::string data = "";
			while (!fin.eof())
			{
				std::getline(fin, data);
				if (stud1.group == data)	//проверка на наличие введенной группы в списке групп
				{
					flag2 = 0;
					flag = 0;
				}
			}
		}
		else
		{
			std::cout << "ERROR"; //Файл не удалось создать или открыть
		}
		if (flag2)
		{
			std::cout << "Данной группы не существует, введите другую группу: ";
			std::cin >> stud1.group;	//просьба ввести название группы повторно
			flag = 1;
		}
		else
		{
			flag = 0;	//изменение буливой переменной для выхода из цыкла
		}
		fin.close();
	}
	nameofgroup = stud1.group; //присваивание названия группы в глобальную переменную
}

Grades

Функция Grades реализует, простановку оценок студентам.

В ходе выполнения функции, пользователю предлагается ввести дату, за которую он хочет выставить оценку. После получения программой даты, происходит проверка на существование файла с оценками на данную дату. Если файл существует, то происходит его запись в специализированный промежуточный файл, это происходит для реализации корректной и органичной записи в файл отметок, без потерь данных. Если файл не существует, то программа копирует данные из файла со списком группы в промежуточный файл. Следом, на экран выводится полный список группы с отметками (если они есть). Пользователю предлагается ввести фамилию и имя студента, которому он хочет выставить оценку. Как только программа получает эти данные, происходит проверка на наличие данного студента в группе, если его нет, то пользователю предлагается ввести фамилию и имя повторно. После получения данных программой, происходит создание файла для оценок на данную дату (принцип нахождения пути файла и формирования его название – сложение строк). Следом, идет поиск данного студента в промежуточном файле. Принцип поиска и записи таков: если фамилия и имя не совпадает с введенными пользователем, то происходит запись этих данных в файл с оценками, если ФИ совпали, то пользователю предлагается ввести студенту оценку, полученная строчка записывается в файл с оценками. В конце работы функции, на экран выводится список группы с внесенными изменениями.

void Grades()
{
	DataofStudent student1; //объявление переменных класса DataofStudent
	std::string way = "C:\\journal\\allgroup\\", delfile = "delfile.txt", txt = ".txt", attendance = "\\grade", choice = ""; //объявление переменных типа string
	bool flag = 0, flag2 = 1; //объявление переменных типа bool
	std::ofstream fout; //объявление переменной класса ofstream
	std::ifstream fin; //объявление переменной класса ifstream
	std::cout << "Введите дату за которую вы хотите проставить оценки: ";
	std::cin >> choice;	//ввод даты 
	fin.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open())
	{
		flag = 1;		//проверка наличия файла с оценками на данную дату
	}
	fin.close();
	if (flag)
	{
		fin.open(way + nameofgroup + attendance + choice + txt);
		fout.open(way + delfile);
		if (fin.is_open() and fout.is_open())
		{
			std::string data = "";
			while (!fin.eof())		//запись данных существующего файла в специализированный файл
			{
				std::getline(fin, data);
				fout << data << "\n";
			}
		}
		else
		{
			std::cout << "ERROR"; //Файл не удалось создать или открыть
		}
		fin.close();
		fout.close();
	}
	else
	{
		fin.open(way + nameofgroup + txt);
		fout.open(way + delfile);
		if (fin.is_open() and fout.is_open())
		{
			std::string data = "";
			while (!fin.eof())
			{									//запись  в специализированный файл списка группы 
				std::getline(fin, data);
				fout << data << "\n";
			}
		}
		else
		{
			std::cout << "ERROR"; //Файл не удалось создать или открыть
		}
		fin.close();
		fout.close();
	}
	fin.open(way + delfile);
	if (fin.is_open())
	{
		std::string data = "";
		while (!fin.eof())	//вывод списка группы на экран
		{
			std::getline(fin, data);
			std::cout << data << "\n";
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fin.close();
	std::cout << "Введите фамилию и имя студента. которому вы хотите выставить оценку: " << std::endl;
	std::cin >> student1.name;	//ввод фамили и имени студента
	while (flag2)
	{
		fin.open(way + delfile);
		if (fin.is_open())
		{
			std::string data = "";
			while (!fin.eof())
			{
				std::getline(fin, data);
				if (data == student1.name)
				{
					flag2 = 0;	//проверка наличия данно ФИ в списке группы
				}
			}
		}
		else
		{
			std::cout << "ERROR"; //Файл не удалось создать или открыть
		}
		if (flag2)
		{
			std::cout << "Такого студента не существует, повторите ввод фамилии и имени: "; //повторный ввод ФИ студента
			std::cin >> student1.name;
		}
		fin.close();
	}
	fin.open(way + delfile);
	fout.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open() and fout.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data);
			if (data == student1.name)
			{
				bool flag3 = 1;
				for (int i = 0; i < data.length(); i++)
				{											//процесс нахождения ФИ студента в файле
					if (flag3 and data[i] != '\t')
					{
						fout << data[i];	//запись данных в файл с оценками
					}
					else
					{
						flag3 = 0;
					}

				}
				std::string choice2;
				std::cout << "Введите оценку: ";	//ввод оценки
				std::cin >> choice2;
				fout << "\t" << choice2 << "\n";	//запись данных в файл с оценками
			}
			else
			{
				fout << data << "\n";	//запись данных в файл с оценками
			}
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fin.close();
	fout.close();
	std::cout << "\n";
	fin.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data);
			std::cout << "\t\t\t" << data << "\n";	//вывод измененных данных на экран
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fin.close();
}

Attendance

Функция Attendance реализует простановку посещаемости студентов с последующей записью в файл.

В ходе выполнения функции, пользователю предлагается ввести дату, за которую он хочет выставить посещаемость. После получения программой даты, происходит проверка на существование файла с посещаемостью на данную дату. Если файл существует, то происходит его запись в специализированный промежуточный файл, это происходит для реализации корректной и органичной записи в файл посещаемости, без потерь данных. Если файл не существует, то программа копирует данные из файла со списком группы в промежуточный файл. Следом, на экран выводится полный список группы с посещаемостью (если она есть). Пользователю предлагается ввести фамилию и имя студента, которому он хочет выставить посещаемость. Как только программа получает эти данные, происходит проверка на наличие данного студента в группе, если его нет, то пользователю предлагается ввести фамилию и имя повторно. После получения данных программой, происходит создание файла для посещаемости на данную дату (принцип нахождения пути файла и формирования его название – сложение строк). Следом, идет поиск данного студента в промежуточном файле. Принцип поиска и записи таков: если фамилия и имя не совпадает с введенными пользователем, то происходит запись этих данных в файл с оценками, если ФИ совпали, то пользователю предлагается ввести посещаемость студента, полученная строчка записывается в файл с посещаемостью. В конце работы функции, на экран выводится список группы с внесенными изменениями.

void Attendance()
{
	DataofStudent student1; //объявление переменной класса DataofStudent
	std::string way = "C:\\journal\\allgroup\\", delfile = "delfile.txt", txt = ".txt", attendance = "\\attendance", choice = "";//объявление переменных типа string
	bool flag = 0, flag2 = 1; //объявление переменной типа bool
	std::ofstream fout; //объявление пременной класса ofstream
	std::ifstream fin; //объявление переменной класса ifstream
	std::cout << "Введите дату за которую вы хотите проставить посещаемость: ";
	std::cin >> choice; //ввод даты
	fin.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open())
	{
		flag = 1;	//проверка на наличие файла
	}
	fin.close();
	if (flag)
	{
		fin.open(way + nameofgroup + attendance + choice + txt);
		fout.open(way + delfile);
		if (fin.is_open() and fout.is_open())
		{
			std::string data = "";
			while (!fin.eof())	//запись данных файла в промежуточный файл
			{
				std::getline(fin, data);
				fout << data << "\n";
			}
		}
		else
		{
			std::cout << "EROR";
		}
		fin.close();
		fout.close();
	}
	else
	{
		fin.open(way + nameofgroup + txt);
		fout.open(way + delfile);
		if (fin.is_open() and fout.is_open())
		{
			std::string data = "";
			while (!fin.eof())
			{						//запись списка группы в промежуточный файл
				std::getline(fin, data);
				fout << data << "\n";
			}
		}
		else
		{
			std::cout << "EROR";
		}
		fin.close();
		fout.close();
	}
	fin.open(way + delfile);
	if (fin.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data);
			std::cout << data << "\n";	//ввывод списка группы на экран
		}
	}
	else
	{
		std::cout << "EROR";
	}
	fin.close();
	std::cout << "Введите фамилию и имя студента. которому вы хотите выставить посещаемость: " << std::endl;
	std::cin >> student1.name;	//ввод фамили и имени студента
	while (flag2)
	{
		fin.open(way + delfile);
		if (fin.is_open())
		{
			std::string data = "";
			while (!fin.eof())
			{
				std::getline(fin, data);
				if (data == student1.name)	//проверка на наличие данного студента в группе
				{
					flag2 = 0;
				}
			}
		}
		else
		{
			std::cout << "EROR";
		}
		if (flag2)
		{
			std::cout << "Такого студента не существует, повторите ввод фамилии и имени: ";	//повторный ввод ФИ студента
			std::cin >> student1.name;
		}
		fin.close();
	}
	fin.open(way + delfile);
	fout.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open() and fout.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data);
			if (data == student1.name)
			{
				bool flag3 = 1;
				for (int i = 0; i < data.length(); i++)
				{
					if (flag3 and data[i] != '\t')
					{
						fout << data[i];	//процесс нахождения студента в файле
					}
					else
					{
						flag3 = 0;
					}

				}
				std::string choice2;
				std::cout << "Введите посещаемость: ";
				std::cin >> choice2; //ввод посещаемости
				fout << "\t" << choice2 << "\n";
			}
			else
			{
				fout << data << "\n";
			}
		}
	}
	else
	{
		std::cout << "EROR";
	}
	fin.close();
	fout.close();
	std::cout << "\n";
	fin.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data); //вывод измененных данных на экран
			std::cout << "\t\t\t" << data << "\n";
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fin.close();
}

Comment

Функция Comment реализует в программе написание комментария к дате.

В ходе выполнения функции, пользователю предлагается ввести дату, для которой он хочет написать комментарий. При получении программой даты, происходит открытие файла с режимом открытия ios_base::app (открыть файл для записи в конец файла). Наименование файла и путь его нахождения формируется, путем сложения строк. Пользователю предлагается ввести комментарий. Происходит запись данных в файл. После на экран выводятся изменённые данные файла.

void Comment()
{
	DataofStudent student1;//объявление переменной класса DataofStudent
	std::string way = "C:\\journal\\allgroup\\", delfile = "delfile.txt", txt = ".txt", attendance = "\\comment", choice = ""; //объявление переменнх типа string
	std::ofstream fout;//объявление переменной класса ofstream
	std::ifstream fin;//объявление переменной класса ifstream
	std::cout << "Введите дату для которой вы хотите оставить коментарий: ";
	std::cin >> choice; //ввод даты
	fout.open(way + nameofgroup + attendance + choice + txt, std::ios_base::app);
	if (fout.is_open())
	{
		std::string choice2;
		std::cout << "Введите коментарий: "; //ввод коментария
		std::cin >> choice2;
		fout << choice2 << "\n";
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	std::cout << "\n";
	fout.close();
	fin.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data);	//вывод изменненных данных на экран
			std::cout << "\t\t\t" << data << "\n";
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fin.close();

}

Deadline

Функция Deadline реализует в программе создание dedlin’а и комментария к нему, с записью этих данных в файл.

В ходе выполнения функции, пользователю предлагается ввести дату, на которую он хочет установить deadline. При получении программой даты, происходит открытие файла с режимом открытия ios_base::app (открыть файл для записи в конец файла). Наименование файла и путь его нахождения формируется, путем сложения строк. Пользователю предлагается ввести комментарий. Происходит запись данных в файл. После на экран выводятся изменённые данные файла.

void Deadline()
{
	DataofStudent student1; //объявление переменной класса DataofStudent
	std::string way = "C:\\journal\\allgroup\\", delfile = "delfile.txt", txt = ".txt", attendance = "\\deadline", choice = ""; //объявление переменной типа string
	std::ofstream fout; //объявление переменной класса ofstream
	std::ifstream fin; //объявление переменной класса ifstream
	std::cout << "Введите дату на которую вы хотите установить deadline: ";
	std::cin >> choice; //ввод даты
	fout.open(way + nameofgroup + attendance + choice + txt, std::ios_base::app);
	if (fout.is_open())
	{
		std::string choice2;
		std::cout << "Введите коментарий к deadlin'у: "; //ввод коментария 
		std::cin >> choice2;
		fout << choice2 << "\n";
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	std::cout << "\n";
	fout.close();
	fin.open(way + nameofgroup + attendance + choice + txt);
	if (fin.is_open())
	{
		std::string data = "";
		while (!fin.eof())
		{
			std::getline(fin, data);
			std::cout << "\t\t\t" << data << "\n"; //вывод измененных данных на экран
		}
	}
	else
	{
		std::cout << "ERROR"; //Файл не удалось создать или открыть
	}
	fin.close();
}

Main

Аналогично, основываясь на блок схеме, был написан код основной части программы.

В ходе выполнения программы, на экран выводится меню. Пользователю предлагается выбрать один из пунктов. При выборе пункта 1, вызывается функция Reg, а затем функция Authon; При выборе пункта 2, вызывается функция Authon; При выборе пункта 3 происходит выход из программы. После успешной авторизации вызывается функция GroupSelection. После выбора группы на экран выводится меню дальнейших действий. Пользователю предлагается выбрать один из пунктов. При выборе пункта 1 вызывается функция Grades; При выборе пункта 2 вызывается функция Attendance; При выборе пункта 3 вызывается функция Deadline; При выборе пункта 4 вызывается функция Comment; При выборе пункта 5 происходит выход из программы.

void main()
{
	std::string choice = ""; //объявление переменной типа string
	bool flag = 1; //объявление переменной типа bool
	setlocale(0, ""); //установка языкового стандарта для яязыка
	std::cout << "\t\t\tДобро пожаловать в электронный журнал\n"; //вывод меню на экран
	std::cout << "\t\t\tЕсли вы ходите зарегистрироваться введите 1\n\t\t\tЕсли выхотите авторизоваться введите 2\n\t\t\tЕсли вы хотите закрыть программу введите 3\n";
	std::cin >> choice;//ввод символа, отвечающего за выбор пункта меню
	if (choice == "3")
	{
		return; //выход из программы
	}
	while (flag)
	{
		if (choice == "1")
		{
			flag = 0;
			Reg(); //регистрация
			Authon();//авторизация
		}
		else
		{
			if (choice == "2" and flag)
			{
				Authon(); //авторизация
				flag = 0;
			}
			else
			{
				std::cout << "Сделайте выбор повторно: ";
				std::cin >> choice; //повторное осуществленеи выбора пункта меню
			}
		}
	}
	GroupSelection(); //выбор группы
	std::cout << "\n\t\t\tВыберете дальнейшее действие:\n"; //вывод меню выбора дальнейших действий
	std::cout << "\t\t\tЕсли вы хотите поставить оценку студенту, введите 1\n\t\t\tЕсли проставить посещаемость, введите 2\n\t\t\tЕсли вы хотите установить дату конца дедлайна, введите 3\n\t\t\tЕсли вы хотите написать коментарий, введите 4\n\t\t\tЕсли вы хотите закрыть программу введите 5\n";
	std::cin >> choice; // ввод символа, отвечающего за выбор пункта меню
	flag = 1;
	while (flag)
	{
		if (choice == "1")
		{
			flag = 0;
			Grades(); //простанока оценки
		}
		if (choice == "2")
		{
			flag = 0;
			Attendance(); //простановка посещаемости
		}
		if (choice == "3")
		{
			flag = 0;
			Deadline(); //установка deadlin'a
		}
		if (choice == "4")
		{
			flag = 0;
			Comment(); //написание комментария
		}
		if (choice == "5")
		{
			return; //выход из программы
		}
		if (choice != "1" and choice != "2" and choice != "3" and choice != "4" and choice != "5")
		{
			flag = 1;
			std::cout << "Повторите ввод: ";
			std::cin >> choice; //повторное осуществление выбора пункта меню
		}
	}
}

Для реализации полноценной работоспособности моей программы необходимо создать несколько текстовых файлов и директорий согласно диаграмме.

диаграмма

диаграмма

В файл allgroup.txt необходимо записать название группы. Также папке allgroup нужно создать папку с название группы и текстовый документ с названием группы, в который необходимо занести список группы.

Тестирование и отладка программы

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

Тестирование работы регистрации

Тестирование работы регистрации
Тестирование авторизации
Тестирование авторизации
Тестирование выбора группы
Тестирование выбора группы
Тестирование постановки оценки
Тестирование постановки оценки
Тестирование постановки посещаемости
Тестирование постановки посещаемости
Тестирование установки даты конца дедлайна
Тестирование установки даты конца дедлайна
Тестирование написания комментария к дате
Тестирование написания комментария к дате

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

Заключение

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

  • Класс DataofTeature, хранящий в себе информацию о преподавателе.

  • Класс DataofStudent, хранящий в себе информацию о студенте.

  • Функция Reg, реализующая регистраци.

  • Функцию Authon, реализующая авторизацию в программу.

  • Функция GroupSelection, реализующая выбор группы.

  • Функция Grades, реализующая простановку оценок.

  • Функция Attendance, реализующая простановку посещаемости.

  • Функция Comment, отвечающая за возможность написания комментария к дате.

  • Функция Deadline, дающая возможность установить дэдлайн и написать к нему комментарий.

  • Функция main, в которой реализовано основное взаимодействие пользователя с программой (меню и т.д.).

Весь код программы был написан в среде разработки Visual Studio 2022. Суммарный объем строк в тексте программы составляет 724.

#Введение

Программирование — не только написание кода, но и ещё планирование кода; определение того какие фичи нужны, а какие нет. У меня есть своя система, определяющая: как заниматься планированием программ, фич; как организовывать себя; как не забывать идеи. И я хочу в этой статье рассказать об этом. Что-то в этой системе придумал сам, что-то украл у других людей.

Эта статья может быть полезна начинающим программистам.

#На примере программы для изучения английских слов

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

В итоге эту програму я довёл до абсолютного конца за ≈40 часов чистого времени. Мне не нужны какие-то фичи, ничего не болит. Что очень необычно для пет-проекта, ведь их главное свойство, что они начинаются, но никогда не заканчиваются.

#2Создание продукта

#3Сбор идей

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

#4Беспорядочный сбор идей

Я беру файлик и называю его ideas.md. Теперь в нём будут лежать все идеи по данному проекту.

Сначала надо просто накидать всё что лежит в голове без всякого порядка. Я набросал, затем перечитывал это по многу раз и вносил те элементы что ещё не записал. Причём я записывал все идеи, даже самые безумные, мало ли что потом может пригодиться или случиться.

На беспорядочный сбор идей ушло 20 минут, и в результате получился такой файл:

(желательно его не читать, а просто увидеть масштаб)

@341bd26/ideas.md diff

  • Хотелось бы загружать из текста и из субтитров, чтобы была кнопка, которая читает буфер обмена
    • Чтобы при добавлении субтитров или текста, смотрелись все слова, и те что уже известны или выучены, не добавлялись, а новые слова показывались для дальнейшего добавления
  • Интерфейс добавления слова
    • Известные или выученные слова фильтруются
    • Показывается английское слово
    • Предлагается добавить его русский перевод вручную
    • Либо есть кнопка «я уже знаю это слово»
  • Чтобы для данного слова можно было видеть его контекст использования
  • Чтобы в специальном файле можно было настравить раскладку клавиатуры, чтобы автоматически раскладка подстраивалась без переключения раскладки.
  • Можно менять местами язык вопросов и ответов
  • Как вводятся слова:
    • Слово, которое не набиралось ни разу, надо сначала ввести n раз
    • Слова, которые 5 раз отвечались правильно, считаются на сегодня законченными
    • Слова, которые отвечаются неправильно, получают рейтинг -2
    • Так же контроллируется дата, когда человек отвечал и как. Если некоторое слово долго не набиралось, то необходимо его повторить, причем если до этого повторение работало хорошо, то приоритет меньший.
    • Только когда слово зарабатывает рейтинг кратный 5, то в записях фиксируется дата, когда это было сделано
  • Приоритет слов для набора: Каждая категория сортируется в случайном порядке
    • Слова, которые не набирались 5 раз
    • Слова, которые имеют отрицательный рейтинг
    • Слова, которые имеют рейтинг меньше 5
    • Слова, которые имеют рейтинг выше 5, но весь этот рейтинг был заработан свыше 5 дней назад
    • Слова, которые имеют рейтинг выше 10, но весь этот рейтинг был заработан свыше 5 дней назад
    • Слова, которые имеют рейтинг выше 15, но весь этот рейтинг был заработан свыше 20 дней назад (слова, которые давно не повторялись)
    • Слова, которые имеют рейтинг выше 20, но весь этот рейтинг был заработан свыше 20 дней назад
    • Всё, больше точно не надо
  • В центре экрана написано слово, которое надо перевести, ниже его написаны варианты ответа в виде «____ __», причем необходимо, чтобы _ были раздельны
    • Не соотносится с многозначностью слов, пусть будет просто N полей с не важно какой длиной
  • Как справляться с многозначностью слов
    • Для данного английского слова хранится множество пар русских слов, аналогично наоборот
    • Если сейчас показывается многозначное английское слово, то внизу нужно ввести все добавленные его русские смыслы
    • В статистике оценивается пара (русское слово, английское слово)
    • Если какое-то значение многозначного слова уже выучено или не требует повторения, то оно не показывается для ввода, оно просто показывается текстом, чтобы можно было понять какие смыслы введены, а какие нет
  • Статистика
    • Для каждого слова запоминается сколько раз его печатали, сколько правильно, сколько неправильно.
    • Для каждого дня запоминается сколько слов за сегодня отработано по полной, сколько слов отработано вообще итд.
    • Попробовать рисовать статистику через графики egui.
    • Ведётся количество новых добавленных слов в день
    • Где-то должно быть окошко чтобы посмотреть просто количество всех слов в системе, количество выученных слов и количество изучаемых слов
  • При добавлении новых слов есть возможность говорить: я это слово знаю; это не знаю. Чтобы не учить лишний раз известные слова, и чтобы в других текстах они не добавлялись как неизвестные.

Кстати, на этом этапе крайне приятно владеть быстрой слепой печатью, чтобы писать много текста и не отвлекаться процессом печати.

#4Систематизация идей

У меня есть принцип, что что-то надо систематизировать и разбирать на категории только в двух случаях:

  • Когда ты точно знаешь что эта категория использовалась ранее и она работает.
  • У тебя есть критическая масса элементов этой категории.

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

На это тоже ушло 20 минут.

Я хотел написать программу как можно быстрее, и как можно быстрее получать результат, поэтому я разделил идеи на разные категории, постарался выбрать такие идеи, чтобы реализовать первую рабочую версию (MVP) можно было максимально быстро.

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

В итоге файл с идеями теперь выглядит так:

@5387e15/ideas.md diff

систематизированные идеи

Реализовать в первую очередь

  • Общий интерфейс
    • Добавление слов
      • Через субтитры .src
      • Через текст
    • Окошко для выучивания слов показывается всегда и его нельзя закрыть, либо оно вообще привязано к фону
  • Интерфейс получения слов из текста или субтитров
    • Есть две кнопки: «добавить как текст», «добавить как субтитры»
  • Интерфейс добавления слова
    • Известные или выученные слова фильтруются
    • Показывается английское слово
    • Предлагается добавить его русский перевод вручную (новая строка означает новый смысл)
    • Есть кнопка «добавить переводы слова»
    • Либо есть кнопка «я уже знаю это слово»
  • Интерфейс ввода слова
    • Вверху написано английское (или русское) слово
    • Внизу N полей для ввода всех многозначностей этого слова
    • Некоторые поля могут быть серыми с уже написанными словами, так как эти слова выучены или не требуют сейчас повторения
    • Для перехода вниз или проверки текущего слова можно нажать Enter
    • Показывается правильно или неправильно введено слово только после введения всех слов
    • Для кажого слова показывается точками сколько раз ещё предстоит его вводить на сегодня
  • Порядок ввода слова
    • Первые 2 раза слово вводится с подсказкой программы
    • Затем 3 раза нужно ввести слово по памяти на сегодня
    • Следующий раз ввести слово 5 раз нужно через день и более
    • На этом этапе слово считается наполовину выученным
    • Потом 5 раз через неделю и более
    • Потом 5 раз через месяц и более
    • После этого слово считается абсолютно выученным
    • Каждая ошибка добавляет необходимость вводить ещё один лишний раз это слово
  • Слова в очереди
    • Русские и английские слова даются вперемешку
    • Всё вперемешку
    • Перебирается каждое слово и смотрится, нужно ли его набирать сегодня и сколько раз
  • Как справляться с многозначностью слов
    • Для данного английского слова хранится множество пар русских слов, аналогично наоборот
    • В статистике оценивается пара (русское слово, английское слово)
  • Статистика
    • Для каждого слова запоминается:
      • Сколько раз его печатали, сколько правильно, сколько неправильно
      • Все даты майлстоунов, когда его печатали в первый день, во второй день, черз неделю, через месяц

сложные идеи

Реализовать потом

  • Интерфейс получения слов из текста или субтитров
    • Программа всегда видит буфер обмена, если открыто это окно
    • Внизу серым написан текст, который сейчас находится в буфере обмена
    • Показывается только 200 первых символов этого текста, далее ставится троеточие и подписано количество байт занимаемых всем текстом
  • Интерфейс добавления слова
    • Чтобы для данного слова можно было видеть его контекст использования
  • Интерфейс статистики слова
    • Когда добавлено (дата, количество дней назад)
    • Сколько раз вводилось
    • Сколько правильно, сколько неправильно
    • Все майлстоуны (дней после добавления)
  • Интерфейс ввода слова
    • Есть кнопочка (i) напротив каждого слова, на которую можно нажать и посмотреть статистику этого слова
  • Интерфейс окна «раскладка клавиатуры»
    • Тебя просят включить русский язык и ввести все английские буквы, как если бы они находились при включённом английском языке
    • Аналогично при включённом английском языке просят ввести все русские буквы
    • Таким образом программа запоминает раскладку клавиатуры и сохраняет её в настройки, чтобы потом использовать чтобы не переключать раскладку клавиатуры
  • Статистика
    • Попробовать рисовать статистику через графики egui.
    • Где-то должно быть окошко чтобы посмотреть просто количество всех слов в системе, количество выученных слов и количество изучаемых слов
    • Для каждого дня запоминается:
      • Сколько слов сегодня отработано по полной
      • Сколько попыток совершено вообще, сколько правильных, сколько неправильных
      • Сколько задолженность на сегодня
      • Сколько слов сегодня добавили
      • Как долго была включена программа (простои больше 15 секунд не учитываются)
    • Можно получить статистику за всё время, суммировав статистику за каждый день

отсортировать

#3Планирование структур данных и функций

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

И начинать код лучше всего не с написания действий, а с проектирования типов/структур данных и сигнатур функций. Под структурами данных я понимаю не списки, деревья итд, а просто enum’ы и struct’ы. Я даже где-то слышал такую фразу:

Найти нужную структуру данных — это уже значит решить половину задачи.

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

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

Хорошая цитата из доклада

Мой ответ на вопрос о том зачем нужны типы, отлично иллюстрируется цитатой Коннора МакБрайда, тоже очень известного теоретика в области ЯП. Он в трэде жалуется на то что последние 20-30 лет писали ЯП таким образом чтобы типы сами выводились из программы, тогда как можно было делать всё наоборот: можно было писать типы, из которых потом выводятся программы. Мне кажется что это очень глубокая мысль. И, честно говоря, когда я это осознал, то очень сильно поменял своё отношение к тому как пишу код. Потому что ведь на самом деле типы — это идеальная проекция вашей доменной модели приложения на код, которая всегда будет актуальней кода, потому что если она внезапно перестаётся быть актуальной, то код не тайп-чекается. И это с моей точки зрения самое главное — написать крутой, корректный, правильный тип, насколько хорошо позволяет ваш ЯП. Даже если у вас не очень мощные типы, всегда есть возможности спроектировать вашу систему так, чтобы типы там отражали вашу доменную область наилучшим образом. Тогда процесс имплементации становится делом техники. В Idris’е даже есть момент: если вы правильно написали тип, то код может вывестись сам. Но в реальной жизни, когда мы не используем такие ЯП, как правило, когда есть хороший тип, то вы просто пишите банальный код и всё очень просто и понятно. И это мой ответ на то зачем же нужны типы.

41:18

Таймкод 39:19

Ещё есть идея, что чтобы удобнее было писать код, надо подумать о том как представить данные в том виде, чтобы задача в них решалась максимально естественно, и перевести их в этот формат:

×1.5
png

Ссылка на твит

Далее я буду кидаться коммитами, начинающимися с @. Мне кажется что оптимальным способом смотрения их будет: открыть в новой вкладке и пролистать diff, увидеть примерно что произошло. Либо можно просто их игнорировать, особо ничего не потеряете. Смотреть что происходило в коммитах может быть полезно если вам нужны прям детали как происходила моя разработка.

Спустя два коммита (@a8549a3, @b79f219) и 1ч 20м, у меня получились следующие типы, которые далее будут являться основой всего:

/// Итерация изучения слова, сколько ждать с последнего изучения, сколько раз повторить, показывать ли слово во время набора
struct LearnType {
    /// Сколько дней ждать с последнего изучения
    wait_days: i8,
    count: i8,
    show_word: bool,
}

/// Статистика написаний для слова, дня или вообще
struct TypingStats {
    typed: i32,
    right: i32,
    wrong: i32,
}

/// Обозначает одну пару слов рус-англ или англ-рус в статистике
enum WordStatus {
    /// Мы знали это слово раньше, его изучать не надо
    KnowPreviously, 

    /// Мусорное слово, артефакт от приблизительного парсинга текстового файла или субтитров
    TrashWord,

    /// Мы изучаем это слово
    ToLearn { 
        translation: String,

        /// Когда это слово в последний раз изучали
        last_learn: Day, 

        /// Количество изучений слова, при поиске того что надо печатать, проходим по всему массиву
        learns: Vec<LearnType>, 

        /// Статистика
        stats: TypingStats, 
    },

    /// Мы знаем это слово
    Learned { 
        translation: String,

        /// Статистика
        stats: TypingStats, 
    },
}

struct WordsSaved(BTreeMap<String, Vec<WordStatus>>);

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

Следующим этапом приступил к планированю структур и методов для графического интерфейса. Я пишу интерфейс через ImGui, про который написал отдельную статью. Поэтому на интерфейс у меня потратится минимально времени, и планировать его максимально легко.

Интерфейс распланировал за 32м: @0cab890, и после этого планирования даже чуть-чуть улучшились и основные структуры данных.

#3Написание кода

Далее за 1ч написал код логики: @96eb608.

Затем за 2ч 45м написал код интерфейса до минимально рабочего состояния: @7b8de3d.

Кстати, писать работающий код поверх распланированных функций и типов крайне приятно, код так легко и быстро идёт.

Итак, на отметке чистого времени у нас 6ч 16м, и программа выглядит следующим образом:

×1
png

Здесь работает всего три окошка и основной функционал.

#3Todo-листы

Итак, я написал самый минимальный прототип. По идее им уже можно пользоваться.

Нам больше не настолько нужен файлик с идеями, удаляем оттуда всё реализованное: (он стал совсем маленьким)

@47b0669/ideas.md diff

идеи неизвестной полезности

  • Чтобы при добавлении слов замерялась их частотность, даже частотность известных, и она просто суммировалась к тому что уже хранится, чтобы можно было видеть частотность выученных слов. Хотя и для этого придётся какой-то сложный интерфейс пилить.
  • Интерфейс добавления слова
    • Чтобы для данного слова можно было видеть его контекст использования
  • Интерфейс ввода слова
    • Есть кнопочка (i) напротив каждого слова, на которую можно нажать и посмотреть статистику этого слова
  • Интерфейс статистики слова
    • Когда добавлено (дата, количество дней назад)
    • Сколько раз вводилось
    • Сколько правильно, сколько неправильно
    • Все майлстоуны (дней после добавления)

И заводим файлик todo, в котором разместим конкретные todo-пункты для выполнения:

@47b0669/learn_words.todo diff

общее:
  ✔ сделать чтобы по интерфейсу написания слова можно было легко перемещаться @done (21-07-29 23:34)
  ✔ чтобы субтитры могли возвращать ошибку и она показывалась в окне @done (21-07-29 23:41)
  ☐ сделать чтобы перемещение по интерфейсу ввода слова делалось через enter
  ☐ добавить чтобы каждое слово знало свой текущий уровень
  ☐ чтобы из файла считывалась комбинация (Words, Settings), и чтобы она же сохранялась
  ☐ замер времени в программе
    + когда простой мышки или клавиатуры больше 15 секунд, программа переходит в режим паузы, и прекращает замер времени, и это показывается на весь экран
    + время в программе за сегодня показывается снизу
    + каждый день запоминается количество времени в програме

раскладка:
  ☐ сделать окно для раскладки клавиатуры
    + галочка "использовать автопереключение раскладки", и если галочка отмечена, то далее показывается всё что есть
    + введите все свои английские символы
    + введите все свои русские символы
    + если ввести символ не можешь, значит ставить пробел
    + чтобы чекалось если вдруг из двух разных языков находятся одинаковые символы, тогда отвергать такую раскладку
    + можно ставить enter для удобства
    + сравнивалось количество символов без enter, и говорилось когда они совпадают а когда нет
    + кнопка "использовать эту раскладку"
  ☐ сделать виджеты поля ввода, которое умеет определять текущую раскладку и язык ответа и автоматически подменять буквы
  ☐ раскладка должна храниться в settings

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

васм:
  ☐ хранение в куках
  ☐ заюзать quad_rand
  ☐ при закрытии вкладки чтобы автоматически сохранялся прогресс
  ☐ кнопки для считывания и загрузки своих данных в программу в меню в пункте Data -> {Import, Export}

Тут стоит отвлечься насчёт того как я веду todo-списки. Одни люди это делают через GitHub, другие через приложение на телефон, а я через расширение для текстового редактора. Я пишу в Sublime + PlainTasks, так же есть похожее расширение для VSCode: Todo+.

Учтите, что этот файл выглядит очень хорошо только в Sublime + PlainTasks, от markdown здесь никакого форматирования к сожалению не делается.

Теперь далее можно реализовывать по одному пунктику и сразу видеть результат.

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

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

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

#3Обычный цикл разработки

Теперь я выполняю туду-пункты и потихоньку коммичу изменения от них. Пока выполняю одни пункты, в голову могут приходить идеи других, и их тоже заношу в туду. Что-то совсем радикальное заношу в файлик ideas.md, чтобы не забыть, но и не заставлять себя реализовывать.

На таймере чистого времени 21ч 21м и следующий результат:

×1.2
png

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

На таймере 33ч 23м чистого времени и я публикую статью про эту програму.

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

Программу можно считать завершённой.

#3Куда девать выполненные туду-пункты

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

@42b5e72/learn_words.todo link

общее:
  ☐ для stackplot сделать чтобы самые маленькие по площади были в самом низу, а самые большие в самом вверху

статьи:
  ✔ рассказать о quad-storage @done (21-08-10 21:52)
  ☐ написать статью о том как сделал эту прогу
  ☐ 1 сентября опубликовать статью по результатам месячного использования этой проги

далёкая перспектива:
  ☐ https://github.com/emilk/egui/issues/595
  ☐ в зависимости от того что выключается в stackplot в легенде, убирать это из вычислений, для этого надо внедрить фичу в egui

рефакторинг:
  ✔ причесать функцию ui, вынести поля ввода со всеми их фичами в отдельную функцию, чтобы не было этого копипаста, а данные в отдельную структуру @done (21-08-10 19:27)
  ☐ для того чтобы тратилось меньше памяти, и прога работала быстрее за счёт уменьшения числа аллокаций, использовать айдишники строк, а все строки хранить в одной структуре
  ☐ переделать так, чтобы в words хранился не массив, где слово может быть выученным и подлежащем изучению, а чтобы сверху там было (trash, known, (learn, и вот уже внутри learn массив (либо выученное, либо изучаемое))) (сомнительное удобство)
  ☐ попытаться заюзать gat

-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
АРХИВ:
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------

общее:
  ✔ сделать чтобы по интерфейсу написания слова можно было легко перемещаться @done (21-07-29 23:34)
  ✔ чтобы субтитры могли возвращать ошибку и она показывалась в окне @done (21-07-29 23:41)
  ✔ добавить чтобы каждое слово знало свой текущий уровень @done (21-07-30 14:18)
  ✔ чтобы из файла считывалась комбинация (Words, Settings), и чтобы она же сохранялась @done (21-07-30 14:23)
  ✔ замер времени в программе @done (21-07-30 15:01)
    + когда простой мышки или клавиатуры больше 15 секунд, программа переходит в режим паузы, и прекращает замер времени, и это показывается на весь экран
    + время в программе за сегодня показывается снизу
    + каждый день запоминается количество времени в програме
  ✔ сделать чтобы перемещение по интерфейсу ввода слова делалось через enter @done (21-07-31 23:24)
  ✔ сделать базовое окно about @done (21-07-31 23:35)
  ✔ кажется на васме протекает буфер обмена при использовании русских символов. видимо путаются количество чаров и длина в байтах, надо пофиксить @done (21-08-01 00:10)


раскладка:
  ✔ сделать окно для раскладки клавиатуры @done (21-07-30 19:30)
    + галочка "использовать автопереключение раскладки", и если галочка отмечена, то далее показывается всё что есть
    + введите все свои английские символы
    + введите все свои русские символы
    + если ввести символ не можешь, значит ставить пробел
    + чтобы чекалось если вдруг из двух разных языков находятся одинаковые символы, тогда отвергать такую раскладку
    + можно ставить enter для удобства
    + сравнивалось количество символов без enter, и говорилось когда они совпадают а когда нет
    + кнопка "использовать эту раскладку"
  ✔ сделать виджеты поля ввода, которое умеет определять текущую раскладку и язык ответа и автоматически подменять буквы @done (21-07-30 19:30)
  ✔ раскладка должна храниться в settings @done (21-07-30 19:30)

статистика:
  ✔ основа для замера каждый день @done (21-07-30 15:34)
    + замерять количество попыток, правильных и неправильных
    + новых неизвестных слов
    + обновляется либо вручную, либо при закрытии программы, либо при открытии окна статистики
    + заодно замерять количество попыток вообще
  ✔ показывать статистику за сегодня внизу @done (21-07-30 15:34)
  ✔ запоминание количества слов каждого уровня каждый день @done (21-07-30 15:34)
  ✔ статистика количества слов в программе: @done (21-07-30 16:23)
    + известные
    + мусорные
    + изучаемые на каждый уровень
    + изученные полностью
    + вычисляется при вызове программы из words
  ✔ график количества запомненных слов за все дни, условно какую площадь он занимает, со stems, по уровням @done (21-07-30 17:40)
  ✔ аналогично верхнему график количества правильных и неправильных попыток @done (21-07-30 17:40)
  ✔ плитка как на гитхабе @done (21-07-30 23:36)
    + можно выбирать какой параметр показывать, учитывая всё что известно для текущего дня

васм:
  ✔ кнопки для считывания и загрузки своих данных в программу в меню в пункте Data -> {Import, Export} @done (21-07-30 18:03)
  ✔ заюзать quad_rand @done (21-07-31 14:51)
  ✔ хранение в куках @done (21-07-31 22:20)
    + https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage
  ✔ попробовать скомпилить под васм @done (21-07-31 23:12)
  ✔ при закрытии вкладки чтобы автоматически сохранялся прогресс @done (21-07-31 23:12)

рефакторинг:
  ✔ сделать trait ClosableWindow, и функцию process_window, которая обрабатывает окно, которое может закрыться, чтобы не копипастить это постоянно. или лучше структуру, которая оборачивается вокруг структуры окна, умеет закрываться, сама конструирует окно, и сама в функции ui отслеживает когда окно хотят закрыть @done (21-07-30 16:06)

критичное:
  ✔ если просто нажимать кнопку мыши без движения, то выскакивает пауза @done (21-08-02 21:20)
  ✔ для того чтобы читать буфер обмена, пользователь должен сам нажать ctrl+v, тогда мб убрать автоматическое считывание буфера обмена, аналогично для ctrl+c @done (21-08-02 21:54)
  ✔ подсказки должны даваться с пробелом, а то из-за курсора их не видно @done (21-08-02 21:55)
  ✔ чтобы автосохранение было после каждого слова @done (21-08-02 21:56)
  ✔ если нажать use this text с пустым текстом, то происходит паника, file: "src/main.rs", line: 1185, col: 38 @done (21-08-02 22:01)
  ✔ кажется в копипасте нельзя вставить текст длиньше 32768 символов @done (21-08-02 22:37)
  ✔ переделать настройки количества изучения, чтобы они не копипастились в каждое слово, а были глобальны @done (21-08-02 23:12)
    + тогда надо чтобы это можно было задавать в окне settings

сделать следующим:
  ✔ при вводе слова с подсказкой необходимо вводить не только перевод слова, но и его самого. это нужно, потому что я пытаюсь ускориться, и не читаю что за слово с подсказкой я пишу @done (21-08-03 17:22)
  ✔ наверное за сессию надо изучать меньше слов, а не все добавленные. сделать настройку, которая позволяет взять N (пусть для начала будет 20) слов в пул, и изучать их, и только когда они кончатся, изучать дальше. @done (21-08-03 17:48)
  ✔ окно-редактор-просмотрщик слов, где можно искать слова fuzzy поиском, где сразу отображается внутренность @done (21-08-03 20:20)
  ✔ автоматическое открытие окна просмотрщика слов, где фильтрование происходит по текущему добавленному слову @done (21-08-03 20:20)
  ✔ окно для редактирования одного слова @done (21-08-03 22:16)
  ✔ сделать карандашик напротив слова, которое открывает окно для этого слова и позволяет его редактировать @done (21-08-03 22:16)
  ✔ всё-таки добавить фичу, показывающую контекст конкретного слова, заодно показывать частоту его встречи в данном тексте @done (21-08-03 23:02)
  ✔ должна быть возможность выбирать количество новых слов, и количество слов для повторения @done (21-08-04 14:57)
  ✔ после добавления текста или субтитров должно показываться окно с инфой: @done (21-08-04 17:20)
    + всего слов
    + уникальных слов
    + отфильтровано
      + известные (known, trash, learned)
      + изучаемые (tolearn)
    + неизвестных
  ✔ синхронные субтитры, когда одновременно показывается и русский и английский вариант @done (21-08-04 23:51)
    ✔ разобраться с выделением текста при поиске @done (21-08-04 23:55)
    ✔ чтобы когда в вводе ничего нет, или нашлись новые результаты, скролл улетал на начало @done (21-08-04 23:57)
    ✔ 0 всегда обозначает отсутствие скролла @done (21-08-04 23:57)
    ✔ сделать чтобы скролл целился на лейбл только после нажатия кнопки @done (21-08-04 23:57)
    ✔ убрать массив в поиске слова @done (21-08-05 00:03)
  ✘ вынести общую часть в коде find_whole_word @cancelled (21-08-05 00:14)
  ✔ сделать чтобы нулевой элемент не показывался в кнопочках, и чтобы не выделялся, и чтобы на него нельзя было попасть @done (21-08-05 00:14)
  ✔ в окне добавления слова может унести контекст вправо @done (21-08-05 13:52)
  ✔ возможность менять масштаб в настройках @done (21-08-05 14:02)
  ✔ должна быть галочка, позволяющая двигать график @done (21-08-05 14:19)
  ✔ нужна белая тема, ибо на тёмной глазам неприятно @done (21-08-05 14:35)
    + запоминать тему в настройки
    + рисовать всё окно белым или чёрным в зависимости от темы
    + запомнить цвета для всяких штук типо activity в зависимости от темы
  ✔ заюзать нормальный рандом, который инициализируется текущим временем @done (21-08-05 19:22)
  ✔ после ввода какого-то слова неправильно, надо его снова ввести с подсказкой, и переходить дальше не разрешит, пока правильно не напишешь @done (21-08-10 16:34)
    + после неправильного ввода слова его надо снова написать даже несколько раз
  ✔ пропускать окно проверки для ввода с подсказкой @done (21-08-10 16:34)
  ✔ после ввода слова должна быть возможность инвертировать правильный и неправильный результаты @done (21-08-10 16:34)
    + чтобы там использовалось right_to_left
    + для этого надо регистрировать попытки не после их ввода, а после нажатия кнопки "next"
  ✔ чтобы если нажимается backspace на пустом поле или кнопке, фокус запрашивался назад @done (21-08-10 17:54)
  ✘ перевести Words на хранение двух разных языков, и при выборе слов для набора считать только английские слова @cancelled (21-08-10 18:21)
  ✘ сортировать слова для добавления не по их алфавитному написанию, а по порядку как они встречаются в тексте, чтобы лишний раз не читать одни и те же предложения @cancelled (21-08-10 21:51)
  ---
  ✔ в окне add words должно быть поле где можно добавлять известные переводы этого слова @done (21-08-10 18:12)
  ✔ сделать кнопку для скипа добавляемых слов @done (21-08-10 18:12)
  ✔ нужна возможность отменить предыдущее нажатие при добавлении слова, а то так можешь быстро нажимать что знаешь слово и раз, пропустил одно @done (21-08-10 18:12)
    + запоминать одно слово, и удалять его из words методом для удаления, если нажалась кнопка back
  ---
  ✔ сделать чтобы при выборе слов добавлялись сразу переводы, и выбор останавливался когда набиралось больше чем нужное количество, или все слова кончались @done (21-08-10 19:02)
  ✔ в первую очередь должны выбираться наиболее старые слова в окне выбора слов @done (21-08-10 19:02)
  ✔ писать сколько осталось набрать это слово сегодня @done (21-08-10 19:12)
  ✔ чтобы на кнопке при нажатии backspace отправляло назад @done (21-08-10 19:16)
  ✔ должна быть кнопка отмены текущего набора и выбора количества слов для изучения @done (21-08-10 19:26)
  ✔ наверное лучше сначала набрать все слова, которые ты не знаешь с подсказкой, в рандомном порядке, а уже затем набирать все слова которые надо без подсказки набирать причём надо сделать не просто выбор рандома, а чтобы нормально shuffle'ился весь массив, аналогично всё остальное, чтобы подряд не шло два раза одно и то же слово никогда @done (21-08-10 19:46)
  ---
  ✔ чтобы при переименовании перевода, перевод тоже переименовывался нормально @done (21-08-11 18:15)
  ✔ сохранять всё после изменения слова @done (21-08-11 18:15)
  ✔ в окне edit word должна быть возможность удалять конкретный перевод слова, и добавлять новые, в окне выставления дня должно автоматически ставиться сегодняшний день @done (21-08-11 18:25)
  ---
  ✔ чтобы через настройки можно было задавать уровни и количество повторений. @done (21-08-11 18:39)
  ---
  ✔ сделать чтобы текущий день считался локальным, а то у меня в 0:00 день был не сегодняшний @done (21-08-11 19:04)
  ✘ законтрибьютить user_dpi в egui-miniquad @cancelled (21-08-11 19:27)
  ✘ мб попробовать отображать панику на экране @cancelled (21-08-11 19:27)
  ✔ баг: не все слова выбираются когда выбираешь для повторения то, что не имеет перевода для повторения @done (21-08-11 23:02)
  ---
  ✔ перейти на egui-web, egui-glium @done (21-08-11 22:25)
  ✔ добавить возможность скачивать экспорт как файл @done (21-08-12 14:58)
  ✘ добавить кнопку, которая выделяет всё @cancelled (21-08-12 14:58)
  ---
  ✔ оптимизировать цвета в белой теме, мб через отдельное окно @done (21-08-13 19:18)
  ✘ заставить в вебе работать изменение масштаба @cancelled (21-08-13 20:24)

не криитчное:
  ✔ кажется нативное приложение не хочет сохранять статистику в файл @done (21-08-01 23:06)
  ✔ кажется окно добавления слов не фильтрует известные слова @done (21-08-01 23:12)
  ✔ невозможно нажать пробел из-за замены символов @done (21-08-02 21:06)
  ✔ слова должны быть огромными, а не простой label @done (21-08-02 21:06)
  ✔ чтобы слова можно было удалять @done (21-08-03 23:15)
  ✘ при вводе слова должна быть возможность посмотреть его статистику @cancelled (21-08-03 23:15)
  ✘ при вводе в попытках слова должна быть возможность отредактировать это слово (типо иногда оставил лишнее окончание или что-то такое) @cancelled (21-08-03 23:15)
  ✔ в окне добавления слов по тексту показывать сколько было уникальных, а сколько отфильтровалось @done (21-08-05 14:35)
  ✔ добавить learned translations в окно добавления слов @done (21-08-05 14:36)
  ✘ в github стате затемнять на dim 0 те элементы где 0 @cancelled (21-08-05 14:39)
  ✘ должна быть возможность добавлять алиасы для какого-то слова, типо если ты его ввёл не так, чтобы оно считалось тоже правильным. @cancelled (21-08-11 19:04)
    + тогда должна быть кнопка после ввода слова, которая не только отменяет неверность текущего ответа, но и одновременно добавляет его в алисы
    + это не нужно, так как есть кнопка invert

#2Время работы над этой программой

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

@aba59d5/video.md link

информация

  • (во времени не учитывается время на написание статей)
  • время написания первых идей: 20 минут
  • время их ситематизации: 20 минут
  • планирование структур данных, связанных с основной логикой, без учёта интерфейса: 1 час 20 минут
  • планирование структур и методов интерфейса: 32м (2:32)
  • написание кода основной логики: 1 час (3:32)
  • написание кода интерфейса до минимально рабочего состояния: 2ч 45м (6:16)
  • 6ч 16м ————————————————— Минимально рабочее состояние
  • сделал два пункта и распланировал дальнейшие идеи в todo: 45м (7:02)
  • слетел таймер
  • три общих пункта: 47м (0:47)
  • основа статистики: 34м (1:21)
  • рефакторинг окон: 30м (1:51)
  • реализация статистики и других мелких улучшений: 1ч 53м (3:44)
  • раскладка клавиатуры: 1ч 4м (4:48)
  • github-like плитка: 3ч (7:44)
  • написал quad-storage: 1ч 49м (9:33)
  • заставил запускаться в васме, пофиксил баги и небольшие дополнения: 1ч 50м (11:23)
  • скинул таймер
  • написание статьи про программу: 2ч 56м
  • 21ч 21м ————————————————— Средне рабочее состояние
  • закончил править все критичные пункты: 1ч 30м
  • начал таймер
  • сделал чтобы можно было выбирать количество слов: 44 минуты (0:44)
  • сделал чтобы можно было искать по всем словам с fuzzy поиском и это работало при добавлении слова: 1ч 2м (1:46)
  • сделал окно для редактирования одного слова: 53м (2:39)
  • добавил показ контекста данного слова из текста: 46м (3:15)
  • для работы можно выбирать количество новых слов и количество слов для повторения: 21м (3:36)
  • добавил вывод информации о количестве слов в тексте после добавления: 20м (3:56)
  • фича синхронных субтитров: 3ч 26м (7:22)
  • мелкие фичи: 57м (8:19)
  • переход на другой генератор рандома: 10м (8:29)
  • сбросил таймер
  • дописал статью про программу с учётом новых фич и пользования: 2ч 3м
  • 33ч 23м ————————————————— Первый релиз
  • повторение слов после неправильного ввода и инвертирование результатов: 1ч 48м
  • улучшения окна add words: 20м
  • выбор переводов при выборе слов и выбор наиболее задолженных слов: 43м
  • улучшения набора слова: 45м
  • улучшения окна edit word: 30м
  • задание количества повторений в настройках: 11м
  • чтобы текущий день считался правильно с учётом тайм-зоны: 37м
  • переехал на egui_template: 2ч 13м
  • написал про второй релиз: 30м
  • 41ч ————————————————— Второй релиз
  • добавил скачивание статистики в виде файла: 1ч 15м
  • оптимизировал цвета в белой теме: 1ч 2м
  • не смог заставить в вебе работать изменение масштаба: 1ч
  • написание статьи про imgui: 2ч 44м
  • написание статьи про то как пишу программы: 1ч

#2Пример сложной фичи

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

Когда дело доходит до такой сложной фичи, её надо хорошо продумать.

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

Вот результат продумывания в файлике ideas.md:

@80a5703/ideas.md diff

синхронные субтитры

  • это будет отдельное окно, которому можно указывать конкретное слово, а оно будет их искать все его встречи в первом предоставленном тексте
  • окно для добавления имеет два поля для ввода текста: Lang 1 (to search words), Lang 2 (translation of Lang 1).
  • у окна для показывания есть метод, который позволяет ввести в поиск нужное слово, если окно открыто. в отличие от окна поиска, это окно не открывается автоматически
  • использует column для окна вставки субтитров
  • использует grid для показывания параллельно. так как там могут быть пустые места с обоих сторон.
  • использует код аналогичным scrolling для выбора элемента скролла
  • перебирает одновременно оба субтитра и смещает указатель текущего времени, если у текущего времени есть пересечение с тем что на другом языке, связывает их в один
  • ещё в окне показывается номер элемента слева, то есть grid состоит из 3 элементов
  • если одна фраза на одном языке пересекается с несколькими на другом языке, то она показывается только для первой
  • есть галочка искать по словам или по вхождениям

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

Сначала я планировал алгоритм в случае того что субтитры выглядят хорошо. На картинке ниже время идёт справа-налево, снизу русские субтитры, сверху английские.

×1
jpg

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

×1
jpg

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

  • Рассмотреть крайние случаи.
  • Узнать какие у тебя есть гарантии от входных данных, увидеть подвох.
  • Постараться продумать алгоритм без костылей, чтобы на его реализацию не ушло больше часов, чем длится олимпиада.
  • Чтобы алгоритм работал за приемлемое время.

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

Так что крайне советую вам прокачаться в олимпиадном программировании на codeforces. LeetCode фигня, ибо он плохо замеряет время работы программы, и вообще задачки там слабые.

Кстати я использую бумагу только когда надо что-то рисовать или писать математические формулы, в других случаях писать текст на клавиатуре в миллион раз быстрее. Так что лично я советую вам писать идеи и туду-пункты не на бумаге.

#2Про чистое время

Я замерял время работы и можно увидеть что чистого времени получилось 40 часов, что это значит? Это значит что я бы мог сделать эту программу за рабочую неделю? Нет.

Моё чистое время замерялось только во время работы, перерывы я не засчитывал. Ещё я работал не по 8 часов в день, а меньше: иногда 2, иногда 4. И самое главное — между этими подходами у меня были большие перерывы в виде отдыха и сна. Так что это может быть причиной почему я так эффективно работал.

На работе мы работаем с перерывами, итого за 8 часов рабочего дня, из них по-настоящему рабочими получается всегда меньше. Говорят, 4-6.

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

Так что все эти инициативы по переходу на 4-часовой или 6-часовой рабочий день имеют смысл.

#На примере фичи для Portal Explorer

Это пример про то как я внёс непростую фичу в другую програму.

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

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

Поэтому сначала я взял и начал расписывать вопросы и ответы на них. Здесь самое главное — продумать как фича встанет в имеющуюся структуру программы. Я рассуждал в форме текста. Когда появилось первое понимание — накидал struct’урки и enum’ы. Наблюдать результат рассуждений и типы можно на скриншоте ниже:

×1
png

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

×1.1
png

Теперь, после того как у меня всё чётко и понятно в голове, я мог начать очень эффективно фигачить код,.

И затем код был благополучно реализован. Конечно, пару штук на планировании я забыл, но без этого никуда.

#Про пет-проекты

Немного мыслей про то как делать пет-проекты, кажется что они подходят духу статьи.

#2Поиск аналогов

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

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

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

Ну или если ваша задача в том чтобы научиться какой-то технологии через пет-проект, то этот совет неприменим, тут писать очередной велосипед — святое дело.

#2Важнее что-то не делать

Просто процитирую tonsky:

Давайте расскажу вам про главное правило пет-проектов. Главное правило пет-проектов: придумать, как ничего не делать.

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

«Скрипты. Планировщик в CI запускает тесты, оформленные в pytest/junit/whatever, рисует красивые картинки, срёт уведомлениями, если что-то пошло не так. Надо только определиться, кто отвечает за реакцию на уведомления.»

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

Но в пет-проектах, к сожалению, зарплату не платят, поэтому приходится адаптироваться. Что не так с этим предложением?

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

Трюк с пет-проектами в том, чтобы обмануть себя и успеть сделать что-то, что можно показать людям до того, как ты устанешь и тебе надоест. А тебе устанет и надоест, trust me. Поэтому количество нерелевантной работы надо резать жестко и беспощадно. И поэтому я так доволен решением с авторизацией: работы нет, а тестирование выполняется.

Классическая иллюстрация этого принципа это «не пишите движок блога». Потому что устанете быстрее, чем напишете первый пост. Люди, которые хостятся на Github Pages с готовым шаблоном или на WordPress — те, которым интересно решить проблему; люди, которые пишут движок — те, которым интересно попрокрастинировать. Поэтому вы читаете этот текст в Телеграмме, а не на каком-то самописном сайте с собственным компилятором — я бы этот компилятор до сих пор писал.

Другой пример из недавнего — Roam Research. Чуваки лет то ли пять, то ли семь сидят без сервера вообще, тупо складывают все в Firebase и ничего, работают, денег подняли. Во всей инфраструктуре нет ни одного сервера. Потом пришел создатель Athens Research, решил склонировать Roam, но еще больше не заморачиваться, и не стал делать даже Firebase. Просто сделал локального клиента, так еще и без авторизации обошелся. И все равно 2 ляма поднял. Легенда.

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

#2Прототипирование

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

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

Поэтому ImGui здесь отлично заходит для прототипов или пет-проектов. Он ускоряет разработку.

#2Сразу отбрасывать сложные фичи

Как мне удалось так быстро сделать программу для изучения английских слов?

Потому что на самом начальном этапе я откинул самые сложные фичи:

  • Иметь встроенный словарь
  • Нормализация слов (убрать -s, -ing, -ed итд.)
  • Retained mode интерфейс

Благодаря этому я тратил время только на войну с собой. Не воюя с другими библиотеками.

Такие вещи надо заранее откидывать, иначе ты никогда не закончишь свой проект. Вначале всё должно быть тупо и вручную.

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

#Автоматизация

Щас хайпятся всякие GitHub Copilot, которые типо пишут код за программистов, и типо бу-бу-бу программистов заменят машины.

Посмотрите на эту статью ещё раз. Разве такое можно автоматизировать? Это настоящее мышление, которое требуется для программирования даже джуном. Это нельзя автоматизировать до тех пор, пока не будет создан сильный ИИ. А до тех пор Copilot будет только инструментом, который немного упрощает разработку в руках программиста.

А когда создадут сильный ИИ, то отпадёт смысл в любом человеческом труде на планете Земля, так что нет смысла волноваться конкретно за программистов. Все станем бесполезными вместе.

#Заключение

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

Если вам нравится что я делаю, то подписывайтесь на меня в Telegram и YouTube.

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

Определение идеи

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

  1. Что должна делать написанная программа.
  2. Чем будет полезна.
  3. Как может помочь пользователям, чем упростит работу.
  4. Чем отличается от конкурентов, похожих программ.
  5. Где можно написать программу.
  6. На какой платформе написать прогу.

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

Выбор языка программирования

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

C (Си)

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

Новым пользователям, которые хотят заняться написанием одной программы и бросить программирование, Си совсем не подойдёт. Его сложно изучить из-за того, как мало по нему материалов в сети и учебниках, а пользователей, которые пишут на нём — немного, поэтому знатоков в языке ещё нужно поискать. Но если мир программирования затянет пользователей — его изучение рекомендуется.

C++

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

Python

Классика, которая навсегда останется любимой среди программистов. Язык — основа, которую изучают как любители, так и профессионалы. Как и Си++, Python подойдёт для того, чтобы писать программы на простом уровне, отвечающие за базовые функции или для более сложных продуктов.

Python, сколько бы ни спорили пользователи интернета, остаётся первым в списке рекомендаций, когда спрашивают: «С какого языка начать программировать». Он — прост в использовании, а обучающих курсов, учебников, материалов — более, чем достаточно, чтобы каждый нашёл то, что поможет ему изучить язык лучше.

Java

Такая же классика, как и Python, рекомендуемая к изучению. Это — улучшенная версия C++, с большим функционалом. С помощью Java происходит написание программ для игр, бизнеса, менее масштабных целей. Запускается на Операционных системах любого типа, что делает его любимым, помогает использовать и проверять везде.

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

Изучение языка

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

Для изучения могут быть использованы:

  1. Учебники.
  2. Курсы.
  3. Открытые Интернет-ресурсы.
  4. Форумы для программистов.

Написание программы

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

Для того, чтобы упростить написание, также необходимо использовать немаловажную функцию комментирования. По умолчанию комментарий начинается с символов «//», но может отличаться в зависимости от выбранного языка. Комментарии — строчки, которые не учитываются при компиляции кода, программисты используют их, чтобы отметить, что делает функция или строка. Комментарии упростят работу, когда строчек будет более 500 или 1 000, и поиск чего-то станет сложнее.

Стоит приготовиться к тому, что написание кода — нелёгкое дело. Для него понадобится много нервов, удаления лишних строчек, исправления того, в чём пользователь был уверен с самого начала. Если дело идёт слишком сложно, а принципы программирования — непонятны даже после десяти учебников, стоит обратиться к специалистам, которые знают, что делать. Обращение к профессионалам актуально для тех, кто хочет написать бизнес-программы — иногда для их написания новичкам нужна помощь.

Как написать программу самому

От начала до конца: пошаговое руководство по написанию программ на языке Си

Язык программирования Си был разработан в начале 1970-х годов в Bell Labs. С тех пор он стал одним из самых распространенных языков программирования, используемых для написания операционных систем, приложений и библиотек. В этой статье мы предлагаем пошаговое руководство по написанию программ на языке Си.

Шаг 1: Установка компилятора Си

Прежде чем начать писать программы на языке Си, необходимо установить компилятор. Компилятор преобразует исходный код на языке Си в машинный код, который может быть выполнен на компьютере. Существуют множество компиляторов Си, доступных для разных операционных систем. Например, на Linux можно установить GCC (GNU Compiler Collection) с помощью команды:

sudo apt-get install gcc

На Windows можно установить MinGW (Minimalist GNU for Windows). После установки компилятора можно проверить его работу, написав простую программу на языке Си и скомпилировав ее. Например, для программы, которая выводит строку «Hello, World!», исходный код может выглядеть так:

#include <stdio.h>

int main() {
   printf("Hello, World!");
   return 0;
}

Для компиляции этой программы введите в консоли:

gcc helloworld.c -o helloworld

Здесь «helloworld.c» — это имя файла с исходным кодом программы, «-o helloworld» — это параметр, который указывает компилятору, что нужно создать файл с именем «helloworld», содержащий скомпилированную программу.

Шаг 2: Знакомство с основами языка Си

Перед тем, как начать писать сложные программы, необходимо понимать основные концепции языка Си. Некоторые из них включают типы данных, операторы, условные операторы, циклы и функции. Вот несколько примеров, которые помогут вам понять основы языка:

#include <stdio.h>

int main() {
   int a = 5; // объявление переменной 'a' типа 'int' со значением 5
   float b = 3.14; // объявление переменной 'b' типа 'float' со значением 3.14
   char c = 'A'; // объявление переменной 'c' типа 'char' со значением 'A'
   
   if (a > b) {
      printf("a больше b\n");
   } else {
      printf("b больше a\n");
   }
   
   for (int i = 0; i < 10; i++) {
      printf("%d\n", i);
   }
   
   return 0;
}

Здесь мы объявляем три переменные: ‘a’ типа ‘int’, ‘b’ типа ‘float’ и ‘c’ типа ‘char’. Затем мы используем условный оператор ‘if’, чтобы проверить, является ли ‘a’ больше, чем ‘b’. Если это так, мы выводим строку «a больше b», в противном случае — «b больше a». Затем мы используем цикл ‘for’, чтобы вывести числа от 0 до 9. Функция ‘printf’ используется для вывода данных на консоль.

Шаг 3: Создание функций

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

#include <stdio.h>

int add(int a, int b) {
   return a + b;
}

int main() {
   int result = add(5, 3);
   printf("5 + 3 равно %d\n", result);
   return 0;
}

Мы создаем функцию ‘add’, которая принимает два аргумента типа ‘int’ и возвращает их сумму. Затем мы вызываем эту функцию в нашей основной программе и передаем ей значения 5 и 3. Функция возвращает сумму 8, которая сохраняется в переменной ‘result’, и мы выводим ее на консоль.

Шаг 4: Работа с указателями

Указатели — это еще один важный концепт языка Си. Указатели используются для работы с памятью и обеспечивают возможность более эффективной работы с данными. Вот пример использования указателей:

#include <stdio.h>

int main() {
   int var = 5;
   int* var_ptr = &var; // объявление указателя на переменную 'var'
   
   printf("Значение переменной 'var': %d\n", var);
   printf("Значение переменной 'var' через указатель: %d\n", *var_ptr);
   
   *var_ptr = 10;
   
   printf("Значение переменной 'var' после изменения через указатель: %d\n", var);
   
   return 0;
}

Мы объявляем переменную ‘var’ со значением 5, а затем объявляем указатель ‘var_ptr’, который указывает на значение ‘var’. Затем мы выводим значение переменной ‘var’ на экран и используем указатель для вывода того же самого значения. Затем мы изменяем значение переменной через указатель и снова выводим значение переменной на экран. Выходные данные должны быть следующими:

Значение переменной 'var': 5
Значение переменной 'var' через указатель: 5
Значение переменной 'var' после изменения через указатель: 10

Шаг 5: Работа с массивами

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

#include <stdio.h>

int main() {
   int arr[5] = {1, 2, 3, 4, 5}; // объявление массива
   
   for (int i = 0; i < 5; i++) {
      printf("%d\n", arr[i]); // вывод элементов массива
   }
   
   return 0;
}

Здесь мы объявляем массив ‘arr’ длиной пять элементов и инициализируем его значениями 1, 2, 3, 4 и 5. Затем мы используем цикл ‘for’, чтобы вывести каждый элемент массива на экран.

Шаг 6: Работа с файлами

Работа с файлами — это ключевой элемент программирования. В языке Си существуют функции для чтения и записи файлов. Например, вот пример программы, которая читает содержимое файла и выводит его на экран:

#include <stdio.h>

int main() {
   FILE *fp;
   char c;
   
   // открытие файла
   fp = fopen("file.txt", "r");
   
   // чтение файла и вывод содержимого на экран
   while ((c = getc(fp)) != EOF)
      printf("%c", c);
   
   // закрытие файла
   fclose(fp);
   
   return 0;
}

Здесь мы открываем файл ‘file.txt’ с помощью функции ‘fopen’, которая открывает файл в режиме чтения (‘r’). Затем мы используем цикл ‘while’, чтобы читать каждый символ из файла и выводить его на экран функцией ‘printf’. Наконец, мы закрываем файл с помощью функции ‘fclose’.

Шаг 7: Сборка программы

Когда программа написана, ее необходимо скомпилировать и собрать в единый исполняемый файл. Для этого мы можем использовать компилятор из командной строки. Вот пример команды для компиляции программы:

gcc program.c -o program

Здесь «program.c» — это имя файла с исходным кодом, «-o program» означает, что скомпилированная программа будет называться «program». После того, как программа успешно скомпилирована, ее можно запустить из командной строки:

./program

Заключение

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

Понравилась статья? Поделить с друзьями:
  • Haier hw70 bp12969a инструкция по эксплуатации на русском
  • Инструкция по перегонке самогона на ректификационной колонне
  • Инструкция таблеток кавинтон форте 10 миллиграмм
  • Гиллан глазные капли инструкция цена отзывы врачей
  • Руководства для жкх