Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.222.200.143] |
|
Страницы: (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
,
|
|
|
Неприемлемо. Ты переписал пример на другом языке.
|