На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (32) « Первая ... 17 18 [19] 20 21 ...  31 32  ( Перейти к последнему сообщению )  
> goto vs break & continue , Кроха-сын пришел к отцу и спросила кроха: "goto - это хорошо?"
    Цитата Serafim @
    передать в качестве аргументов не позволяет религия?
    Зачем? Мне религия все позволяет, а вот тебе похоже как раз религия и запрещает goto :)
      Цитата applegame @
      Мне религия все позволяет, а вот тебе похоже как раз религия и запрещает goto

      верно :yes:
        Славян, я уже не очень хорошо помню, но по-моему примерно как-то так я в бейсике и делал процедуры. Под какой-то вариант спектрума, со встроенным бейсиком.

        Добавлено
        А, нет, наврал. Не заметил, что у тебя в разные места возвращается. Так я вроде не извращался.
          Цитата D_KEY @
          у тебя в разные места возвращается. Так я вроде не извращался.
          Я сначала в одно место возвращался, но увидел, что тот блок можно тогда было бы засунуть вместо goto, а потому пришлось придумать 2 места возврата. :blush:
            Цитата Qraizer @
            Предполагается-то ведь, что прерывание исполнения и сохранение состояние с последующим восстановлением состояния и продолжением исполнения суть очень редкая операция. Зачем делать лишние движения на каждой итерации ради исчезающе малого процента ситуаций, их обосновывающих?

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

            Аргумент в духе "я это реально писал, было сложно", извини, но не убеждает. С таким же успехом, могла быть обратная ситуация - в смысле долго и мучительно переделывать на вариант с goto. Потому что я в упор не вижу, что тут goto помогает выиграть. Ну да ладно, это не слишком интересный спор.
              Цитата DarkEld3r @
              Цитата Qraizer @
              Предполагается-то ведь, что прерывание исполнения и сохранение состояние с последующим восстановлением состояния и продолжением исполнения суть очень редкая операция. Зачем делать лишние движения на каждой итерации ради исчезающе малого процента ситуаций, их обосновывающих?

              Этот момент не понял. Разве не в обоих случаях необходимость восстановления состояния проверяется один раз (до входа в цикл)?

              Нет. Во втором случае еще приходится работать особым образом с счетчиками.
                Да, был невнимателен. В принципе, это своеобразное подтверждение, что с goto тут всё-таки нагляднее. :D Хотя я бы всё равно не сказал, что так уж сильно.
                  Как говорится не прошло и пол-года ...

                  Сижу-бодаюсь об "оплюсовывании" либы libssh2 в плане SFTP-функционала. Наверное тру-прогеры скажут, мол не парься, бери QStateMachine. Может это будет даже по-фэншую. Но задача практическая, время горит, а мне нужен только upload и download, и пока даже без чтений каталогов, атрибутов и прочего. К чему я это все? Прогаю в стиле самой либы (а она си-шная), безбожно тягаю куски кода из примеров. И вот пришло время нормальной обработки ошибок ... и вспомнил я эту тему.

                  Сперва ступор, ну как-же тут без goto?!! Наваял процедуру, потестил, погонял, ну супер - работает. Да есть goto, стыдно - но есть, получилось вот-так:
                  Скрытый текст
                  ExpandedWrap disabled
                    // ─────────────────────────────────────────────────────────────────────────────────────────────────
                    // sftp_class ► slotLogin
                    // ─────────────────────────────────────────────────────────────────────────────────────────────────
                    void mov::qt::sftp_class::slotLogin() {
                        struct addrinfo hint;
                        struct addrinfo *addrs;
                        struct sockaddr_in *sin;
                        const char *fingerprint;
                        struct addrinfo *p;
                        int ret;
                        bool found;
                        sftpError = sftp_error::no;
                        if (sftpState == sftp_state::ready && Auth->authState == auth_state::ok) {
                            // инициализация библиотеки
                            if (libssh2_init(0) != 0) {
                                sftpError = sftp_error::libssh2_error;
                                return;
                            }
                            // поиск адреса хоста
                            memset(&hint, 0, sizeof(hint));
                            hint.ai_flags = AI_NUMERICHOST;
                            hint.ai_family = AF_UNSPEC;
                            hint.ai_socktype = SOCK_STREAM;
                            hint.ai_protocol = IPPROTO_TCP;
                            ret = getaddrinfo(Host.toLocal8Bit().data(), NULL, &hint, &addrs);
                            if (ret == EAI_NONAME) {
                                hint.ai_flags = 0;
                                ret = getaddrinfo(Host.toLocal8Bit().data(), NULL, &hint, &addrs);
                            }
                            if (ret != 0)               {
                                sftpError = sftp_error::resolve_error;
                                goto cleanup_libssh2_init;
                            }
                            found = false;
                            for (p = addrs; p != nullptr; p = p->ai_next) {
                                if (p->ai_family == AF_INET) {
                                    found = true;
                                    sin = reinterpret_cast<sockaddr_in *>(p->ai_addr);
                                    break;
                                }
                            }
                            if (!found) {
                                sftpError = sftp_error::ip4_error;
                                goto cleanup_libssh2_init;
                            }
                            // создание сокета
                            sock = socket(AF_INET, SOCK_STREAM, 0);
                            if (sock == INVALID_SOCKET) {
                                sftpError = sftp_error::socket_error;
                                goto cleanup_libssh2_init;
                            }
                            sin->sin_family = AF_INET;
                            sin->sin_port = htons(Port);
                            // коннект
                            ret = ::connect(sock, (struct sockaddr *)(sin), sizeof(struct sockaddr_in));
                            if (ret != 0) {
                                sftpError = sftp_error::connect_error;
                                goto cleanup_socket;
                            }
                            // создание сессии
                            session = libssh2_session_init();
                            if (!session) {
                                sftpError = sftp_error::session_error;
                                goto cleanup_socket;
                            }
                            // установка баннера
                            if (libssh2_session_banner_set(session, "SSH-2.0-OpenSSH_LIBSSH2_1.9.0") != 0) {
                                sftpError = sftp_error::session_error;
                                goto cleanup_session;
                            }
                            // рукопожатие
                            if (libssh2_session_handshake(session, sock)) {
                                sftpError = sftp_error::handshake_error;
                                goto cleanup_session;
                            }
                            // перевод в неблокируемый режим
                            libssh2_session_set_blocking(session, 0);
                            // получение отпечатка
                            fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
                            // авторизация
                            if (Auth->authType == auth_type::login) {
                                while ((ret = libssh2_userauth_password(
                                                                session,
                                                                Auth->login.toLocal8Bit().data(),
                                                                Auth->password.toLocal8Bit().data()
                                                            ))   == LIBSSH2_ERROR_EAGAIN);
                                if (ret) {
                                    sftpError = sftp_error::auth_error;
                                    goto cleanup_session;
                                }
                            } else {
                                while ((ret = libssh2_userauth_publickey_frommemory(
                                                                session,
                                                                Auth->login.toLocal8Bit().data(),
                                                                Auth->login.length(),
                                                                Auth->public_array.data(),
                                                                Auth->public_array.size(),
                                                                Auth->private_array.data(),
                                                                Auth->private_array.size(),
                                                                Auth->password.toLocal8Bit().data()
                                                            )) == LIBSSH2_ERROR_EAGAIN);
                                if (ret) {
                                    sftpError = sftp_error::auth_error;
                                    goto cleanup_session;
                                }
                            }
                            // инициализация ftp-сессии
                            do {
                                sftp_session = libssh2_sftp_init(session);
                                if (!sftp_session) {
                                    if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)
                                        waitsocket(sock, session);
                                    else {
                                        sftpError = sftp_error::auth_error;
                                        goto cleanup_session;
                                    }
                                }
                            } while (!sftp_session);
                            // все четко и дерзко
                            sftpState = sftp_state::logged_in;
                            return;
                            // аварийная очистка
                        cleanup_session:
                            libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing!");
                            libssh2_session_free(session);
                        cleanup_socket:
                            #ifdef WIN32
                            closesocket(sock);
                            #else
                            close(sock);
                            #endif
                        cleanup_libssh2_init:
                            libssh2_exit();
                        }
                    }

                  Потом подумал, ну можно же без goto. А то посоны не поймут! Сперва пришло на ум - глобальный cвич. Но возникло немотивированное отвращение. И тут на помощь пришла лямбда, правда пришлось еще объявление метода чуть поправить. Получилось вот так:
                  Скрытый текст
                  ExpandedWrap disabled
                    // ─────────────────────────────────────────────────────────────────────────────────────────────────
                    // sftp_class ► slotLogin
                    // ─────────────────────────────────────────────────────────────────────────────────────────────────
                    bool mov::qt::sftp_class::slotLogin() {
                        struct addrinfo hint;
                        struct addrinfo *addrs;
                        struct sockaddr_in *sin;
                        const char *fingerprint;
                        struct addrinfo *p;
                        int ret;
                        bool found;
                        enum class cleanup_point {session, socket, libssh2, none};
                        auto cleanup = [&](cleanup_point p, sftp_error e)->bool {
                            sftpError = e;
                            switch (p) {
                                case cleanup_point::session:
                                    libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing!");
                                    libssh2_session_free(session);
                                case cleanup_point::socket:
                                    #ifdef WIN32
                                    closesocket(sock);
                                    #else
                                    close(sock);
                                    #endif
                                case cleanup_point::libssh2:
                                    libssh2_exit();
                                default:;
                            }
                            return false;
                        };
                        sftpError = sftp_error::no;
                        if (sftpState == sftp_state::ready && Auth->authState == auth_state::ok) {
                            // инициализация библиотеки
                            if (libssh2_init(0) != 0) return cleanup(cleanup_point::none, sftp_error::libssh2_error);
                            // поиск адреса хоста
                            memset(&hint, 0, sizeof(hint));
                            hint.ai_flags = AI_NUMERICHOST;
                            hint.ai_family = AF_UNSPEC;
                            hint.ai_socktype = SOCK_STREAM;
                            hint.ai_protocol = IPPROTO_TCP;
                            ret = getaddrinfo(Host.toLocal8Bit().data(), NULL, &hint, &addrs);
                            if (ret == EAI_NONAME) {
                                hint.ai_flags = 0;
                                ret = getaddrinfo(Host.toLocal8Bit().data(), NULL, &hint, &addrs);
                            }
                            if (ret != 0)   return cleanup(cleanup_point::libssh2, sftp_error::resolve_error);
                            found = false;
                            for (p = addrs; p != nullptr; p = p->ai_next) {
                                if (p->ai_family == AF_INET) {
                                    found = true;
                                    sin = reinterpret_cast<sockaddr_in *>(p->ai_addr);
                                    break;
                                }
                            }
                            if (!found) return cleanup(cleanup_point::libssh2, sftp_error::ip4_error);
                            // создание сокета
                            sock = socket(AF_INET, SOCK_STREAM, 0);
                            if (sock == INVALID_SOCKET) return cleanup(cleanup_point::libssh2, sftp_error::socket_error);
                            sin->sin_family = AF_INET;
                            sin->sin_port = htons(Port);
                            // коннект
                            ret = ::connect(sock, (struct sockaddr *)(sin), sizeof(struct sockaddr_in));
                            if (ret != 0) return cleanup(cleanup_point::socket, sftp_error::connect_error);
                            // создание сессии
                            session = libssh2_session_init();
                            if (!session) return cleanup(cleanup_point::socket, sftp_error::session_error);
                            // установка баннера
                            if (libssh2_session_banner_set(session, "SSH-2.0-OpenSSH_LIBSSH2_1.9.0") != 0)
                                return cleanup(cleanup_point::session, sftp_error::session_error);
                            // рукопожатие
                            if (libssh2_session_handshake(session, sock))
                                return cleanup(cleanup_point::session, sftp_error::handshake_error);
                            // перевод в неблокируемый режим
                            libssh2_session_set_blocking(session, 0);
                            // получение отпечатка
                            fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
                            // авторизация
                            if (Auth->authType == auth_type::login) {
                                while ((ret = libssh2_userauth_password(
                                                                session,
                                                                Auth->login.toLocal8Bit().data(),
                                                                Auth->password.toLocal8Bit().data()
                                                            ))   == LIBSSH2_ERROR_EAGAIN);
                                if (ret) return cleanup(cleanup_point::session, sftp_error::auth_error);
                            } else {
                                while ((ret = libssh2_userauth_publickey_frommemory(
                                                                session,
                                                                Auth->login.toLocal8Bit().data(),
                                                                Auth->login.length(),
                                                                Auth->public_array.data(),
                                                                Auth->public_array.size(),
                                                                Auth->private_array.data(),
                                                                Auth->private_array.size(),
                                                                Auth->password.toLocal8Bit().data()
                                                            )) == LIBSSH2_ERROR_EAGAIN);
                                if (ret) return cleanup(cleanup_point::session, sftp_error::auth_error);
                            }
                            // инициализация ftp-сессии
                            do {
                                sftp_session = libssh2_sftp_init(session);
                                if (!sftp_session) {
                                    if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)
                                        waitsocket(sock, session);
                                    else
                                        return cleanup(cleanup_point::session, sftp_error::auth_error);
                                }
                            } while (!sftp_session);
                            // все четко и дерзко
                            sftpState = sftp_state::logged_in;
                            return true;
                        }
                        return false;
                    }

                  Вроде и от goto избавился, и код стал короче ... но радости это не прибавило! :-? Читабельность стала хуже. И вот я подумываю вернуться к первой версии реализации слота. Ухожу я от вас, хейтеры goto! :lol:
                    JoeUser, что за бред? Пос++оны освобождают ресурсы в деструкторах
                      Цитата korvin @
                      Пос++оны освобождают ресурсы в деструкторах

                      Ага! Давай начинай мне советовать эту портянку с линейным выполнением переписать в 9 классов! :popcorn:
                        Цитата korvin @
                        JoeUser, что за бред? Пос++оны освобождают ресурсы в деструкторах

                        Ну да! На крайняк можно юзнуть деструктор смарт поинтера, например там: https://ideone.com/GALIGw
                        ExpandedWrap disabled
                              #include <iostream>
                              #include <memory>
                              
                              
                              void slotLogin()
                              {
                                  auto socket_cleanup = [](int* ptr){
                                      std::cout << "socket_cleanup is called" << std::endl;
                                  };
                              
                                  auto libssh2_init_cleanup = [](int* ptr){
                                      std::cout << "libssh2_init_cleanup is called" << std::endl;
                                  };
                              
                              auto socket = std::unique_ptr<int, decltype(socket_cleanup)>(new int()/*::connect(...)*/, socket_cleanup);
                              auto libssh2_init = std::unique_ptr<int, decltype(libssh2_init_cleanup)>(new int()/*libssh2_init(...)*/, libssh2_init_cleanup);
                           
                          /*...*/
                              }
                              
                              int main() {
                                  slotLogin();
                                  return 0;
                              }

                        И никаких goto не надо.
                        Сообщение отредактировано: Wound -
                          Цитата Wound @
                          auto socket = std::unique_ptr<int, decltype(socket_cleanup)>(new int() ..................

                          Это реально читабельнее goto? И мне для этого обязательно кучу дергать? :lol: Кроме зашкаливающей ненависти к goto я не вижу тут профита.
                            Если ты не видишь разницы между этим кодом и своим с goto, а так же если ты не видишь профита, то тут бессмысленно что либо объяснять. Пусть тебе кто то другой растолкует. Мне лень расписывать основы.
                            Сообщение отредактировано: Wound -
                              Договорились! :) Peace! :victory:
                                Цитата JoeUser @
                                Это реально читабельнее goto?

                                К слову - этот вопрос тебе нужно адресовать тем кто сидит в комитете по стандартизации. Спроси у них, какого хера - они из С++ делают какое то вырвиглазное говно, на котором нельзя нормально писать читабельный код, что его даже не осиливают люди с 20тилетним стажем, теряются в двух строчках шаблонных параметров. Понавводили тут панимаешь ли, всякие вариадики, лямбды... :lol:
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (32) « Первая ... 17 18 [19] 20 21 ...  31 32


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0669 ]   [ 14 queries used ]   [ Generated: 19.05.24, 13:11 GMT ]