我的朋友说我的代码很难看,我不明白为什么

时间:2019-12-17 01:07:12

标签: c

好,所以我试图解决这个问题:

https://dmoj.ca/problem/ccc11s2

我的解决方法如下:

#define in(ptr, i) while(i-->0){scanf(" %c", ptr++);} 
#define ans(ptr, i, n) while(i-->0){getchar(); (getchar()!=*(ptr++))?: n++;}
#define rst(ptr, r, i, n) ptr=r;i=n

int main(){

        int n, nCorrect = 0, i;
        scanf("%d", &n);    
        i = n;

        char r[n];
        char* ptr = r;

        in(ptr, i);     
        rst(ptr, r, i, n); 
        ans(ptr, i, nCorrect);

        printf("%d\n", nCorrect);

        return 0;
}

我的朋友不断告诉我,我不应该这样写。我给人的印象是,使用#define首先使它运行,因此该程序将运行得更快。

谢谢!

1 个答案:

答案 0 :(得分:11)

这是cargo cult programming#define不会“使事情变得更快”,它会内联代码,而有时内联代码是做事的更快方法。

您的变量名是完全不透明的,您所做的事情就像使用三元组,除了看起来很酷之外,没有任何真正的原因。该代码是“最小的”,因为它可能有效(没有测试)并且在字符数方面,但是否则完全不可维护

我说这是因为他写了很多(有时是故意的)不透明的Perl代码:不要

编写代码时,请牢记以下几点:

  • 使用有意义的名称声明函数和变量。遵守最小惊讶原则,即名为is_alive的函数不应格式化硬盘驱动器,向老板发送愤怒的醉酒电子邮件等,它应告诉您是否存在某些问题,然后就是这样rst这个函数有什么作用?这是一个惊喜!
  • 首先以标准方式进行操作。对抗过早优化的拖船。您将这些函数称为一次,即使您将它们调用一百万次,现代硬件上的C也是如此的可笑,以至于您甚至都很难用秒表来衡量它需要花多长时间。这是瞬间的。 不要优化您无法衡量的缓慢
  • 需要仔细定义宏,而不仅仅是slapdash。它们得到内插,这意味着适用不同的规则。如果while(i-->0)i,则无论出于何种原因,x+2都会完全中断。了解它们的工作原理,然后是否以及何时正确编写它们,您实际上需要一个宏。 注意语法复杂性

编写简单而有效的代码很无聊,因为它没有令人惊讶的地方,它并不总是那么容易,但它总是必需的。当您成为一名开发人员时,您将编写越来越无聊,越来越普通的代码,因为您将能够以可视化方式解决复杂问题的简单解决方案,从而避免了像这样的解决方案的所有不必要的夸张和夸张。

这里所有花哨的技巧都没有保存什么。通过优化对这段代码进行编译时,编译器将决定要内联的函数,并且由于涉及到IO,因此#define欺骗所导致的可能节省的任何时间都将完全丢失。内核将不得不花费的时间来从内核到用户空间来回转移数据。您的更改将大大少于统计噪音。

如果您想让程序运行的更快,则需要知道什么样的事情会使它变慢。例如,getch()实际上很慢,因为每个调用都需要相当痛苦的内核偏移。没有任何优化或宏观魔术可以解决这个问题。而是一次将其全部读取到缓冲区中,然后使用简单的指针比较对其进行解析:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main() {
  // Maximum size of file is:
  // + N to NNNNN (1-5 byte + newline = 6 bytes)
  // + 10,000 entries (letter + newline = 2 bytes each)
  // + Don't care about NUL terminator
  size_t max_size = 10000 * 2 + 6;
  char* raw = malloc(max_size);

  fread(raw, 1, max_size, stdin);

  char* p = raw;

  size_t count = atoi(p);
  while (*(p++) != '\n');

  int score = 0;

  for (int i = 0; i < count; ++i) {
    score += p[i * 2] == p[count * 2 + i * 2];
  }

  printf("%d\n", score);

  free(raw);

  return 0;
}

在Windows上,您需要对其进行调整以处理CRLF,而不只是LF,但是相同的想法可行。

getch()在读取大量数据时是残酷的。如果您不相信我,请编写一个测试程序,使用该方法在其中复制一个大文件(〜1GB),然后与一种更合理的策略进行比较,即读取〜64KB数据块。

在一个程序中,您只读取少量数据,如今这些数据已无足轻重,因此10K条目是不合算的,但是将其转储到缓冲区并在那里进行处理的方法可节省大量时间对不需要解码的东西进行解码很麻烦,将这个问题归结为基本要点:将字符串的不同部分与其他部分进行比较并计算匹配项。

相关问题