Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.119.116.43] |
|
Страницы: (32) « Первая ... 17 18 [19] 20 21 ... 31 32 ( Перейти к последнему сообщению ) |
Сообщ.
#271
,
|
|
|
Зачем? Мне религия все позволяет, а вот тебе похоже как раз религия и запрещает goto
|
Сообщ.
#272
,
|
|
|
Цитата applegame @ Мне религия все позволяет, а вот тебе похоже как раз религия и запрещает goto верно |
Сообщ.
#273
,
|
|
|
Славян, я уже не очень хорошо помню, но по-моему примерно как-то так я в бейсике и делал процедуры. Под какой-то вариант спектрума, со встроенным бейсиком.
Добавлено А, нет, наврал. Не заметил, что у тебя в разные места возвращается. Так я вроде не извращался. |
Сообщ.
#274
,
|
|
|
Цитата D_KEY @ Я сначала в одно место возвращался, но увидел, что тот блок можно тогда было бы засунуть вместо goto, а потому пришлось придумать 2 места возврата. у тебя в разные места возвращается. Так я вроде не извращался. |
Сообщ.
#275
,
|
|
|
Цитата Qraizer @ Предполагается-то ведь, что прерывание исполнения и сохранение состояние с последующим восстановлением состояния и продолжением исполнения суть очень редкая операция. Зачем делать лишние движения на каждой итерации ради исчезающе малого процента ситуаций, их обосновывающих? Этот момент не понял. Разве не в обоих случаях необходимость восстановления состояния проверяется один раз (до входа в цикл)? Прерывание, опять же, в обоих вариантах проверяется в каждой итерации, да и как иначе. Аргумент в духе "я это реально писал, было сложно", извини, но не убеждает. С таким же успехом, могла быть обратная ситуация - в смысле долго и мучительно переделывать на вариант с goto. Потому что я в упор не вижу, что тут goto помогает выиграть. Ну да ладно, это не слишком интересный спор. |
Сообщ.
#276
,
|
|
|
Цитата DarkEld3r @ Цитата Qraizer @ Предполагается-то ведь, что прерывание исполнения и сохранение состояние с последующим восстановлением состояния и продолжением исполнения суть очень редкая операция. Зачем делать лишние движения на каждой итерации ради исчезающе малого процента ситуаций, их обосновывающих? Этот момент не понял. Разве не в обоих случаях необходимость восстановления состояния проверяется один раз (до входа в цикл)? Нет. Во втором случае еще приходится работать особым образом с счетчиками. |
Сообщ.
#277
,
|
|
|
Да, был невнимателен. В принципе, это своеобразное подтверждение, что с goto тут всё-таки нагляднее. Хотя я бы всё равно не сказал, что так уж сильно.
|
Сообщ.
#278
,
|
|
|
Как говорится не прошло и пол-года ...
Сижу-бодаюсь об "оплюсовывании" либы libssh2 в плане SFTP-функционала. Наверное тру-прогеры скажут, мол не парься, бери QStateMachine. Может это будет даже по-фэншую. Но задача практическая, время горит, а мне нужен только upload и download, и пока даже без чтений каталогов, атрибутов и прочего. К чему я это все? Прогаю в стиле самой либы (а она си-шная), безбожно тягаю куски кода из примеров. И вот пришло время нормальной обработки ошибок ... и вспомнил я эту тему. Сперва ступор, ну как-же тут без goto?!! Наваял процедуру, потестил, погонял, ну супер - работает. Да есть goto, стыдно - но есть, получилось вот-так: Скрытый текст // ───────────────────────────────────────────────────────────────────────────────────────────────── // 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вич. Но возникло немотивированное отвращение. И тут на помощь пришла лямбда, правда пришлось еще объявление метода чуть поправить. Получилось вот так: Скрытый текст // ───────────────────────────────────────────────────────────────────────────────────────────────── // 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! |
Сообщ.
#279
,
|
|
|
JoeUser, что за бред? Пос++оны освобождают ресурсы в деструкторах
|
Сообщ.
#280
,
|
|
|
Цитата korvin @ Пос++оны освобождают ресурсы в деструкторах Ага! Давай начинай мне советовать эту портянку с линейным выполнением переписать в 9 классов! |
Сообщ.
#281
,
|
|
|
Цитата korvin @ JoeUser, что за бред? Пос++оны освобождают ресурсы в деструкторах Ну да! На крайняк можно юзнуть деструктор смарт поинтера, например там: https://ideone.com/GALIGw #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 не надо. |
Сообщ.
#282
,
|
|
|
Цитата Wound @ auto socket = std::unique_ptr<int, decltype(socket_cleanup)>(new int() .................. Это реально читабельнее goto? И мне для этого обязательно кучу дергать? Кроме зашкаливающей ненависти к goto я не вижу тут профита. |
Сообщ.
#283
,
|
|
|
Если ты не видишь разницы между этим кодом и своим с goto, а так же если ты не видишь профита, то тут бессмысленно что либо объяснять. Пусть тебе кто то другой растолкует. Мне лень расписывать основы.
|
Сообщ.
#284
,
|
|
|
Договорились! Peace!
|
Сообщ.
#285
,
|
|
|
Цитата JoeUser @ Это реально читабельнее goto? К слову - этот вопрос тебе нужно адресовать тем кто сидит в комитете по стандартизации. Спроси у них, какого хера - они из С++ делают какое то вырвиглазное говно, на котором нельзя нормально писать читабельный код, что его даже не осиливают люди с 20тилетним стажем, теряются в двух строчках шаблонных параметров. Понавводили тут панимаешь ли, всякие вариадики, лямбды... |