
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.3] |
![]() |
|
Страницы: (12) « Первая ... 2 3 [4] 5 6 ... 11 12 все ( Перейти к последнему сообщению ) |
Сообщ.
#46
,
|
|
|
Цитата Qraizer @ Ещё он писался в несколько приёмов и отлаживался. С goto написалось с первого раза и заработало без отладки. А зачем тогда проектировать всякие идиомы, патерны? Можно и без них ведь все написать с первого раза не отлаживаясь, в одной функции main с помощью всяких goto, главное блок схему нарисовать, чтоб не запутаться потом ![]() |
![]() |
Сообщ.
#47
,
|
|
Далеко не уверен. Как должны выглядеть примеры, я уже говорил выше. Я как-то натыкался на такой вопрос MS-ному блогеру, мол, почему у вас в примерах постоянно memset() для инициализации структур вместо простого = {0}, на что был получен ровно такой же ответ. Во-первых, = {0} легко пропустить и не заметить при чтении, в результате код, адаптированный читателем под свои нужды, с большей вероятностью будет содержать ошибку. Во-вторых, читатель может писать на каком-нибудь VB или Turbo Pascal for Windows и C читает со словарём, поэтому memset() не поймёт если, то пойдёт читать справку, а нагуглить = {0} ему будет куда сложнее. В результате у них было принято в примерах MSDN писать всё максимально линейно и топорно, и неважно, что пример при этом разрастётся в разы по объёму.
Добавлено Я ожидал такой реакции. Как это по-интернетному: прочитать эпиграф и закрыть книгу. Добавлено Ты язык поменял. Если б я писал на C++, я б написал ![]() ![]() bool copyFile(const char* src, const char* dst) { std::vector<char> buf(BUF_SIZE); std::ifstream inF(src); std::ofstream ouF(dst); if (inF.is_open()) return false; if (ouF.is_open()) return false; inF.read(&buf.front(), buf.size()); while (inF.good()) || inF.eof() && inF.gcount() != 0) { ouF.write(&buf.front(), inF.gcount()); if (ouF.pcount() != inF.gcount()) return false; inF.read(&buf.front(), buf.size()); } return true; } Хотя кого я обманываю: ![]() ![]() bool copyFile(const char* src, const char* dst) { std::ifstream inF(src); std::ofstream ouF(dst); if (inF.is_open()) return false; if (ouF.is_open()) return false; ouF << inF.rdbuf(); return ouF.pcount() == inF.gcount(); } |
Сообщ.
#48
,
|
|
|
Цитата Qraizer @ Я ожидал такой реакции. Как это по-интернетному: прочитать эпиграф и закрыть книгу. Дело в том, что я ожидал увидеть не обсирание goto K&R, а конкретно описание какого нибудь паттерна. Ну что то типа - "Все ругают goto за то то и за то то. Но! Есть один паттерн, в реализации которого goto просто не заменимая вещь. И так рассмотрим пример...". Но ты привел как раз ссылку на то что "Все кругом злоупотребляют goto, и вообще он полный оцтой, и всегда можно обойтись без него, тем не менее, ща мы вам покажем пару вещей, где в принципе - если лень что то писать, можно и обойтись goto, с кучей оговорок...". Например чуваки тут от нефиг делать пишут эмуляцию RAII и исключений на С, и как то обходятся без goto -> https://github.com/psevon/exceptions-and-raii-in-c А вы пытаетесь отмазать применение goto, даже там, где ему вообще не место. |
![]() |
Сообщ.
#49
,
|
|
Цитата KILLER @ Ну так прочти следующие два предложения Но ты привел как раз ссылку на то что "Все кругом злоупотребляют goto, и вообще он полный оцтой, и всегда можно обойтись без него, тем не менее, ща мы вам покажем пару вещей, где в принципе - если лень что то писать, можно и обойтись goto, с кучей оговорок...". ![]() К тому же в цитате написано "почти всегда", ты, видимо, пропустил. Случайно. |
Сообщ.
#50
,
|
|
|
Цитата Qraizer @ Ты язык поменял. Если б я писал на C++, я б написал Ну например на гцц есть такая штука -> http://echorand.me/site/notes/articles/c_c...ttribute_c.html Пример взят по ссылке выше: ![]() ![]() # include <stdlib.h> # include <stdio.h> # define TMP_FILE "/tmp/tmp.file" void free_buffer(char **buffer) { printf("Freeing buffer\n"); free(*buffer); } void cleanup_file(FILE **fp) { printf("Closing file\n"); fclose(*fp); printf("Deleting the file\n"); remove(TMP_FILE); } int main(int argc, char **argv) { char *buffer __attribute__ ((__cleanup__(free_buffer))) = malloc(20); FILE *fp __attribute__ ((__cleanup__(cleanup_file))); fp = fopen(TMP_FILE, "w+"); if (fp != NULL) fprintf(fp, "%s", "Alinewithnospaces"); fflush(fp); fseek(fp, 0L, SEEK_SET); fscanf(fp, "%s", buffer); printf("%s\n", buffer); return 0; } Я работал с apache там ЕМНИП это уже реализовано из каропки. Но я на чистом С уже не писал лет 5. Если бы я на нем писал, я бы давно уже написал себе пару вспомогательных функций конкретно для работы с ресурсами в стиле RAII. Сейчас у меня попросту нет времени, переделывать и переписывать ваши примеры. Добавлено Цитата Qraizer @ К тому же в цитате написано "почти всегда", ты, видимо, пропустил. Случайно. Нет не пропустил. И даже выше я в принципе соглашался с использованием goto в качестве костылей, когда переписать правильно нет времени. Добавлено Цитата Qraizer @ Ну так прочти следующие два предложения ![]() А я именно от туда и процитировал свою фразу, если ты не понял ![]() И ниже они пишут: Цитата Хотя мы не являемся в этом вопросе догматиками, нам все же кажется, что если и нужно использовать оператор GOTO, то весьма умеренно. То что пишите вы - не похоже на весьма умерено, это больше похоже на "как правило", особенно если рассматривать это как паттерн. |
Сообщ.
#51
,
|
|
|
Во-первых, пишите на C++. Хотя бы из-за RAII. Исключения и RTTI можно отрубить.
Во-вторых, даже если вы пишите на C, рассмотрите варианты с __finally для ms-компилятора и __attribute__ ((__cleanup__(f))) для gcc/clang. В-третьих, если таки "чистый Си", то смотрите по обстоятельствам. Иногда действительно без goto получается больше говнокода. Но злоупотреблять не стоит. Мне кажется, что большинство с этим согласится, нет? О чем спор? |
Сообщ.
#52
,
|
|
|
Цитата D_KEY @ О чем спор? О том, что майкрософт пишет говнокод и злоупотребляет #define/goto. Мне доказывают что они не пишут говнокод, а goto - нужен для реализации патерна обработки ошибок и клинапа. А я с ними не согласен. Привожу по моему мнению говнокод из ATL/MFC/SDK/MSDN - а мне доказывают что это не говнокод, а хороший, удобочитаемый код. Вот об этом спор. |
![]() |
Сообщ.
#53
,
|
|
Нет, KILLER. Тебе доказывают, что любая крайность – это плохо. Неважно, на каком краю эта крайность.
Добавлено P.S. Если ты не обратил внимание. Я нигде на примеры из продакшн кода не говорил, что так и надо, но говорил за примеры в MSDN. А почему так в продакшн, не знаю. Может быть код писался в расчёте на слабо оптимизирующие компиляторы с плохо оптимизированными RTL, технологиям ATL и MFC в обед сто лет исполняется. И тем не менее не считаю это смертельным. т.к. код соответствует патерну обработки ошибок. |
Сообщ.
#54
,
|
|
|
Цитата Qraizer @ Тебе доказывают, что любая крайность – это плохо. Неважно, на каком краю эта крайность. Ну так объясни мне, зачем в ATL/MFC майкрософт юзает паттерн с goto, вместо идиомы RAII? И злоупотребляет дефайнами? Там что классов нет? Цитата Qraizer @ Я нигде на примеры из продакшн кода не говорил, что так и надо, но говорил за примеры в MSDN. Дак у них в MSDN с классами - ровно то же самое. Конечно можно отмазаться сказать - это всего лишь справка, и вообще похер как там написано. Они наняли отдельных индусов, которые занимаются исключительно написанием семплов для SDK/MSDN и в прод они не лезут. Ну и что бы я тогда возразил? Я бы скорее всего согласился что наверное так и есть. Цитата Qraizer @ Может быть код писался в расчёте на слабо оптимизирующие компиляторы с плохо оптимизированными RTL, технологиям ATL и MFC в обед сто лет исполняется. И тем не менее не считаю это смертельным. т.к. код соответствует патерну обработки ошибок. Угу, в то время - когда можно обойтись RAII. |
![]() |
Сообщ.
#55
,
|
|
Цитата KILLER @ Я его начал мотать по твоей ссылке, не выдержал нажал поиск, первый же встретившийся goto - посмотри на саму функцию, ее по хорошему уже можно было только разбить на 3-4 функций. Зачем такие большие функции писать? И зачем разбивать? Функция с "первым же встретившится goto" предельно понятна. Начал переписывать, не поняв, какую проблему решает goto, очевидно ![]() Да ладно. Ну вот тебе ещё примеры из ядра линукса, git, quake 3. Дальше искать влом. Но, ты, конечно, можешь считать, что авторы всех этих программ - дебилы и говнокодеры, не догадавшиеся, что можно было просто обратиться к KILLER-у с исходников с вопросом "как переписать без goto" - я спорить с этим даже не буду ![]() О чём ты? Ты вполне себе ограничен - религиозной заморочкой "писать код без goto", которая, очевидно, мешает в определённых случаях писать более компакнтный и читаемый код ![]() Перепиши. Вот зуб даю - если у тебя получится не хуже, чем с goto, то тебе тут не только я - половина участников темы плюсы поставит. От себя вообще три плюса обещаю ![]() И что? Или ты не заметил, что тут решается задача "запрыгнуть внутрь циклов", и это не goto cleanup, смысла котоого в плюсах немного? ![]() |
Сообщ.
#56
,
|
|
|
Цитата OpenGL @ Перепиши. Вот зуб даю - если у тебя получится не хуже, чем с goto, то тебе тут не только я - половина участников темы плюсы поставит. От себя вообще три плюса обещаю ![]() Ну честно говоря тот код вряд ли прошел бы pull request во всех компаниях/командах где я работал ![]() А в чем суть задачи? |
![]() |
Сообщ.
#57
,
|
|
Цитата D_KEY @ А в чем суть задачи? Цитата OpenGL @ Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были). |
![]() |
Сообщ.
#58
,
|
|
Сначала думал примерами. Потом подумал, начнут обсуждать примеры вместо сабжа. Но теперь всё-таки думаю, что надо было примерами... Простейший случай ![]() ![]() #define MACROMAX(x,y) \ ((x < y)?y:x) ![]() ![]() template <typename T1, typename T2> T1 templatemax(T1 x, T2 y) { return (x < y)?y:x; } И пример использования.. ![]() ![]() float a = 123.76; double b = 123.04; float c = 125.15; int d; double e; d = MACROMAX(a, b); d = MACROMAX(a, c); e = templatemax(a, b); d = templatemax(a, c); См. выше. добавлю к первому посту ![]() Что касается #define vs const, то это был один из следующих запланированных опросов... опережаете события! Добавлено Кстати. Отличный пример ![]() |
Сообщ.
#59
,
|
|
|
Нашел ту тему, там даже мои варианты были. Вот два из них:
Цитата D_KEY @ ![]() ![]() int i = 0, j = 0, k = 0; restore(&i, &j, &k); for(; i < 10; ++i, j = i, k = j) { for (; j < 10; ++j, k = j) { for(; k < 10; ++k) { // ... } } } Цитата D_KEY @ Есть еще вариант со switch ![]() Не проверял, мог опечататься ![]() ![]() int i = 0, j = 0, k = 0; switch (restore(&i, &j, &k)) case 0: for(i = 0; i < 10; ++i) { for (j = i; j < 10; ++j) { for(k = j; k < 10; ++k) { default: // ... } } } } Сам я в той теме считал вариант с goto более понятным. |
Сообщ.
#60
,
|
|
|
Неприемлемо. Ты переписал пример на другом языке.
|