1. Си / Говнокод #12269

    +141

    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
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>
    
    int main()
    {
    	nachalo: system("cls");
    	int a;
    	printf("Write first number...");
    	scanf("%i", &a);
    
    	int b;
    	printf("Write second number...");
    	scanf("%i", &b);
    
    	int res1;
    	res1=a+b;
    
    	int res2;
    	res2=a-b;
    
    	int res3;
    	res3=a*b;
    
    	float res4;
    	res4=(float)a/b;
    
    	int res5;
    	res5=a*a;
    
    	int res6;
    	res6=b*b;
    
    	printf("\nSumm of %i + %i = %i\n", a, b, res1);
    	printf("Difference of %i - %i = %i\n", a, b, res2);
    	printf("Production of %i * %i = %i\n", a, b, res3);
    	printf("Private of %i / %i = %.4f\n\n", a, b, res4);
    	printf("Square of %i is %i\n", a, res5);
    	printf("Square of %i is %i\n\n", b, res6);
    
    	int max;
    	max = (b>a) ? b:a;
    	printf("The greatest number of %i and %i is %d\n\n", a, b, max);
    
    	int choice;
    	printf("To run program again, press number 1, else numbers \nor symbols will close the program...\n> ");
    	scanf("%i", &choice);
    	if (choice == 1)
    	{
    		goto nachalo;
    	}
    	else (choice != 1);
    	{
    		return 0;
    	}
    }

    Калькулятор. Nuff said

    Запостил: heivizi, 11 Декабря 2012

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

    • лаба
      Ответить
      • да, самая первая лаба
        Ответить
        • А что, даже и аккуратненько написано. Ангрийский удручает только, но и там видно, что человек старался.
          Ответить
        • Конструкции типа
          int res1;
          res1=a+b;
          можно совместить в
          int res1 = a+b;
          Конструкцию с goto стоит переделать на while. Например так:
          while (1) {
              /* всякий код */
              /* ... */
              scanf("%i", &choice);
              if (choice != 1)
                   break;
          }
          return 0;
          P.S. system("cls"), имхо, не нужен. Красоты и удобства эта очистка не добавляет. <windows.h> тоже не нужен, и без него должно собраться.
          P.P.S. А в остальном, для первой лабы, очень даже хорошо.
          Ответить
          • int b;
            scanf("%i", &b);

            следует заменить на
            scanf("%i", &(int b));
            Ответить
            • > scanf("%i", &(int b));
              Тонко. Я даже ощутил сишкобатхерт и проверил.
              Ответить
              • intB
                Ответить
              • Ошибка компиляции будет. Что должно было быть?
                http://ideone.com/F2tR3o
                Ответить
                • Вообще я имел в виду объявление переменной в месте передачи параметра.
                  Ответить
                  • Нет такого в сишке.
                    Ответить
                    • Единственное, что я могу посоветовать, как замену твоему извращению, так это вот это:
                      http://liveworkspace.org/code/4skHZ7$13
                      #include <stdio.h>
                      int main() {//gcc only
                         scanf("%i", ({int b; &b;}));
                         printf("ok");
                         return 0;
                      }
                      Ответить
                      • Но это немного не то, ибо переменная дальше не видна.
                        Ответить
    • goto считать вредными.
      Неужели такую лаботу могли принять?
      Ответить
      • > goto считать вредными
        Верно. Но и верховным злом считать goto не стоит. При программировании на Си встречаются ситуации в которых goto упрощает код и делает его более понятным (код ОПа, естественно, не такая ситуация, и здесь goto не нужен).

        > Неужели такую лаботу могли принять?
        Почему нет? Я бы на месте препода пояснил неудачные моменты и принял. Пересдавать лабу из-за мелких придирок считаю пустой тратой времени. Пусть лучше студент вместо этого потратит время на следующую лабу, и попробует там избежать этих проблем.
        Ответить
        • while getch - примитивнейшая техника, в которой не надо быть семи пядей во лбу. Это не rocket science. Собственно, гото плохо уже этим, вместо организации вменяемого цикла, появилось на ровном месте.
          Ответить
          • goto плохо тем, что это слишком сильный инструмент, который по глупости и молодости хочется юзать везде, по поводу и без повода, особенно если первым языком был бейсик (как у меня)... Больше ничего плохого в нем нет. Со временем (довольно быстро, особенно если кто-то поможет и покажет как выглядят те же примеры без goto) приходит понимание, что без него код, как правило, лучше читается, и goto само уходит из употребления.

            P.S. Но я считаю, что задача препода при приеме лаб - раскрыть студенту его ошибки, и пояснить способы, как их избежать (к сожалению таких очень мало), а не сказать ему "ты мудак, иди нахуй отсюда, ниче я тебе не расскажу, придешь с переписанной лабой" (как делают многие преподы). На лекции ведь все тонкости не раскроешь, да и никто не запомнит их, пока не нарвется сам. Ведь в мозг врезаются именно ситуации в которых участвовал ты сам, а не абстрактные советы в вакууме.
            Ответить
            • здесь присутствуют те, кому препод на лабах раскрывал ошибки и пояснял способы?
              у меня преподы на лабах просто проверяли что работает на их введенных значениях, ну а малознакомые иногда просили на месте что-нибудь изменить, чтобы удостовериться, что лаба писана мной
              Ответить
              • > здесь присутствуют те, кому препод на лабах раскрывал ошибки и пояснял способы?
                Маловероятно. Жаль конечно.

                > у меня преподы на лабах просто проверяли что работает на их введенных значениях
                А у нас был эпичный препод, который лабу проверял строго на тех числах, которые даны заранее, и ни на каких более, и, при этом, совершенно не интересовался исходниками. В результате каждый год половина студентов сдавала ему прогу, в которой по нажатию на кнопку "рассчитать" появляется намертво вбитый ответ.
                Ответить
        • > на Си встречаются ситуации в которых goto упрощает код и делает его более понятным
          90 процентов этих goto суть breakи. Остальные 10% не нужны и могут быть заменены структурным кодом. Из этих 10% - половина duff device-подобные извраты.
          Ответить
          • > 90 процентов этих goto суть breakи
            break'и из двух циклов да, структурно они смотрятся как флажкоебское говно, или внешний цикл засран копиями условий выхода из внутренего, что еще хуже.

            Прыжок к концу функции для освобождения ресурсов. Были бы исключения или RAII - был бы не нужен.

            Ну и реализация конечных автоматов (в сгенеренном коде).

            Других полезных применений не попадалось.
            Ответить
            • >break'и из двух циклов да, структурно они смотрятся как флажкоебское говно
              int fors(size_t am, size_t bm)
              {
                int res=0;
                for(int a=5; a<am; a++)
                  for(int b=5; b<bm; b++)
                  {
                    res = res + arr[a][b];
                    if(res > 42)
                      return 42;
                  }
                return 42;
              }
              
              int get42()
              {
                return fors(265,265);
              }
              Структурно и никакого флашкоёбского говна.
              Ответить
              • Не так структурно, но все ещё нет никакого флашкоёбского говна:
                int get42()
                {
                  vector<int> arr=getArr();
                  size_t am = 265, bm = 265;
                  return [&]
                  {
                    int res=0;
                    for(size_t a=5; a<am; a++)
                      for(size_t b=5; b<bm; b++)
                      {
                        res = res + arr[a][b];
                        if(res > 42)
                          return 42;
                      }
                    return 42;
                  }();
                }
                Ответить
                • Стоп. А теперь спрячь подальше лямбду и RAIIшный вектор, и посмотри внимательно на название раздела. А также на мою фразу "при программировании на Си".

                  P.S. Флашкоебского говна нет, но код стал намного непонятнее чем какой-нибудь такой
                  int get42() {
                      // preparations
                      arr = ...;
                      size_t am = ..., bm = ...;
                      int sum = 0, result = 0;
                      // the loop
                      for (size_t a = 5; a<am; a++) {
                          for (size_t b = 5; b<bm; b++) {
                              sum += arr[a][b];
                              if (sum > 42) {
                                  result = sum;
                                  goto stop;
                              }
                          }
                      }
                  stop:
                      // release arr here;
                      // ...
                      return result;
                  }
                  Ответить
                  • Лол, у меня с 2мя функциями получилось короче, чем у тебя с goto:
                    http://govnokod.ru/12269#comment163986
                    Ответить
                    • Aлсо get42 пишется так:
                      int get42(void) {return 42;}
                      Ответить
                    • Там arr не освобождают и не получают;)

                      Естественно, что goto нужен не для каждого выхода из двух циклов (в 90% случаев сойдет return, особенно в крестах). А только для тех, где после них нужно что-то освободить или доделать, и при этом должны быть доступны некие переменные как внутри цикла, так и после него. Вот тогда функция становится неудобной (у нее много не особо осмысленных аргументов, да еще и переданных по указателю).
                      Ответить
                  • > Стоп. А теперь спрячь подальше лямбду
                    ко ко ко
                    http://liveworkspace.org/code/36ND6p$1
                    #include <stdio.h>
                    
                    #define lambda(l_ret_type, l_arguments, l_body)         \
                      ({                                                    \
                        l_ret_type l_anonymous_functions_name l_arguments   \
                          l_body                                            \
                        &l_anonymous_functions_name;                        \
                      })
                      
                    int arr[1000][1000];
                    
                    int get42()
                    {
                      size_t am = 265, bm = 265;
                      return lambda(int, (),
                      {
                        int res=0;
                        for(size_t a=5; a<am; a++)
                          for(size_t b=5; b<bm; b++)
                          {
                            res = res + arr[a][b];
                            if(res > 42)
                              return 42;
                          }
                        return 42;
                      })();
                    }
                    
                    int main() {
                       
                       printf("%i", get42());
                       return 0;
                    }
                    Ответить
              • А если у меня пара-тройка локальных переменных, которые активно юзаются внутри двойного цикла? Передавать их в эту функцию? А возвращать значения как, если их нужно несколько (например a и b в твоем примере)? Через указатели, переданные в аргументах? Ну уж нет, я лучше goto поставлю.

                P.S. Чем доставляют gotoфобы - так это тем, что они готовы наворотить конструкции вдвое превышающие по длине код с goto, и, при этом, еще более сомнительные по понятности, лишь бы не ставить goto.
                Ответить
              • return 42 дублируется, а с готом бы дублирования не было
                Ответить

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