好,所以我试图解决这个问题:
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
首先使它运行,因此该程序将运行得更快。
谢谢!
答案 0 :(得分:11)
这是cargo cult programming。 #define
不会“使事情变得更快”,它会内联代码,而有时内联代码是做事的更快方法。
您的变量名是完全不透明的,您所做的事情就像使用三元组,除了看起来很酷之外,没有任何真正的原因。该代码是“最小的”,因为它可能有效(没有测试)并且在字符数方面,但是否则完全不可维护。
我说这是因为他写了很多(有时是故意的)不透明的Perl代码:不要。
编写代码时,请牢记以下几点:
is_alive
的函数不应格式化硬盘驱动器,向老板发送愤怒的醉酒电子邮件等,它应告诉您是否存在某些问题,然后就是这样。 rst
这个函数有什么作用?这是一个惊喜! 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条目是不合算的,但是将其转储到缓冲区并在那里进行处理的方法可节省大量时间对不需要解码的东西进行解码很麻烦,将这个问题归结为基本要点:将字符串的不同部分与其他部分进行比较并计算匹配项。