注册 登录
编程论坛 C++教室

[求助]关于歌词文件读取的操作,调试半天没找到错误地方,请指教!

wfpb 发布于 2007-03-16 13:14, 1151 次点击

找了半天,也没找出错误,还请大家帮我调试一下,顺便上传一个歌曲文件,协助调试。

程序代码:

#include <afx.h>
#include <cmath>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;


//字符串转整数
int CStringToInt(CString str)
{
    int len=str.GetLength();
    int i=0;
    int answer=0;
    bool negative=false;
    if(str[0]=='-')
    {
        i=1;
        negative=true;
    }
    for(;i<len;i++)
    {
        answer+=int((str[i]-'0')*pow(10,len-i-1));
    }
    if(negative)
        answer*=-1;
    return answer;
}
//字符串转浮点数
float CStringToFloat(CString str)
{
    int sep=str.Find('.');
    CString temp=str.Left(sep);
    int i=CStringToInt(temp);
    temp=str.Right(str.GetLength()-sep-1);
    int t=CStringToInt(temp);
    int s=temp.GetLength();
    float f=((float)t)/pow(10,s);
    return f+(float)i;
}
//字符串转时间
void CStringToTime(CString str,int &min,float &sec)
{
    int sep=str.Find(':');
    CString temp=str.Left(sep);
    min=CStringToInt(temp);
    temp=str.Right(str.GetLength()-sep-1);
    sec=CStringToFloat(temp);
}




//=======================上面3个辅助函数没有问题,测试过了================//


//歌词数据部分
typedef struct LYRICS
{
    int m_min;        //分钟
    float m_sec;    //秒钟
    CString m_lrc;    //歌词
    LYRICS(int m,float s,CString str)
    {
        m_min=m;
        m_sec=s;
        m_lrc=str;
    }
    bool operator<(LYRICS lrc)
    {
        if(m_min<lrc.m_min)
            return true;
        else if(m_min==lrc.m_min)
            return m_sec<lrc.m_sec?true:false;
        else return false;
    }
}*LPLYRICS,LRC;


//歌曲信息部分
typedef struct LYRICSINFO   
{
    char m_ti[40];    //歌名
    char m_ar[40];    //艺人名
    char m_al[40];    //专辑
    char m_by[40];    //编者
    int m_offset;//偏移
    LYRICSINFO()
    {
        memset(m_ti,0,40);
        memset(m_ar,0,40);
        memset(m_al,0,40);
        memset(m_by,0,40);
        m_offset=0;
    }
} *LPLYRICSINFO,LRCINFO;



class Lyrics
{
    typedef unsigned int POS;
    typedef vector<LRC> VECLRC;    //歌词数据容器
#define MAX 100
    LRCINFO    m_lrcinfo;    //歌词信息
    VECLRC m_data;            //歌词数据
    ifstream m_file;    //歌词文件
    CString ReadLrcInfo(LPLYRICSINFO lplyricsinfo)    //读取歌词信息
    {
        m_file.seekg(0);
        while(!m_file.eof())
        {
            char buf[MAX]={0};
            m_file.getline(buf,MAX);
            CString temp(\"\"),str(buf,strlen(buf));
            char dwReturn[20]={0};
            int s=str.Find(\"[\")+1;
            int e=str.Find(':');
            for(int i=s;i<e;i++)
                if(str[i]==' ')continue;
                else temp+=str[i];
            s=e+1;
            e=str.Find(']');
            for(int m=s,n=0;m<e;m++)
            {
                dwReturn[n]=buf[m];
                n++;
            }


            if(temp==_T(\"ti\"))
                strcpy(lplyricsinfo->m_ti,dwReturn);
            else if(temp==_T(\"ar\"))
                strcpy(lplyricsinfo->m_ar,dwReturn);   
            else if(temp==_T(\"al\"))
            {
                strcpy(lplyricsinfo->m_al,dwReturn);
                cout<<\"al\"<<endl;
            }

//上面的al可以正常输出,到下面就出现问题了,我断点跟踪都没用,不知道他怎么突然崩溃

            else if(temp==_T(\"by\"))
                strcpy(lplyricsinfo->m_by,dwReturn);
            else if(temp==_T(\"offset\"))
                m_lrcinfo.m_offset=CStringToInt(dwReturn);
            else{
                return CString(buf,strlen(buf));
            }


        }
        return \"\";
    }
    void ReadLrcData(VECLRC &veclrc)            //读取歌词内容和时间
    {
        while(!m_file.eof())
        {
            char buf[MAX]={0};
            m_file.getline(buf,MAX);
            CString str(buf,strlen(buf));
            CStringToLrc(str,m_data);
        }
    }
    void CStringToLrc(CString str,VECLRC &veclrc)        //字符串转换为priority_queue<LRC>
    {
        //获取歌词        
        CString szlrc=str.Right(str.GetLength()-str.ReverseFind(']')-1);
        szlrc=szlrc.Right(str.GetLength()-str.ReverseFind(' ')-1);
        //从右往左读取时间
        CString temp=\"\";
        while(str!=_T(\"\"))
        {
            int sep=str.ReverseFind('[');
            for(;sep<str.ReverseFind(']');sep++)
                if(str[sep]!=' ')
                    temp+=str[sep];
            int m=0;
            float f=0;
            CStringToTime(temp,m,f);
            veclrc.push_back(LRC(m,f,szlrc));
            str=str.Left(sep);
        }
    }
public:
    Lyrics()
    {
        memset(&m_lrcinfo,0,sizeof(LRCINFO));   
    }
    bool Open(LPCTSTR lpszFileName, UINT nOpenFlags)
    {
        m_file.open(lpszFileName,(ios_base::openmode)nOpenFlags);
        if(m_file.fail())return false;
        CString head=ReadLrcInfo(&m_lrcinfo);
        CStringToLrc(head,m_data);
        ReadLrcData(m_data);
        sort(m_data.begin(),m_data.end());
        return true;
    }
    void Close()
    {
        m_file.close();
    }
    void GetLrcInfo(LPLYRICSINFO lplrcinfo)
    {
        strcpy(lplrcinfo->m_ti,m_lrcinfo.m_ti);
        strcpy(lplrcinfo->m_ar,m_lrcinfo.m_ar);
        strcpy(lplrcinfo->m_al,m_lrcinfo.m_al);
        strcpy(lplrcinfo->m_by,m_lrcinfo.m_by);
        lplrcinfo->m_offset=m_lrcinfo.m_offset;
    }
    POS FindFirst(LPLYRICS lplrc)
    {
        lplrc->m_min=m_data.front().m_min;
        lplrc->m_sec=m_data.front().m_sec;
        lplrc->m_lrc=m_data.front().m_lrc;
        return 0;
    }
    void FindNext(LPLYRICS lplrc,POS& pos)
    {   
        pos++;
        lplrc->m_min=m_data.at(pos).m_min;
        lplrc->m_sec=m_data.at(pos).m_sec;
        lplrc->m_lrc=m_data.at(pos).m_lrc;
    }
};


int main()
{
    Lyrics lyrics;
    if(!lyrics.Open(\"s.h.e - 怎么办.txt\",(UINT)ios::in))
    {
        cout<<\"失败!\";
        exit(1);
    }
    LYRICSINFO lrcInfo;
    lyrics.GetLrcInfo(&lrcInfo);
    cout<<lrcInfo.m_ti<<endl;
    lyrics.Close();
    return 0;
}

只有本站会员才能查看附件,请 登录

[此贴子已经被作者于2007-3-16 20:21:39编辑过]

2 回复
#2
litcatyx2007-03-16 21:43
Lyrics::ReadLrcInfo中的dwReturn你给的太小了,当分析到唱片(al)时,"花样少年少女 电视原声带"几个字大于20(也就是你给定的值),所以会出错
#3
wfpb2007-03-16 22:37

弄完了,发上来大家需要用就直接用,直接对歌词操作的类。我打包上传了.

只有本站会员才能查看附件,请 登录

刚想起来先前没有写操作,现在加一个新建歌词文件函数,对文件用lrc特定格式写入。

[此贴子已经被作者于2007-3-17 12:06:34编辑过]

1