VC++lrc歌词解析种

VC++lrc歌词解析类

        由于时间仓促,所以没有加过多的错误处理或检查,另外结构体、变量和字符串等没有动态定义,可能会导致严重的缓冲区错误,所以如果要当做一个项目来做的话,建议加上这些处理、检查,并动态分配内存。

        虽然说这是写成了一个C++类,但是文件读写以及许多函数都是C中的。见代码吧!代码看起来比较简单,老规矩,下载地址在后面。

        差点忘记说明了,这种实现比较不好暂停,若有好点子,欢迎回复。谢谢!

#include <stdio.h>
#include <windows.h>


typedef struct
{
    unsigned  int  time;
    char           data[40];

}LineData;

class CLrc
{
    public:

        BOOL  Open( LPTSTR  FileName );
        void  Close();
        BOOL  GetTitle( LPTSTR  Title ); // 未实现
        BOOL  GetAlbum( LPTSTR  Album ); // 未实现
        BOOL  GetArtist( LPTSTR  Artist ); // 未实现
        BOOL  GetEditor( LPTSTR  Editor ); // 未实现
        BOOL  ReadLine( LPTSTR  Data );

        CLrc()
        {
            memset( LrcFile, 0, 128 );
            ldpoint = 0;
        }

        ~CLrc()
        {
            if( hLrcFile != NULL )
            {
                fclose( hLrcFile );
            }
        }

   // private:

        FILE *hLrcFile;
        char  LrcFile[128];

        LineData  ld[100];
        int   ldpoint;

        void  DelCRLF( char *Data );
        void  Sort();
        int   Findch( const char *str, unsigned char ch );
        int   GetTime( const char *line );
        void  ResolveLine( const char *line );
        void  GetLineData( const char *line, char *data );

};

// 打开文件
BOOL CLrc::Open( LPTSTR  FileName )
{
    FILE  *fp;

    fp = fopen(FileName, "r");
    if( fp == NULL )
    {
        return FALSE;
    }
    hLrcFile = fp;
    return  TRUE;
}

// 关闭文件
void  CLrc::Close()
{
    if( hLrcFile != NULL )
    {
        fclose( hLrcFile );
    }
}

// 获得行的歌词
// 例如,[00:00.01]abc,该函数将获取到的"abc"保存到data中
void CLrc::GetLineData( const char *line, char *data )
{
    int  i = 0,
         j = 0,
         len;

    if( strcmp( line, "" ) )
    {
        len = strlen( line );

        i = len;
        while( line[i] != ']' && i > 0 )
        {
            i--;
        }

        for( j = i + 1, i += 1; j <= len; j++ )
        {
            data[j - i] = line[j];
        }
    }
}

// 读取下一行数据
BOOL CLrc::ReadLine( char *line )
{
    char  Line[100];

    memset( Line, 0, 100 );
    if( feof( hLrcFile ) || fgets( Line, 100, hLrcFile) == NULL )
    {
        return FALSE;  // 表示文件结束
    }
    DelCRLF( Line );
    strcpy( line, Line );

    return TRUE;  // 正常
}

// 删除Data中的空格
void CLrc::DelCRLF( char *Data )
{
    int  i = 0;
    int  len = strlen( Data );

    for( ; i < len; i++ )
    {
        if( Data[i] == 0x0D || Data[i] == 0x0A )
        {
            int  j = i;

            for( ; j < len ; j++ )
            {
                Data[j] = Data[j + 1];
            }
        }
    }
}

// Findch用于检测ch在str中出现的次数
int CLrc::Findch( const char *str, unsigned char ch )
{
    int  i = strlen( str );
    int  quan = 0;

    while( i-- )
    {
        if( str[i] == ch )
        {
            quan++;
        }
    }
    return  quan;
}

// 获得歌词时间
int CLrc::GetTime( const char *line )
{
    int  min = 0,
         sec = 0,
         ms  = 0;

    if(Findch(line, '.') == 0)
    {
        sscanf( line, "[%d:%d]", &min, &sec );
    }
    else
    {
        sscanf( line, "[%d:%d.%d]", &min, &sec, &ms );
    }
    return  (min * 6000 + sec * 100 + ms );

}

// 解析每一行的数据,存入结构
void CLrc::ResolveLine( const char *line )
{
    char  str[100];
    int   i = 0,
          j = 0,
          last = 0;

    strcpy( str, line );
    if (Findch(str, '[') != Findch(str, ']') )  // 检测正确性
    {
        return;
    }

    for (i = 0; i <= strlen(str); i++ )
    {
        if (str[i] == ']')
        {
            char  buf[50] = "";
            int   t = 0;
            
            for (j = last; j <= i; j++ )
            {
                buf[t++] = str[j];
            }

			ld[ ldpoint ].time = GetTime( buf ) * 10;
            GetLineData( line, ld[ldpoint].data);

            ldpoint++;
 
            i++;
            last = i;           
        }
    }

}

// 将结构中所有歌词排序,冒泡排序
void  CLrc::Sort()
{
    int  i = 0, j;

    for( ; i < ldpoint - 1; i++ )
    {
        for( j = i; j < ldpoint - i; j++ )
        {
            if( ld[j].time > ld[j + 1].time )
            {
                LineData  t;

                t = ld[j];
                ld[j] = ld[j + 1];
                ld[j + 1] = t;
            }
        }
    }
}


调用方式:

int main()
{
    CLrc  lrc;

    if( lrc.Open("J:\\lrc2.lrc") == FALSE )
    {
        printf( "无法打开歌词文件!\n" );
        return 0;
    }

    while( true )
    {
        char  line[100] = "";

        if( !lrc.ReadLine( line ) ) // 读完了
        {
            break;
        }
        if( strcmp( line, "" ) )
        {
            lrc.ResolveLine( line ); // 解析数据
        }
    }
    lrc.Close(); // 关闭文件句柄

    lrc.Sort(); // 排序

    if( lrc.ldpoint )
    {
        Sleep( lrc.ld[0].time );
        printf( "%s\n", lrc.ld[0].data ); // 输出第一行

        for( int i = 1; i < lrc.ldpoint; i++ )
        {
            Sleep( lrc.ld[i].time - lrc.ld[i - 1].time );
            printf( "%s\n", lrc.ld[i].data );
        }
    }

    return 0;
}