首页
社区
课程
招聘
c语言写的文件批量改名,求出错原因
发表于: 2014-2-2 20:53 10503

c语言写的文件批量改名,求出错原因

2014-2-2 20:53
10503
下了2部动漫,第一部文件名是001.rm....152.rm。第二部文件名是001XXXXX.rm....291xxx.rm。
想把第二部的文件名改为153.rm....443.rm,然后再吧两部动漫拷贝在一个文件夹里。改名工作量比较大,写了个简单的C语言程序。可结果只有部分文件改名成功了,部分没有成功,实在找不出原因,求大神赐教。。。

源码如下:
#include<io.h>
#include<stdio.h>
#include <ctype.h>
#include <string.h>
#include <windows.h>
int main()
{
  long Handle;
  struct _finddata_t FileInfo;
  char newname[512][7]={0};
  char oldname[512][70]={0};
  char s1[100];
  char * p=newname;
  char rm[]=".rm";
  int i,j,k;
  if((Handle=_findfirst("D:\\db2\\db2\\*.rm",&FileInfo))==-1L)
    printf("没有找到匹配的文件\n");
  else
  {
    strcpy(p,FileInfo.name);
    p=oldname;
    strcpy(p,FileInfo.name);
    p=newname;
    for(i=0;i<strlen(FileInfo.name)-3;i++)
    p[i+3]=NULL;

    j=atoi(p);
    j=j+152;
    sprintf(p, "%03d", j);
    strcat(p,rm);
    //printf("%s     %s\n",oldname[0],newname[0]);

    for(k=1;_findnext(Handle,&FileInfo)==0;k++)
    {
      
      p=oldname[k];
      strcpy(p,FileInfo.name);
      p=s1;
      strcpy(p,FileInfo.name);
      for(i=0;i<strlen(FileInfo.name)-3;i++)
      p[i+3]=NULL;

      j=atoi(p);
      j=j+152;
      sprintf(p, "%03d", j);
      strcat(s1,rm);
      p=newname[k];
      strcat(p,s1);
    }
    _findclose(Handle);
  }
  for (i=0;i<291;i++)
  {
    //printf("%s     %s\n",oldname[i],newname[i]);
    rename(oldname[i],newname[i]);
    Sleep(500);
  }
  getchar();
  return 0;


以上,注释掉的printf测试过,新旧文件名都是正确的,字符串处理虽然有不少警告错,但应该没什么问题。部分文件可以正确被改名,本来以为是硬件来不及处理,所以加了句sleep,结果还是老样子没改的还是没改。。。求高手给解答。我应该如何处理才能得到想要的结果。谢谢!

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (24)
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
那次看哪个大型工程上还用fopen,感觉很好笑。

一般不用C库函数,用win32api。
另外oldname和newname的大小怎么不样?

最后,觉得你可以用按键精灵解决问题,菜鸟都可以写的,在用之前先查查windows有哪些快捷键
2014-2-2 21:25
0
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
不知道你19行以来的6行是什么意思。

代码风格……
2014-2-2 21:27
0
雪    币: 382
活跃值: (554)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
请问用fopen有什么问题吗?
2014-2-2 21:32
0
雪    币: 2362
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
c语言之父谭浩强的得意门生
2014-2-2 23:13
0
雪    币: 254
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
继续测试了下,发现所有没改成功的文件,都是文件名里含有unicode的。应该是rename操作不了这样的文件。
不知道楼上说的winapi能否完成,继续求解决方案。因为新手刚入门,大神们有方案的请具体一些,用到哪些API,包含在哪些库文件内。谢谢!
2014-2-2 23:25
0
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
这代码没法看 受不了
2014-2-3 00:14
0
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这种时候还是多看看Win32程序设计相关的书吧
2014-2-3 07:18
0
雪    币: 151
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
Python曾经写过一个,winapi  MoveFile
2014-2-3 09:39
0
雪    币: 297
活跃值: (265)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
10
,,,,批处理多方便啊,
2014-2-3 10:05
0
雪    币: 6528
活跃值: (3539)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
有专门的改名软件你不用,Bulk Rename Utility 改这个很简单
2014-2-3 10:13
0
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
C函数这方面错误处理少了,而且个人感觉不是太可靠,用Win32 api可能好些。
鄙人拙见,望指教。
2014-2-3 11:05
0
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
把楼主的代码格式化了下。

#include <io.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <windows.h>

int main()
{
    long               Handle = 0;
    struct _finddata_t FileInfo;
    char               newname[512][7] = {0};
    char               oldname[512][70] = {0};
    char               s1[100];   // 此数组的意思?
    char              *p = newname;
    char               rm[] = ".rm";
   
    int i = 0, j = 0, k = 0;

    if( (Handle = _findfirst("D:\\db2\\db2\\*.rm", &FileInfo)) == -1L )
    {
        printf("没有找到匹配的文件\n");
    }
    else
    {
        strcpy(p, FileInfo.name);  // 这一段p为什么频繁赋值
        p = oldname;
        strcpy(p, FileInfo.name);
        p = newname;  // 这四句表示不解其意
        
        for(i = 0; i < strlen(FileInfo.name) - 3; i++)
        {
            p[i + 3] = NULL;  // 这是要清空吗?因为是char类型的,最好用'\0'
        }
        
        j = atoi(p);
        j = j + 152;
   
        sprintf(p, "%03d", j);
        strcat(p, rm);
        //printf("%s     %s\n",oldname[0],newname[0]);

        for(k = 1; (_findnext(Handle, &FileInfo) == 0); k++)
        {
            p = oldname[k];
            strcpy(p, FileInfo.name);
            p = s1;
            strcpy(p, FileInfo.name);  // ??
      
            for(i = 0; i < strlen(FileInfo.name) - 3; i++)
            {
                p[i+3]=NULL;
            }
      
            j = atoi(p);
            j = j+152;
            sprintf(p, "%03d", j);
            strcat(s1, rm);
            p = newname[k];
            strcat(p, s1);
        }
        
        _findclose(Handle);
    }
    for (i = 0; i < 291; i++)   // 291?
    {
        //printf("%s     %s\n", oldname[i], newname[i]);
        rename(oldname[i], newname[i]);
        Sleep(500);
    }
   
    getchar();
    return 0;
}

/* 编译错误如下,环境VC6 */
//--------------------Configuration: 新建文本文档 - Win32 Debug--------------------
//Compiling...
//新建文本文档.cpp
//o:\users\administrator\desktop\新建文本文档.cpp(14) : error C2440: 'initializing' : cannot convert from 'char [512][7]' to 'char *'
//        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
//o:\users\administrator\desktop\新建文本文档.cpp(26) : error C2440: '=' : cannot convert from 'char [512][70]' to 'char *'
//        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
//o:\users\administrator\desktop\新建文本文档.cpp(28) : error C2440: '=' : cannot convert from 'char [512][7]' to 'char *'
//        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
//o:\users\administrator\desktop\新建文本文档.cpp(30) : warning C4018: '<' : signed/unsigned mismatch
//o:\users\administrator\desktop\新建文本文档.cpp(49) : warning C4018: '<' : signed/unsigned mismatch
//执行 cl.exe 时出错.
//
//新建文本文档.obj - 1 error(s), 0 warning(s)
2014-2-3 11:18
0
雪    币: 254
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
谢谢sunnysab兄的指导,因为是新手,加上本来以为程序很简单。没有考虑结构问题,可能把一些代码写成函数来调用,要简洁得多。所以让各位看晕了。我用VC2010可以编译成功,但是会收到char *与char *[7]的间接级别不同的警告char *p 和s1是我用来转换就文件名字符串临时存放的(就是旧文件名保留前面3个数字后面的全部填0),然后转换好了,在strcpy给新文件名字符串。新旧文件名都好了再用rename改名

继续等如何解决文件名中含有UNICODE导致rename无法操作的问题。楼上的说用MoveFile api的能说具体一点吗,对于API本菜鸟只是略有了解。尝试了下包含windows.h 然后movfile(oldnane[i],newname[i]);没有任何反应,调用getlasterror返回02.
2014-2-3 11:31
0
雪    币: 438
活跃值: (93)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
这个,用个批处理写比较给力。Perl也比用c写好吧。。。
2014-2-3 12:11
0
雪    币: 35
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
觉得还是用批处理来做这个最方便了。
2014-2-3 15:09
0
雪    币: 36
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
如果要自己写的话 按楼上各位说的 cmd脚本是最快的 command prompt里的通配符已经够用了

我不太懂C语言 所以看不来错误 但是我一般都用这个基于正则表达式的改名软件

文件批量改名 1.0 http://www.chken.com/ViewSoft.asp?id=19

用正则表达式改名
第二部动漫改名
表达式 (\d{3})(.*)
新名称 \1.rm
2014-2-3 15:34
0
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
指导谈不上,自己也同时练练手嘛。刚才写的,没有读源文件名中的序号之类的。
其实自己代码写的也很糟糕。

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

#define   MAX_FILE   100    // 最大储存的文件数
#define   MAX_LEN    100    // 文件名最大长度

int main()
{

    int  i = 0;  // 累计找到的
    int  j = 153; // 第二部文件名
    unsigned long    ErrorCode = 0;  // 错误代码,凭此判断循环的结束
                                     // See: http://pegasus827.bokee.com/6312983.html
    WIN32_FIND_DATA  FileInfo;  // 存储文件信息
    HANDLE  hSreach = INVALID_HANDLE_VALUE;  // 搜索的句柄

    char   OldName[MAX_FILE][MAX_LEN];

    memset(OldName, 0, MAX_FILE * MAX_LEN);
    memset(&FileInfo, 0, sizeof(WIN32_FIND_DATA));  // 清空结构,防止无效数据

    hSreach = FindFirstFile("R:\\*.rm", &FileInfo); // 找第一个文件
    if (hSreach == INVALID_HANDLE_VALUE) // 句柄无效
    {
        printf("搜索失败,错误代码:%d\n", (ErrorCode = GetLastError()) );

        // 错误代码为0x02,提示找不到文件
        if (ErrorCode == 0x02)
        {
            printf("找不到文件\n");
        }
        return ErrorCode;
    }

    do
    {
        // 过滤
        if (strcmp(FileInfo.cFileName, ".") != 0
            || strcmp(FileInfo.cFileName, "..") != 0)
        {
            printf("文件: %s\n", FileInfo.cFileName);

            // 防止溢出,使用strncpy
            strncpy(OldName[i], FileInfo.cFileName, MAX_LEN);
            if (i == MAX_LEN - 1)  // OldName装满了
            {
                printf("文件搜索数已达上限!\n");
                //return 0;
                break;
            }
            i++;
        }
        // 查找下一个文件
        FindNextFile(hSreach, &FileInfo);
    }
    while ( (ErrorCode = GetLastError()) != ERROR_NO_MORE_FILES );

    /* 总算找完了,Windows会自动帮我们排序,可以不用从第二部中提取文件名上的编号了吧? */
    printf("搜索完毕!\n");

    CloseHandle(hSreach);

    int  k = 0;  // 循环变量
    for(; k <= i; k++)
    {
        char  src[MAX_LEN] = "";  // 源文件名
        char  dst[MAX_LEN] = "";  // 新文件名

        sprintf(src, "R:\\%s", OldName[k]);
        sprintf(dst, "R:\\%d.rm", j++);

        printf("将 %s 改名为 %s\n", src, dst);
        MoveFile(src, dst);
    }

    printf("改名完毕!\n");

    return ErrorCode;
}
2014-2-3 17:58
0
雪    币: 254
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
试了下上面的MoveFile,貌似仍然没有动静,正在找原因,不管怎么样,先谢谢了,如果没有更好的方案,分就给你了。
2014-2-4 20:00
0
雪    币: 254
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
测试了下,MOVFILE可以成功。但是MoveFile的两个字符串指针参数必须是宽字符型的。用Char *定义的字符指针是不能直接用在里面的,否则就会收到找不到文件的错误。而如何定义和操作这样字符串小弟还没经验,慢慢试吧。包含了<tchar.h>用static wchar_t *指针名=_T("字串内容“);这样定义的字串可以操作以前改不了的文件名。方法都是网上找的现学现用,看来还得继续努力,再次感谢~
2014-2-4 23:09
0
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
才看到您的回复。
我在测试的时候也发现MoveFile()没有用,后来才发现原因:在这个例子中,因为程序和文件不在一起,所以MoveFile()的两个参数需要用绝对路径,后来就加上了那几行代码。
这段程序在我这可以使用,win7 32位 + VC6

同时新手,互相学习!加油!
2014-2-6 15:07
0
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
VC2008,2010用过,对于宽字符和类型就开始比较严格了,还是舍不得VC6,呵呵!VC2010里面写不了MFC程序吧?选哪一项?我以前用的是2010学习版

主要是电脑带不动……
2014-2-6 15:12
0
雪    币: 61
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
怎么会写不了MFC啊,选择VC下的MFC就行了啊
2014-2-6 16:02
0
雪    币: 80
活跃值: (109)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
24
那就奇怪了,我的那个版本没有MFC选项……
2014-2-7 11:32
0
雪    币: 3496
活跃值: (749)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
关注一下,改名还是挺实用的。用VB中FSO可能也行。
2014-3-13 12:44
0
游客
登录 | 注册 方可回帖
返回
//