Forum.iFiction.Ru

iFiction.Ru · ifHub · FAQ · IFWiki · QSP · URQ · INSTEAD · AXMA

форум об interactive fiction, текстовых приключенческих играх и всём таком...

Вы не зашли.

0    0    #1
17.08.2007 21:38

uux
Участник (+887, -80)
Откуда: Москва
Зарегистрирован: 02.12.2006
Сообщений: 1625

Великий и могучий Гоуту Неубиваемый

Тут перевод TADS-мануала неожиданно натолкнул меня на мысль: что может заставить современнх программистов использовать оператор безусловного перехода a.k.a. goto? Речь, естественно, идет не о программировании на Ассемблере, Fortran 66 и т. п., а о более-менее структурированных языках, позволяющих теоретически вообще без него обойтись. Обращаюсь к программистам среди наших форумчан (их, к счастью, есть у нас:): пользуетесь ли вы оператором goto и в каких целях?

Начну, как положено, с себя. Я goto пользуюсь, пожалуй, исключительно при программировании на Visual Basic for Applications. Делаю это по следующим причинам: во-первых, ряд процедур удобнее генерировать при помощи встроенных "визардов", а они их генерят как раз с активным использованием goto. Править каждый раз такую процедуру вручную, убирая goto - значит сводить на нет все преимущества автоматизации;). Во-вторых, безусловный переход на метку в VBA удобно использовать при проверке на возникновение ошибки. В этом случае все обработчики ошибок локализуются в конце процедуры, что делает код в целом более читаемым. И, хотя теоретически подобной группировки можно добиться и другими средствами (и, например, программируя на Паскале, я бы совершенно точно организовал такую группировку без goto), в VBA такой способ кажется почему-то наиболее естественным и удобным.

Отредактировано uux (17.08.2007 21:40)

Неактивен

0    0    #2
18.08.2007 00:06

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Один мой коллега с работы (все пишут на C/C++) очень любит использовать goto. Причем, никто его не заставляет. А даже наоборот, уговаривают не использовать. Но не помогают даже угрозы. Ну не может человек мыслить структурно. Научился программировать во времена ассемблера, с этим и остался. Его исходники никто не трогает, и вникать в них не возьмётся. Вот такая страшная история. %)

Неактивен

0    0    #3
26.08.2007 22:44

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Товарищи, если мне не изменяет память, то изначальная тема топика была о целесообразности использования оператора безусловного перехода goto в СТРУКТУРНЫХ языках программирования (речь шла о ТАДС). Коим не являются машинный код или ассемблер. Какой машинный код генерирует компилятор языка -- сугубо на совести компилятора. Язык -- это абстракция от машинного кода.

Моё мнение: goto в структурных языках не нужен. За 8 лет работы программистом (даже раньше, когда я перестал писать на Басике и Ассемблере) я ни разу не использовал оператор goto, и даже сейчас не могу представить случая, где его действительно стоит использовать. Наверное, сказывается уход от императивного программирования (вся программа -- большой main() ).

"Язык определяет то, о чём мы можем мыслить". Это из предисловия какой-то книги о программировании, может быть даже Страуструпа, не помню. Человек, изо дня в день программирующий только на ассемблере не найдёт общего языка с человеком, пищущим на Луа. smile

Пример из Кернигана и Ричи на языке C++ решается с помощью предназначенного для этого механизма исключений (exceptions). На худой конец, можно обойтись разбиением на функции, так, чтобы goto превратился в return. Я лично не люблю перебарщиваний и запихивания длиннющего алгоритма в одну функцию. Хорошее разбиение на функции только улучшает читабельность программы.

Кстати, для общего развития. Программистам на C/C++ будет интересно. http://digitalmars.com/d/overview.html

Язык D. Выглядит очень вкусно, захлебнулся слюной. Есть компилятор для Линуха.

Отредактировано Gremour (26.08.2007 22:58)

Неактивен

0    0    #4
27.08.2007 20:09

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

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

uux написал:

А как реализовать поэлегантнее пример Олегуса со вложенными условиями без goto?

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

Отредактировано Gremour (27.08.2007 20:18)

Неактивен

0    0    #5
27.08.2007 20:17

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Sfunx написал:

Там голый С, без ++. Кстати, системные вещи на голом С пишутся.

Критические места можно написать на ассемблере. А вообще, компиляторы языка C++ умные программы, и генерят отличный код, особенно с включенной оптимизацией. Глупо писать драйвер устройства на классах, где они вообще не нужны. Но использовать компилятор языка C++ (который включает в себя язык C) никто не мешает.

Неактивен

0    0    #6
29.08.2007 18:59

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

zerrr написал:

Сужу по РТАДС - я делал там набросок 6 локаций и пары-тройки пазлов : занял процесс около 2 дней, при том, что в программировании я абсолютный ноль

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

(R)TADS мне очень нравится как система. Но. Библиотека нуждается в доработке (а точнее полной переработке). И, возможно, стоит взять одну из нестандартных библиотек. Иногда очень не хватает некоторых имплементаций, которые нужны практически в любой игре.

Но это уже совсем не про Гоуту. smile

Неактивен

0    0    #7
03.09.2007 14:15

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Olegus t.Gl. написал:

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

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

И странно, что никто не поднял тему досрочного выхода из процедуры/функции: return, в середине «тела» процедуры/функции. Разве это не из этой же серии?..

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

(Кстати, множественными return'ами я лично пользуюсь постоянно).

Неактивен

0    0    #8
03.09.2007 17:26

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Eten: вот тебе функция (is_decimal) разбора десятичного числа на языке C (почти). Без goto. Решение в лоб. Иногда самое лучшее smile

Код:

//---------------------------------------------------------------------------

bool is_digit (char c)  // Является ли символ цифрой?
{
    return c >= '0' && c <= '9';
}

//---------------------------------------------------------------------------

bool is_exp (char c)   // Является ли символ значком экспоненты?
{
    return c == 'e' || c == 'E';
}

//---------------------------------------------------------------------------

double read_number (char **p) // Чтение целого числа из строки
{                             // (переводит стоящие подряд цифры в число)
    double res = 0;
    while (is_digit (**p))
    {
        res = res * 10 + (double) (**p - '0');
        (*p)++;
    }
    return res;
}

//---------------------------------------------------------------------------

double read_fraction (char **p) // То же, что и read_number, только
{                               // результат = число после запятой
    double res = 0;
    double multiplier = 1; 
    while (is_digit (**p))
    {
        multiplier *= 0.1;
        res = res  + multiplier * (double) (**p - '0');
        (*p)++;
    }
    return res;
}

//---------------------------------------------------------------------------

bool is_decimal (char *p)   // Чтение десятичного числа из строки.
                            // Возвращает признак успешности перевода строки в число
{
    double int_part = 0;    // Если нужно -- можно вычислить само число
    double frac_part = 0;   // result = (int_part + frac_part) * 10 ^ exponent
    double exponent = 0;    //
    double exp_sign = 1;
    bool int_read = false;

    if (is_digit (*p))      // Число может начинаться с цифры: 123
    {
        int_part = read_number (&p); // Тогда читаем целую часть
        int_read = true;
        if (!*p)
            return true;        // Конец строки -- разбор успешный
    }
    else
        if (*p != '.')      // Или с точки: .456
            return false;   // Иначе ошибка

    // Целая часть ушла. Осталась либо точка, либо 'E'

    if (*p == '.')          // Если точка
    {
        p++;                // Пропускаем точку
        if (!*p)
            return int_read; // Конец строки -- разбор успешный, если была целая часть
    }
    else
        if (!is_exp (*p))  // Не 'E'?
            return false;  // Значит ошибка

    if (is_digit (*p))  // Далее дробная часть: xxx.456
    {
        frac_part = read_fraction (&p); // Читаем дробную часть
        if (!*p)
            return true;    // Конец строки -- разбор успешный
        if (!is_exp (*p))
            return false;   // Может остаться только 'E'
    }

    p++;                    // Пропускаем 'E'
    if (*p == '+' || *p == '-') // После 'E' может быть знак
    {
        exp_sign = (*p == '+'? 1 : -1);
        p++;                    // Пропускаем знак
    }

    if (!is_digit (*p))     // Далее обязательно порядок (цифра)
        return false;

    exponent = read_number (&p) * exp_sign; // Читаем порядок
    if (*p)                 // На этом строка должна закончиться
        return false;

    return true;            // Перевод успешный
}

//---------------------------------------------------------------------------

Если я не допустил ошибки, разбирает любую валидную вариацию десятичного числа.

А твоя программа, кстати, что говорит на число 1.e1?

Отредактировано Gremour (03.09.2007 17:57)

Неактивен

0    0    #9
03.09.2007 17:52

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Eten: Да, кстати, цикл по большому счёту только один smile

Неактивен

0    0    #10
03.09.2007 17:54

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Olegus t.Gl. написал:

Постоянно натыкаюсь на довод о читабельности, однако, народ, что вы в это вкладываете? Если взять не элегантные примеры на десяток-полтора строк, а многоэкранные листинги, то сказать, куда произойдёт переход, будет проще с goto (с его чётким указанием меток), чем если разбираться со вложенными if, for и т.п. Я уж не говорю, что придётся разгребать разного рода допонительные конструкции: флаги условия и прочее. Интересен вопрос в плане раскрытия смысла термина "читабельность"…

Вообще я сам противник вложенностей 10-го колена. Разобраться без пол-литра в этом сложно. И текст уезжает за экран. %) Такие вещи лучше разбивать на функции. 2-3 вложенности максимум.

Неактивен

0    0    #11
05.09.2007 15:46

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

Я решал поставленню задачу. Без вычисления самого числа программа будет еще проще (можно легко модифицировать), но я решил, что число всё же нужно. Если не учитывать все варианты написания числа (вроде 1.e1) опять же алгоритм будет короче. Но почему бы их не учесть? Это вроде бы как стандарт, любой компилятор C++ понимает разные валидные вариации сокращения формы десятичного числа (опустить ноль до или после точки, опустить знак экспоненты).

Неактивен

0    0    #12
05.09.2007 18:26

Gremour
Участник (+1)
Откуда: Беларусь
Зарегистрирован: 09.11.2004
Сообщений: 234

Re: Великий и могучий Гоуту Неубиваемый

.12 читается как 0.12
34. читается как 34.0

1.e1, соответственно, равно десяти.

Хотя, если для системы нет разницы, целое число или нет, то можно на этом не заостряться. В C/C++ описание "34." даёт компилятору информацию о том, что указанная константа в дробном формате.

Если смотреть с общечеловеческой :) позиции, то алгоритм можно упростить, пропуская только формат с цифрами по обе стороны от точки (если точка есть).

Отредактировано Gremour (05.09.2007 18:32)

Неактивен

Powered by PunBB
© copyright 2001–2026 iFiction.Ru