Решения загадки: пишем код на русском языке

Вчера я задал небольшую загадку про то, как на C++ заставить компилироваться и правильно работать такой cpp файл:

НАЧАЛО ПРОГРАММЫ

Выведи текст на экран

начало текста
“Я помню чудное мгновенье: \n\
Передо мной явилась ты, \n\
Как мимолетное виденье, \n\
Как гений чистой красоты.”
конец текста

Выведи текст в файл “Стих.txt”

начало текста
“В томленьях грусти безнадежной\n\
В тревогах шумной суеты,\n\
Звучал мне долго голос нежный\n\
И снились милые черты.”
конец текста

КОНЕЦ ПРОГРАММЫ

Сегодня выкладываю свой ответ (весь код и проект для Visual Studio 2010 вы можете скачать отсюда).
Итак, понятно, что где-то должны быть #define, в которых должны быть прописаны ключевые слова, например:
#define НАЧАЛО int _tmain(int argc, _TCHAR* argv[]) {
#define КОНЕЦ }



Я для этого выбрал вариант с прописыванием .h файла в /FI (force include) опции компилятора. Эта опция заставляет компилятор автоматически добавить #include для указанного файла вначале каждого компилируемого файла в проекте.
Так что я написал DefinesRus.h и добавил в опции компилятора /FI DefinesRus.h .
Второй вариант, который можно было использовать - это задефайнить всё в опциях компилятора, используя -D name=definition, например, “-D КОНЕЦ=}”. Тогда можно вообще без .h файлов обойтись.


Вот сам мой DefinesRus.h:

#pragma once

#include <tchar.h>
#include <fstream>

#define НАЧАЛО int _tmain(int argc, _TCHAR* argv[]) {
#define ПРОГРАММЫ 
#define КОНЕЦ }

class OutputInterface
{
public:
	virtual void output(const char* text) = 0;
};

class OutputOnScreen : public OutputInterface
{
public:
	void output(const char* text)
	{
		printf("%s", text);
	}
};

class OutputToFile : public OutputInterface
{
	const char* mFileName;
public:
	OutputToFile(const char* fName) : mFileName(fName) {};
	void output(const char* text)
	{
		std::ofstream f(mFileName);
		f << text;
	}
};

class Outputter
{
	OutputInterface* mRealOutput;
	const char* mText;
public:
	Outputter(OutputInterface* realOutputter, const char* text) : mRealOutput (realOutputter), mText(text) {}
	~Outputter() {mRealOutput->output(mText);}
};

#define UNIQUE_NAME_HELPER(a,b) a ## b
#define _UNIQUE_NAME_HELPER(a, b) UNIQUE_NAME_HELPER(a,b)
#define UNIQUE_NAME(a) _UNIQUE_NAME_HELPER(a, __COUNTER__)

#define Выведи Outputter 
#define текст UNIQUE_NAME(text)(
#define на 
#define в
#define экран new OutputOnScreen(
#define файл new OutputToFile(
#define начало ),
#define конец );
#define текста

Мой вариант не использует никакой черной магии и позволяет легко расширять программу - легко добавить, например, вывод на принтер, создав OutputToPrinter и породив его от OutputInterface. Далее надо будет добавить #define ПРИНТЕР new OutputToPrinter(. И всё.
После этого можно писать ВЫВЕДИ ТЕКСТ НА ПРИНТЕР и он выведется.
Про читабельность и простоту решения - решать вам.

Я получил 3 работающих варианта с решением этой загадки: от Bright (самое первое решение), от Олександр Єфремов и от некоего nobody. :)
Именно вариант nobody понравился мне лично больше всего. Вариант очень короткий, хотя там используется “черная магия”, чего я обычно не люблю.
Вариант от Олександр Єфремов тоже хорош. Там тоже используется черная магия и __iob_func.


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

НАЧАЛО

ЗАГАДАЙ СЛУЧАЙНОЕ ЧИСЛО X ОТ 1 ДО 100 ВКЛЮЧИТЕЛЬНО

ПОКА ЧИСЛО X НЕ УГАДАНО
    ВЫВЕДИ НА ЭКРАН "ВВЕДИТЕ ЧИСЛО ОТ 1 до 100:"
    ЖДАТЬ ВВОДА ЧИСЛА Y
    ЕСЛИ Y РАВНО X ТО
        ВЫВЕДИ  НА ЭКРАН "Поздравляю, вы угадали число"
        ЗАВЕРШИТЬ
    ИНАЧЕ
       ЕСЛИ Y БОЛЬШЕ X ТО ВЫВЕДИ НА ЭКРАН "Загаданное  число меньше" ИНАЧЕ ВЫВЕДИ НА ЭКРАН "Загаданное число больше".
       ВЫВЕДИ НА ЭКРАН "Попробуйте еще раз!"
       ПРОДОЛЖАЙ УГАДЫВАТЬ

КОНЕЦ

Этот код тоже будет компилироваться и работать! Дерзайте.

6 комментариев к Решения загадки: пишем код на русском языке

Ответить

 

 

 

Вы можете использовать эти HTML тэги

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>