我正在我的Windows操作系统上查看文件agents.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);
}
答案 0 :(得分:3)
如果没有在分析器中实际测量代码的速度(并且使用您用作输入的文件,因为我使用的文件可能有不同的注释集等,会触发不同的行为),这很难说得肯定。但看起来您只是使用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;
}
然后在循环开始时将getc
替换为getNextChar
,并使用peekChar
检查下一个字符(后跟虚拟getNextChar()
以使用它)。
对于解析而言,这是一个非常有用的模式 - 无论是在角色级别还是在令牌级别,因此很好地了解它是如何工作的。
您还可以使用标准ungetc
来&#34;放回&#34;你看到的角色。
这是否会使你的代码运行得更快或更快,很难说,正如我在开始时说的那样。
答案 1 :(得分:2)
我无法编译你的代码,所以我无法进行测试。但我怀疑瓶颈是fseek
而不是ftell
。拒绝一个字符是解析文件的常见任务......应该由库或某个中间层实现一些缓冲。在这种情况下(拒绝单个字符),您可以使用ungetc
来实现这一点。
所以你应该替换
fseek( file , ( ftell(file) - 1 ) , SEEK_SET );
与
ungetc('*', file); // ungetc('/', file); the second time.