我正在使用wcahr_t类型的字符处理文件。我想加快我的程序。
尽可能用fprintf代替fputwcfscanf代替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"等等。

10-06 02:38