您的位置:首页 > 运维架构 > Linux

c语言自动删除cpp文件中的注释 使用代码删除注释【Linux、mac下】

2014-03-20 18:48 751 查看
当代码写完的时候。有时候我们想要删除其中的注释,如果在源文件中一个一个地找,那么会耗费大量的时间。于是我写了一个方法自动读取cpp文件并且找到其中的注释的语句,把它删除。下面是我的函数。

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#define  NULLCHAR  32       //ascii字符的32表示空字符

void delComments(const char *path);

int main(int argc, const char * argv[])
{
delComments("/Users/zctech/Desktop/1.cpp");
return 0;
}

//删除注释.path:文件名
void delComments(const char *path)
{

int fd = open(path, O_RDWR);

//获取文件大小
struct stat sb;
fstat(fd, &sb);

unsigned char *start = (unsigned char *)mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(start == MAP_FAILED) /* 判断是否映射成功 */
{
printf("映射失败,文件过大或者没有权限");
return;
}
printf("%s", start);

//判断是否为 【/**/】 型注释, 注意当是字符串的时候不替换
unsigned long i = 0;
bool isCom = false;
bool isStr = false;

while (i < sb.st_size)
{
if(!isStr && '/' == *(start + i) && '*' == *(start + i + 1))
{
isCom = true;
}
else if(!isStr && '*' == *(start + i) && '/' == *(start + i + 1))
{
isCom = false;
*(start + i) = *(start + i + 1) = NULLCHAR;
}
else if(!isCom && !isStr && '\"' == *(start + i))
{
isStr = true;
}
else if(!isCom && isStr && '\"' == *(start + i))
{
isStr = false;
}

//移除注释
if (isCom && !isStr)
{
*(start + i) = NULLCHAR;
}
i++;
}

//判断是否为【//】 型注释, 注意当是字符串的时候不替换
i = 0;
isCom = false;
isStr = false;
while (i < sb.st_size)
{
if(!isStr && '/' == *(start + i) && '/' == *(start + i + 1))
{
isCom = true;
}
else if(!isStr && '\n' == *(start + i))
{
isCom = false;
}
else if(!isCom && !isStr && '\"' == *(start + i))
{
isStr = true;
}
else if(!isCom && isStr && '\"' == *(start + i))
{
isStr = false;
}

//移除注释
if (isCom && !isStr)
{
*(start + i) = NULLCHAR;
}

i++;
}

close(fd);
munmap(start, sb.st_size); /* 解除映射 */

}


下面是test.cpp文件中原来的内容
//#include <stdio.h>
//这是我的注释
int main()
{
    printf("///**/");
    printf("//000");
    int a =
//test;
    return
0;
}

执行后,重新打开test.cpp,发现文件内容如下:

int main()
{
    printf("///**/");
    printf("//000");
    int a =        
    return
0;
}
我们发现,注释已经被删除了!!!!!

很好,这样我们就删除了一个文件中的注释了。但是如果我们要删除一个文件夹下所有cpp文件的注释呢?以linux或者mac系统为例,我们增加遍历文件夹函数。

下面的例子是删除桌面上Classes文件夹下所有.c  .cpp 和 .h 文件的 注释。批量删除!!!

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/dir.h>

#define  NULLCHAR  32       //ascii字符的32表示空字符

//删除注释.path:文件路径全名
void delComments(const char *path);

//判断是否为目录.path:文件路径全名
bool isDir(const char* path);

//删除文件夹下所有.c, cpp, .h的注释
void delComInDir(const char *path);

//删除文件夹下所有.c, cpp, .h的注释,这是递归方法
void delComInDir(const char *path, int recursive);

//取文件名的后缀名
const char *getSuffix(const char *path);

//取子串
char* substr(const char*str, unsigned long start, unsigned long end);

int main(int argc, const char * argv[])
{
delComInDir("/Users/zctech/Desktop/my/cocos2d-x-2.2.2/projects/myGame1/Classes");
return 0;
}

//判断是否为目录.path:文件路径全名
bool isDir(const char* path)
{
struct stat st;
lstat(path, &st);
return 0 != S_ISDIR(st.st_mode);
}

//删除文件夹下所有.c, cpp, .h的注释
void delComInDir(const char *path)
{
unsigned long len;
char temp[1024 * 512];
//去掉末尾的'/'
len = strlen(path);
strcpy(temp, path);
if(temp[len - 1] == '/') temp[len -1] = '\0';

if(isDir(temp))
{
//处理目录
int recursive = 1;
delComInDir(temp, recursive);
}
else   //输出文件
{
//找出.h和.cpp文件
if(0 == strcmp("h", getSuffix(temp)) || 0 == strcmp("cpp", getSuffix(temp)) || 0 == strcmp("c", getSuffix(temp)))
{
delComments(temp);
printf("%s\n", temp);
}

}

}

//遍历文件夹de递归函数
void delComInDir(const char *path, int recursive)
{
DIR *pdir;
struct dirent *pdirent;
char temp[256];
pdir = opendir(path);
if(pdir)
{
while((pdirent = readdir(pdir)))
{
//跳过"."和".."
if(strcmp(pdirent->d_name, ".") == 0
|| strcmp(pdirent->d_name, "..") == 0)
continue;
sprintf(temp, "%s/%s", path, pdirent->d_name);

//当temp为目录并且recursive为1的时候递归处理子目录
if(isDir(temp) && recursive)
{
delComInDir(temp, recursive);
}
else
{
//找出.h和.cpp文件
if(0 == strcmp("h", getSuffix(temp)) || 0 == strcmp("cpp", getSuffix(temp)) || 0 == strcmp("c", getSuffix(temp)))
{
delComments(temp);
printf("%s\n", temp);
}
}
}
}
else
{
printf("opendir error:%s\n", path);
}
closedir(pdir);
}

//删除注释.path:文件名
void delComments(const char *path)
{

int fd = open(path, O_RDWR);

//获取文件大小
struct stat sb;
fstat(fd, &sb);

unsigned char *start = (unsigned char *)mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(start == MAP_FAILED) /* 判断是否映射成功 */
{
printf("映射失败,文件过大或者没有权限");
return;
}
printf("%s", start);

//判断是否为 【/**/】 型注释, 注意当是字符串的时候不替换
unsigned long i = 0;
bool isCom = false;
bool isStr = false;

while (i < sb.st_size)
{
if(!isStr && '/' == *(start + i) && '*' == *(start + i + 1))
{
isCom = true;
}
else if(!isStr && '*' == *(start + i) && '/' == *(start + i + 1))
{
isCom = false;
*(start + i) = *(start + i + 1) = NULLCHAR;
}
else if(!isCom && !isStr && '\"' == *(start + i))
{
isStr = true;
}
else if(!isCom && isStr && '\"' == *(start + i))
{
isStr = false;
}

//移除注释
if (isCom && !isStr)
{
*(start + i) = NULLCHAR;
}
i++;
}

//判断是否为【//】 型注释, 注意当是字符串的时候不替换
i = 0;
isCom = false;
isStr = false;
while (i < sb.st_size)
{
if(!isStr && '/' == *(start + i) && '/' == *(start + i + 1))
{
isCom = true;
}
else if(!isStr && '\n' == *(start + i))
{
isCom = false;
}
else if(!isCom && !isStr && '\"' == *(start + i))
{
isStr = true;
}
else if(!isCom && isStr && '\"' == *(start + i))
{
isStr = false;
}

//移除注释
if (isCom && !isStr)
{
*(start + i) = NULLCHAR;
}

i++;
}

close(fd);
munmap(start, sb.st_size); /* 解除映射 */

}

//求子串
char* substr(const char*str, unsigned long start, unsigned long end)
{
unsigned long n = end - start;
static char stbuf[1024];
strncpy(stbuf, str + start, n);
stbuf
= 0;                           //字串最后加上0
return stbuf;
}

//取文件名的后缀名
const char *getSuffix(const char *path)
{
char *ptr;
long pos;
ptr = strrchr(path, '.');    //最后一个出现c的位置
if(!ptr)return "";
pos = ptr - path;             //用指针相减 求得索引

return substr(path, pos + 1, strlen(path));
}


当如如果要删除#pragma这样的注释的话,只要在
void delComments(constchar *path)这个函数中加上# p r a g m a7六个字符的判断即可,如下:

if(!isStr && '#' == *(start + i) &&'p' == *(start + i +1) &&'r' == *(start + i +
2) && 'a' == *(start + i +3) &&'g' == *(start + i +4) &&
'm' == *(start + i + 5) &&'a' == *(start + i +6))
        {
            isCom = true;
        }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐