繁体   English   中英

分支或FTELL(),它正在放缓?

[英]Branching or ftell() that is Slowing?

我在Windows操作系统上查看文件agent.h,我想看没有注释的c ++代码。我用旧程序将它们剥离以更清楚地查看代码,但我很惊讶它花了大约2秒钟才能完成该文件的大小为605KB,所以还算不错。为什么这么慢。我怀疑是ftell()函数在执行此操作,但我无法确定。放慢速度还是使用ftell()?,如果使用ftell(),那么将FILE指针返回的更好方法是什么?

编辑

#include <stdio.h>
#include <time.h>

#define NOT_COMMENT (!DOUBLESLASH_Comment && !ASTERISK_SLASH_Comment)

int main(int argc,char *argv[])
{
    clock_t t1 = clock();

    FILE *input , *output;

    if( fopen_s(&input,argv[1],"r") )
    {
        printf("error opening file %s\n",argv[1]);
        return 0;
    }

    if( fopen_s(&output,argv[2],"w") )
    {
        printf("error opening file %s\n",argv[2]);
        return 0;
    }

    char c , d;
                                                                //escape flag
    bool DOUBLESLASH_Comment = 0 , ASTERISK_SLASH_Comment = 0 , flag = 0;

    /* single quotes / double quotes */
    int s_QUOTED = 0 , d_QUOTED = 0;

    while( (c=getc(input)) != EOF )
    {
        switch(c)
        {
        case '\\':
            {
                if( NOT_COMMENT )
                {
                    if( flag == 1 )
                        flag = 0;
                    else
                        flag = 1;
                }
            }break;

        case '\'':
            {
                if( NOT_COMMENT && !d_QUOTED )
                {
                    if( !flag )
                    {
                        s_QUOTED++;
                    }
                }
            }break;

        case '"':
            {
                if( NOT_COMMENT && !flag )
                {
                    if( !s_QUOTED )
                    {
                        d_QUOTED++;
                    }
                }
            }break;

        case '/':
            {
                if( NOT_COMMENT && !d_QUOTED )
                {
                    if( (d=getc(input)) == '*' )
                    {
                        ASTERISK_SLASH_Comment = 1;
                    }
                    else if( d == '/' )
                    {
                        DOUBLESLASH_Comment = 1;
                    }
                    else
                    {
                        if( d != EOF )
                        {
                            ungetc(d,input);
                        }
                    }
                }
            }break;

        case '*':
            {
                if( ASTERISK_SLASH_Comment )
                {
                    if( (d=getc(input)) == '/')
                    {
                        if( (c=getc(input)) == EOF )
                            return 0;

                        ASTERISK_SLASH_Comment = 0;
                    }
                    else
                    {
                        if( d != EOF )
                        {
                            ungetc(d,input);
                        }
                    }
                }
            }break;

        case '\n':
            {
                if( DOUBLESLASH_Comment )
                {
                    DOUBLESLASH_Comment = 0;
                }
            }break;
        }

        if( NOT_COMMENT && c != '\\' ) flag = 0;
        if( d_QUOTED == 2 ) d_QUOTED = 0;
        if( s_QUOTED == 2 ) s_QUOTED = 0;

        if( NOT_COMMENT )
        {
            fprintf(output,"%c",c);
        }
    }

    fclose(input);
    fclose(output);

    clock_t t2 = clock();

    double elapsed = (double)(t2 - t1) / CLOCKS_PER_SEC;

    printf("time elapsed : %f\n",elapsed);
}

如果没有在分析器中实际测量代码的速度(以及用作输入的文件,因为我使用的文件可能会有一组不同的注释,等等,它们会触发不同的行为),那么很难确定。 但是看起来您只是使用fseek( ... )来移回一个字符。 在这种情况下,编写自己的功能的一个字符先行将是一个更好的选择。

像这样:

char lookahead = ' ';
bool havelookahead = false;

char getNextChar(FILE *input)
{
    if (havelookahead)
    {
        havelookahead = false;
        return lookahead;
    }
    return getc(input);
}

char peekChar(FILE *input)
{
    if (!havelookahead)
    {
        lookahead = getc(input);
        havelookahead = true;
    }
    return lookahead;
}

然后在循环开始时用getNextChar替换您的getc ,并在其中使用peekChar检查下一个字符(后跟一个伪getNextChar()以使用它)。

通常,这是用于解析的有用模式-无论是在字符级别还是在令牌级别,因此了解它的工作方式都是很好的学习。

您也可以使用标准的ungetc来“放回”您看过的角色。

这是否让你的代码显著更快或无法运行就很难说了,因为我在开始时说。

我不能编译你的代码,所以我不能让测试。 但是我怀疑这个瓶颈是fseek而不是ftell 拒绝字符是解析文件中的常见任务...,应由库或具有某些缓冲的中间层来实现。 在这种情况下(拒绝单个字符),您可以使用ungetc来实现。

所以你应该更换

fseek( file , ( ftell(file) - 1 ) , SEEK_SET );

ungetc('*', file);    // ungetc('/', file); the second time.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM