新置MP3一件,居然没有随机播放的功能,坑啊!身为程序媛一枚,自己动手吧~
获取当前路径:
- char buf[1000];
- GetCurrentDirectory(1000,buf);
- string cur_folder_file = string(buf)+"\\*.mp3";
- void getMp3Names(string filepath,vector<string> &names)
- {
- names.clear();
- WIN32_FIND_DATA f;
- HANDLE h = FindFirstFile(filepath.c_str() , &f);
- if(h != INVALID_HANDLE_VALUE)
- {
- do
- {
- names.push_back(f.cFileName);
- } while(FindNextFile(h, &f));
- }
- FindClose(h);
- }
- void renameMp3Names(vector<string> &names){
- int mp3_num = names.size();
- vector<bool> used_names(mp3_num,false);
- srand(time(NULL));
- for(int i=0;i<mp3_num;i++){
- int new_name_num = -1;
- while(new_name_num<0){
- int tmp= rand()%mp3_num;
- if(!used_names[tmp]){
- new_name_num = tmp;
- used_names[tmp] = true;
- }
- }
- char char_tmp[100];
- itoa(new_name_num,char_tmp,10);
- string new_name = string(char_tmp)+".mp3";
- if(!_access(names[i].c_str(),0))
- {
- if(!rename(names[i].c_str(),new_name.c_str()))
- {
- cout<<"RENAME "<<names[i]<<" AS: "<<new_name<<""<<endl;
- }
- }
- }
- return ;
- }
基本可以啦~
不过有一点,这个程序运行第二遍就有问题了,因为所有的文件都变成了 num.mp3,再次随机重命名的时候就会出现冲突,重名文件存在导致rename()失败!
再小小修改一下:
- void renameMp3Names(vector<string> &names){
- cout<<"---------------RENAME MP3 FILES---------------"<<endl;
- int mp3_num = names.size();
- vector<bool> used_names(mp3_num,false);
- srand(time(NULL));
- for(int i=0;i<mp3_num;i++){
- int new_name_num = -1;
- while(new_name_num<0){
- int tmp= rand()%mp3_num;
- if(!used_names[tmp]){
- new_name_num = tmp;
- used_names[tmp] = true;
- }
- }
- char char_tmp[100];
- itoa(new_name_num,char_tmp,10);
- string new_name = string("tmp")+string(char_tmp)+".mp3";
- if(!_access(names[i].c_str(),0))
- {
- if(!rename(names[i].c_str(),new_name.c_str()))
- {
- cout<<"RENAME "<<names[i]<<" AS: "<<new_name<<""<<endl;
- names[i] = new_name;
- //used_names[i] =false;
- }
- }
- }
- for(int i=0;i<mp3_num;i++)
- used_names[i] = false;
- cout<<endl;
- cout<<"-------------AGAIN RENAME MP3 FILES-------------"<<endl;
- for(int i=0;i<mp3_num;i++){
- int new_name_num = -1;
- while(new_name_num<0){
- int tmp= rand()%mp3_num;
- if(!used_names[tmp]){
- new_name_num = tmp;
- used_names[tmp] = true;
- }
- }
- char char_tmp[100];
- itoa(new_name_num,char_tmp,10);
- string new_name = string(char_tmp)+".mp3";
- if(!_access(names[i].c_str(),0))
- {
- if(!rename(names[i].c_str(),new_name.c_str()))
- {
- cout<<"RENAME "<<names[i]<<" AS: "<<new_name<<""<<endl;
- }
- }
- }
- cout<<endl;
- return ;
- }
大功告成啦!
*有关生成随机序列的修改
多谢一楼友邻xiucaijiang 的留言,指出来上述方法生成随机序列的效率很低。确实,上面用的方法是初始化一个序列用来记录已经“用过”的数,如果生成的随机数是已经用过的数,那么就再重新生成一遍。这样的方法对于生成大小为N的随机序列,生成第一个随机数的期望次数为1次,第二次为N/(N-1)次,第三次为N/(N-2)次,最后一个数期望次数为N次效率确实很低。xiucaijiang 给出的方法很好:
可以这样理解这种方法:生成随机序列相当于把之前0~N-1排序的N个数随机排列,那么每次我们随机抽出一个来排到后面。也就是第一次在所有N个数里随机抽一个排到最后一位,第二次在前N-1个数里随机抽一个排到倒数第二位,依次类推。由于每次排序每个数被抽到的概率都是1/N,所以可以认为最终的序列是随机排的。
不过这种方法在实现起来需要做几次不必要的位移,比如上面的例子中,第二次假设抽到了2,由0,1,2,3,5,4变成0,1,3,5,2,4需要把3移到第2位,5移到第三位,2换到第四位。这里3和5的移位其实是不必要的。也就是我们下一次在4个数里随机取,前4个数排列成0,1,3,5还是0,1,5,3是不影响的。所以只需要把2和5换位置即可。
总结生成随机序列的方法:循环N次,第i(i=0~N-1)次的操作为在前N-i个数中随机选一个数与第N-i-1个数交换位置。
- void generateRandomList(vector<int> & rand_list){
- int rand_size = rand_list.size();
- for(int i=0;i<rand_size;i++){
- rand_list[i] = i;
- }
- srand(time(NULL));
- for(int i=0;i<rand_size;i++){
- int tmp_rand= rand()%(rand_size-i);
- int tmp = rand_list[tmp_rand];
- rand_list[tmp_rand] = rand_list[rand_size-1-i];
- rand_list[rand_size-1-i] = tmp;
- }
- return;
- }
这次只需要随机N次就可以生成不重复的随机序列啦~