1. C++ / Говнокод #12610

    +80

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    /* Попытка обьединить четыре  цикла в один.
    	Первый - Присвоение элементам массива значения.
    	Второй - Поиск минимального значения.
    	Третий - Поиск максимального значения.
    	Четвертый - Вывод содержимого массива.
    */
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    int main()
    {
    	int array[100];
    	int flag;
    	int min = 0;
    	int max = 0;
    
    	for (flag=0;flag<100;flag++){					   
    		array[flag]=rand();
    		
    		if ( ! min && ! max){	   //Инициализация переменных, для первой итерации.
    		max = array[0];
    		min = array[0];
    		}
    
    		if (array[flag] >=max) max = array[flag];
    		
    		if (array[flag] <= min) min = array[flag];
    		
    		cout << array[flag] << "\n";
    	}
    	
    	cout << "\nМаксимальное значение: " << max;	
    
    	cout << "\nМинимальное значение: "  << min << '\n';
    	
    	return 0;
    }

    Писал я, пытаясь переделать пример из книжки, в котором для этой же задачи использовалось 4 цикла.
    Просьба обьективно обгадить сей код, дабы мне было над чем подумать.

    P.S только учусь.

    Запостил: shim, 18 Февраля 2013

    Комментарии (41) RSS

    • >> if ( ! min && ! max)
      Замени на flag == 0
      ну и условия >= и <=, я бы заменил на > и <
      Ответить
    • >>if ( ! min && ! max){ //Инициализация переменных, для первой итерации.
      >> max = array[0];
      >> min = array[0];
      >>}
      В принципе это можно вытащить из цикла и цикл начинать с 1, но тогда перед циклом
      надо будет вставить,
      max = min = array[0]=rand();
      cout << array[0] << "\n";

      Будет экономия на спичках.
      Ответить
    • if (!min && !max) можно заменить на тупое, понятное и надежное if (!i).

      > Просьба обьективно обгадить сей код
      А зачем объединять 4 независимых куска? Обычно наоборот стараются разнести независимый код в разные функции. Тогда будет какой-никакой code-reuse - функции чтения, заполнения рандомом, поиска мин./макс, вывода массива можно будет применить в других лабах, а не писать каждый раз заново.

      > flag
      Какой же это флаг? Это ж счетчик.

      > using namespace std
      Отвыкайте, особенно в ашках ;)

      P.S. Придирка, конечно, но в строках 26, 28 не помешал бы перевод строки между условием и действием.
      Ответить
      • Если уж говорить о повторном использовании, то предлагаю отказаться от циклов, зато вернуть смысл массиву:
        int main() {
        	const size_t size = 100;
        	std::vector<int> arr(size);
        	std::srand(/*Some magic value here*/0);
        	std::generate(arr.begin(), arr.end(), std::rand);
        	auto min_max = std::minmax_element(arr.begin(), arr.end());
        	std::copy(arr.begin(), arr.end(), std::ostream_iterator<int>(std::cout, "\n"));
        	std::cout << "max: " << *min_max.second << std::endl;	
        	std::cout << "min: " << *min_max.first << std::endl;
        }
        Ответить
        • Шикарно! Даже не догадывался о существовании std::minmax_element()
          Наверное, если поискать ещё можно найти std::govnokod_solution(12610), который выполнит все необходимые действия.
          Ответить
          • >можно найти std::govnokod_solution(12610), который выполнит все необходимые действия.
            Полагаю для того MS и запилила LINQ.
            Ответить
          • Тут главная фишка в том, что за счет небольшой оптимизации алгоритмическая сложность снижается до 1.5N вместо 2N у отдельных вызовов min_element и max_element. Но на больших объемах реально minmax_element работает столько же времени, сколько один вызов min_element или max_element, за счет лучшей локальности по памяти, ведь вся работа делается за один проход.
            Ответить
    • >int flag;
      не нужно. создавай переменные таким образом, чтобы они жили как можно меньше. В этом случае flag после цикла не используется, поэтому ограничь его областью видимости цикла.

      > Попытка обьединить четыре цикла в один.
      к вышесказанному bormand'ом добавлю, что короткие циклы могут уместить к кэш процессора и несколько коротких отработать быстрее чем один длинный. В некоторых случаях(например opengl/directx) вообще сначала подготавливаются все данные, а потом они передаются функции для отрисовки.

      >int array[100];
      >for (flag=0;flag<100;flag++)
      запили константу для размера
      и в C++ используй C++ контейнеры, например, std::vector, std::array и тп. Смесь C и С++ выглядит нереально уродливо.

      >cout << "\nМаксимальное значение: "
      ЕМПЕН \n не всегда может означать переход строки; юзай std::endl()
      Ответить
      • разница между \n и std::endl (без скобок, причем) лишь в том, что последний дополнительно вызовет flush() потоку

        и что такое емпен? связано с люмпенами?
        Ответить
        • если моя память еще нормальна?
          Ответить
        • Вроде как у stdout/stderr по-умолчанию построчная буферизация в сишной библиотеке, поэтому printf("X/n"); должен быть практически эквивалентен std::cout << "X" << std::endl;
          Это я к тому, что с моей точки зрения, flush при работе с терминалом чаще полезен, чем вреден.
          Ответить
          • у вас слэш не туда наклонился
            Ответить
          • stderr вообще небуферизированный (в качестве примера можно написать многопоточное приложение, которое в каждом потоке параллельно подгаживает в stderr)
            stdout для \n самостоятельно флюшит буфер
            ну и кроме терминальных бывают еще потоки, которых иногда желательно флюшить вручную (в принципе, stdout тоже можно зафлюшить, не используя \n)
            но это всё оффтоп :)
            Ответить
            • >stderr вообще небуферизированный
              Странно, что stdlog при этом буферизированный.
              Ответить
              • странно, но твой стандарт сухой и совсем не пахнет (с)
                слово stdlog в имеющихся у меня REPLICA драфтах С и С++ упоминается ровно 0 раз
                Ответить
              • Если я правильно понимаю, плюсовые стандартные потоки совершенно параллельны сишным, и могут задавать свои настройки буферизации, т.к. не транслируются в операции с std{in,out,err}, а используют вызовы ядра. Т.е. clog, к примеру, может использовать для вывода тот же дескриптор, что и err, но иметь свой streambuf с построковой буферизацией.
                Ответить
            • >stdout для \n самостоятельно флюшит буфер
              Что значит самостоятельно?
              Ответить
              • Например то, что fwrite вызовет flush, если встретит \n при записи
                Ответить
              • When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered.

                так что, по идее, это задача рантайма, а не уровня ОС, следить за \n в line-buffered потоке, например, в stdout

                самостоятельно - в том смысле, что программист не вовлекается
                Ответить
                • Просто я наблюдаю, что std::cout не флашит при \n. Рантайм барахлит?
                  Ответить
                  • кажется, вы путаете stdout и std::cout
                    Ответить
                    • Так, а что такое std::cout - по сути плюсовый аналог для stdout. Не?
                      Ответить
                      • может имеет место вот такой случай?
                        http://liveworkspace.org/code/2bYbly$0
                        Ответить
                        • Я видимо не так прочитал/понял. У меня нет одновременного использования сишного stdout и плюсового std::cout.
                          Причудилось, что \n в std::cout должен флашить буфер.
                          Ответить
                          • ну вообще говоря, std::cout, являющийся обёрткой над stdout (ostream cout; The object cout controls output to a stream buffer associated with the object stdout, declared in <cstdio> (27.9.2).) с человеческой точки зрения должен работать ожидаемо - сбрасывать буфер по \n

                            но, видимо, на разных платформах это не так (видимо, речь идёт о хитрожопом поведении на g++/libstdc++) - наверное, кое-каким разработчикам, которым не платят зарплату за общественно полезную работу, было не с руки имитировать line-buffered в работе std::filebuf при получении \n - но, зато, потенциально std::cout работает на linux быстрее (что сложно замерить, т.к. основные тормоза в консольных приложениях под виндой явно не в рантайме, а в убогом эмуляторе cmd)
                            Ответить
                            • Надо погонять на виндузятине \n. А то я как раз gcc использую. Под QNX :)
                              Ответить
                              • мелкомягкие флашат на \n.
                                Ответить
                                • А на линухе в stdout, насколько помню, буферизация построчная на TTY и PTY (чтобы юзеру было приятно), и блочная в противном случае (чтобы быстрее работало когда юзер не видит).
                                  Ответить
      • Самое забавное, что после упихивания четырех циклов в один, массив уже не нужен и болтается как атавизм.
        Ответить
    • http://stackoverflow.govnokod.ru/
      Ответить
    • Комментарии под doxygen ещё заточить можно.
      А вообще действительно, как сказал @bormand объединять в кучу то, что надо бы делать отдельно, не есть гуд.
      И в довесок к стандартным контейнерам, использовать стандартные алгоритмы min/max.
      Ответить
      • Осталось обосрать строчки 15 и 16, сказав, что, зачастую, лучше писать int min(0). И тогда необсужденными останутся только инклуды, int main(), return 0, пустые строки и строки со скобками...

        P.S. А ну да, до кучи обосрем пустую строку 17 - в ней нету вызова srand(), поэтому всегда будут одинаковые результаты.
        Ответить
        • > необсужденными останутся только инклуды и строки со скобками...
          Строки со скобками сейчас обосрет тарас, ну а мне инклуды не нравятся. Лучше бы сделали import module вместо них создатели языка
          Ответить
        • про хедеры могу добавить, что надо было С++11 привлечь с <random>.
          http://en.cppreference.com/w/cpp/numeric/random
          Ответить
    • Всем спасибо.
      Ответить
    • -Да, мамочка, ты классная блядь! Юрка принялся целовать маму взасос…
      Ответить

    Добавить комментарий