我正在使用wcahr_t
类型的字符处理文件。我想加快我的程序。
尽可能用fprintf
代替fputwc
和fscanf
代替fgetwc
有意义吗?
如果是,为什么?
最佳答案
我只使用每个调用一个wchar_t
进行了一些快速分析,确实有一个明显的区别。首先,代码:
#include "stdio.h"
#include "time.h"
#include "wchar.h"
wchar_t text[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#$";
const int N = 64;
const int M = 500000;
int main()
{
int i, j;
FILE *f1 = fopen("out1", "w");
FILE *f2 = fopen("out2", "w");
if (f1 == NULL || f2 == NULL)
{
printf("Failed to create file.\n");
return -1;
}
clock_t time1 = clock();
for (i = 0; i < M; i++)
for (j = 0; j < N; j++)
fprintf(f1, "%c", text[j]);
time1 = clock() - time1;
clock_t time2 = clock();
for (i = 0; i < M; i++)
for (j = 0; j < N; j++)
fputwc(text[j], f2);
time2 = clock() - time2;
printf("fprintf: %d ticks\nfputwc: %d ticks\n", time1, time2);
return 0;
}
gcc输出:
fprintf:5663刻度
fputwc:3307滴答声
叮当声输出:
fprintf:4696刻度
fputwc:3338个刻度
写入stdout或内存缓冲区有相同的时间差,因此这与它们如何写入或何时刷新等无关,它只是函数实现。让我们看看它们:
最明显的区别是
fprintf
采用一种格式,它必须解析这种格式。所以,它必须做的最起码的工作是:while (*fmt) {
if (*fmt++ == '%') {
switch (*fmt)
{
case 'c': *output = va_arg(args, int); break;
...
}
}
}
如您所见,代码必须进行多次检查,并且增量
fputwc
没有,这意味着额外的执行时间。在其他情况中,case 'c'
的位置实际上很重要,它越低,速度就越慢。(见注释)这些差异可能会占到大多数额外时间。特别是在
printf("%c", x)
的情况下,我们有:设置初始状态-比如说5-30条指令
读取第一个字符并与
'%'
-大约5条指令进行比较阅读第二个字符,switch语句-大约10条指令。
在这之后,它所做的与
fputwc
几乎相同。所有这些额外的指示,每一个电话加起来。还有一些其他的因素可以影响这一点,比如传递一个额外的参数,但是一个好的编译器可以优化它。
尽管如此,这是一种非常低效的处理方法。您可能应该先写入一个缓冲区,然后调用
fwrite
(我的记录与fputwc
)并在一次调用中转储整个缓冲区。需要注意的一点是fwrite(f, sizeof(wchar_t), N, text);
实际上也会输出0字节,最后是"a\0b\0c\0"
等等。