Няшная / Говнокод #9651 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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 <stdio.h>

#define MAXLINE 1000 /* максимальная длина строки в потоке */

int getline(char line[], int maxline);

main()
{
    int len; /* длина текущей строки */
    char line[MAXLINE]; /* текущая введённая строка */

    while((len = getline(line, MAXLINE)) != (-1))
        printf("%s", line);
        
    system("PAUSE");
    return 0;
}

/* getline: считывает строку в s, удаляет пробелы и знаки табуляции в конце строки, возвращает её длину. Удаляет полностью пустые строки */
getline(char s[], int lim)
{
             int c, i;
             
             for(i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
                   s[i] = c;
             if (c == EOF)
                return (-1); /* конец ввода */
             else if (c == '\n') {
                  while(s[i-1] == ' ' || s[i-1] == '\t') /* "удаление" пробелов и знаков табуляции в конце строки */
                     --i;
                  if (i > 0) { /* если строка непустая */
                     s[i] = '\n';
                     ++i;
                  }
                  s[i] = '\0';
                  return i;
             }
}

Задача: убирать в конце каждой строки лишние пробелы и знаки табуляции, удалять полностью пустые строки.
Решение: при считывании строки вида "abc_____\n" на выходе получаем массив символов "abc\n\0___" (пробелы в конце). Печатаем строки по мере поступления, профит.

Говнокод или нормально?

Запостил: justanothernickname justanothernickname, (Updated )

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

  • 1) если конец ввода наступит посередине последней строки - ты её не обрабатываешь - так и надо?
    2) если хочешь пыщьпыщь производительности, то следи за позицией последнего введенного непробельного символа еще в цикле чтения, где getchar
    3) не ну я понимаю, что это хтонический Си, но опускать возвращаемый тип в определении тела функции - некрасиво
    Ответить
    • 1) Нет, конечно. Эпик фэйл, писала ночью и не заметила. Тогда вопрос снимается - точно говнокод.
      2) Да, пожалуй, так и надо делать.
      3) Спасибо за замечание. Пока что только учусь, поэтому правильное оформление ещё не вошло в привычку.
      Ответить
  • Кроме алгоритмического говна (строки 29-30, как верно заметил Steve_Brown), есть еще говно в проектировании. У тебя функция getline (кстати, такая есть стандартной либе glibc, поэтому это имя лучше не использовать) делает сразу три вещи: читает из stdin, фильтрует пробельные символы в конце, еще и пустые строки удаляет. Логичнее разбить эту функцию на три отдельные, скажем, read_line, trim_trailing и delete_empty_line. Такое и тестировать проще, и алгоритм станет намного нагляднее. На счет производительности: сомневаюсь, что после такой переделки она ощутимо просядет.
    Ответить
    • Не обязательно. Спецификация языка С говорят, что при чтении текстовых потоков в общем случае не гарантируется полного совпадения того, что было записано, и того, что потом читается. В частности, приводится как раз такой пример: если вы писали в файл строки с пробелами в конце, то при чтении эти пробелы могут магическим образом пропасть (т.е. платформа имеет право неявно "оптимизировать" текстовые файлы, удаляя на лету лишний whitespace).

      Какой-то частной программе, работающей на нескольких платформах, возможное различие в поведении текстовых потоков может мешать. Вот для того, чтобы изолироваться от таких различий и создать некий platform abstraction layer, может и пригодиться функция, которая и читает стоку из файла, и выкидиывает из нее лишние пробелы на конце. Т.е. это просто функция чтения строки, которая ведет себя на всех платформах одинаково.

      (Понятно, что имя лучше дать другое. И внутренне можно реализовать через подфункции.)
      Ответить
      • Good point. Но это должно быть оформлено соответственно. Все-таки оригинальный ГК мало походит на функцию, выполняющую абстракцию от конкретной платформы.
        По поводу подфункций: а если надо будет еще сделать функцию, которая делает то же самое, но еще и в начале пробельные символы удаляет? И что, копипастить? Так что только подфункции, тут без вариантов.

        Конечно, с ООП это решалось бы проще, через цепочку классов-фильтров. Се ля ви.
        Ответить
  • 2All

    Если абстрагироваться от исходного ГК, насколько оправдана такая замена?

    while(s[i-1] == ' ' || s[i-1] == '\t')
      --i;


    на такое:

    {
      int run = !0;
      while (run) {
        switch (s[i-1]) {
          case ' ':
          case '\t': --i; break;
          default: run = 0; break;
        }
      }
    }
    Ответить
    • зачем обнулять память (нагружать шину), если можно поставить ровно один ноль где нужно?
      ну и !0 это даа, хаккир!
      Ответить
      • > зачем обнулять память (нагружать шину), если можно поставить ровно один ноль где нужно?

        Я как-то вообще не понял, о чем это.

        > !0 это даа, хаккир

        Дело вкуса, мне так очевиднее. Нужно значение, которое «не ноль», вот я и пишу !(не) 0(ноль)
        Ответить
        • > !(не) 0(ноль)
          Теоретически, это должно быть ровно 4294967295 значений, полагая инт в 4 байта.

          Кстати, любопытно, что !0 = 0!. Это что-нибудь, да значит.
          Ответить
          • Это логично, учитывая, что:
            * нормального булева типа нет,
            * под False подразумевается 0,
            * True := !False
            Ответить
  • while(s[i-1] == ' ' || s[i-1] == '\t')
    Совершенно не проверяет на выход за пределы массива. И перед массивом вполне может быть пробел в памяти -> memory corruption.
    Ответить
  • б.D.Z)H"E?PLK(Q K"C E?Y"Q(J"V Y(E)G.G(NA$J VOM:H)G:J!V)S?N V$GK(JW:L!I.S!V"C"Z C,G?K$J.R(W"O?I)S:Y!L(S.RS.N!KG?O T(O:UY?A,J.G)V(M?A$R!M"H!WE.N:M?S:T(D.E$O"P:J.Q.N"V(F.H(B!J:L(T!F?V"G"P?A$O?N,X,O:W.J"T Y:R)L?I.Z"U.V?P$I,V!Z"A.Y)TS,Y:YH(O)L$Y,Y.H!W(C(Q B(S)Y.M$J?T.J:V.Y$C"DC.E"S!B G ZIC"K C.R:B(O?X?W,Z.J K,U$O"AW?S(K.W$W(J,C.S)Y GДAIHNBGKCJUBSNGQFYWTUVDFJKIJPUOWGDUBEYJXRMONVEJXHJY
    Ответить

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

Переведи на "PHP", guest!

    А не использовать ли нам bbcode?


    8