之前看见C代码连蒙带猜,也能编译通过很多东西,今天(没错,今天)刚刚开始学习C,才发现:
1. C没有想象中的那么可怕;
2. C和想像中的可怕程度差不多。
于是,便现学现用,打算把之前用Python写的凯撒加密练习用C重写。结果发现了关键的问题,数组的大小是静态的,根本无法根据用户输入的字符实现动态分配内存;若要动态也可以,方法对初学者难以理解。
后来,想到了方便的GNU Readline库可以自动处理键盘快捷键,便看了看文档,发现只要将一个指针指向它的返回值,就可以获得一段有字符串的内存了,程序完成,结果,速度比Python要至少慢1000倍,难道是Readline效率低下?于是做了一个试验。
程序1: caesar.c
#include <string.h>
#define MAX 99902
int main(void) {
char plain[MAX];
char letter;
int value;
int index;
printf("Please input your plain text: ");
fgets(plain, MAX, stdin);
printf("Please input your key (included negatives): ");
scanf("%i", &value);
for (index = 0; index < strlen(plain); index++) {
letter = plain[index];
if (letter >= 'A' && letter <= 'Z') {
fprintf(stderr, "%c", (letter - 'A' + value) % 26 + 'A');
}
else if (letter >= 'a' && letter <= 'z') {
fprintf(stderr, "%c", (letter - 'a' + value) % 26 + 'a');
}
else {
fprintf(stderr, "%c", letter);
}
}
}
编译参数:
gcc caesar.c -o caesar -O2
程序2 caesar_readline.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <readline/readline.h>
int main(void) {
char * plain;
char letter;
int value;
int index;
plain = readline("Please input your plain text: ");
printf("Please input your key (included negatives): ");
scanf("%i", &value);
for (index = 0; index < strlen(plain); index++) {
letter = plain[index];
if (letter >= 'A' && letter <= 'Z') {
fprintf(stderr, "%c", (letter - 'A' + value) % 26 + 'A');
}
else if (letter >= 'a' && letter <= 'z') {
fprintf(stderr, "%c", (letter - 'a' + value) % 26 + 'a');
}
else {
fprintf(stderr, "%c", letter);
}
}
fprintf(stderr, "\n");
free(plain);
}
编译参数:
gcc caesar_readline.c -o caesar_readline -O2 -lreadline
程序3 caesar.py:
import readline
import sys
plain = input("Please input your plain text: ")
value = int(input("Please input your key (included negatives): "))
for letter in plain:
if ord(letter) >= ord('A') and ord(letter) <= ord('Z'):
print("%s" % chr(((ord(letter) - ord('A') + value) % 26 + ord('A'))), end='', file=sys.stderr)
elif ord(letter) >= ord('a') and ord(letter) <= ord('z'):
print("%s" % chr(((ord(letter) - ord('a') + value) % 26 + ord('a'))), end='', file=sys.stderr)
else:
print("%s" % letter, end='', file=sys.stderr)
print("", file=sys.stderr)
版本: Python 3.2.3
资源1: string
大量随机字符,使用以下代码生成:
import random
def getstr():
temp = chr(random.randint(65, 126))
return temp
for i in range(1,101):
print(getstr(), end='')
然后在string文件结尾加一行,写16
跑分开始!
biergaizi@localhost ~/learning_c/test $ time ./caesar < string 2> c_result > /dev/null
real 0m1.205s
user 0m1.126s
sys 0m0.076s
biergaizi@localhost ~/learning_c/test $ time ./caesar_readline < string 2> c_readline_result > /dev/null
real 2m31.212s
user 2m30.776s
sys 0m0.165s
biergaizi@localhost ~/learning_c/test $ time python caesar.py < string 2> python_result > /dev/null
real 0m0.314s
user 0m0.309s
sys 0m0.004s
输出相同吗?
biergaizi@localhost ~/learning_c/test $ md5sum *result
550963d7440ea4ef23e426147995f38e c_readline_result
550963d7440ea4ef23e426147995f38e c_result
550963d7440ea4ef23e426147995f38e python_result
可以看到,使用readline库后,程序的速度立刻慢了下来,这是为什么?难道readline库效率如此底下?在去掉’> /dev/null’后,发现弹出一个提示符,不停的自动输入string里面的内容,晕,原来是终端输入的速度在影响它……
因此,问题还是出在readline上,显然,把终端输入的时间计算进程序时间也是不公平的,来看sys时间:带不带readline都差不多。来看real时间:第一个C程序用了1.205s完成,而Python仅仅用了0.314s,这不科学啊?!Python同样用了readline库,为何不受影响?如果抛开这个问题,那为什么Python的运行时间依然是最短的?
P.S:其实这些程序处理负数都存在bug,还没能找到一个通用公式解决。
2012年09月13日 — 19:44
readline 是个全功能的编辑器了,在它的man page最后有条 😉
BUGS
It’s too big and too slow.
2012年09月15日 — 10:13
哈哈,我看到了。
不过我的Python代码也import readline了,Python的readline库实现为什么那么快?
2012年09月13日 — 18:36
letter = *plain++:
while(letter)
{
……
letter = *plain++:
}
// free的时候需要释放另存的头指针
2012年10月13日 — 19:38
好办法,节省了复制N次的开销。
2012年09月13日 — 18:29
strlen(plain);
用变量保存plain的长度
2020年04月12日 — 23:16
真的是这样诶
2012年08月28日 — 21:40
c计算时间的一般都用clock()函数。
2012年08月29日 — 15:59
改天再试吧。
2012年08月23日 — 18:16
0