C程序设计语言练习1-23 编写一个删除C语言程序中所有的注释语句,要正确处理带引号的字符串与字符常量,以C语言中,注释不允许嵌套。
本程序运行后,将要求用户输入一个当前目录下的C源码程序文件名,读取后,将文件中的所有注释删除掉。
将另存为*_noc.ext文件,*中可以包含多个点,.ext可以为空(即没有文件扩展名)。
编辑C源码:
User@User-PC MINGW32 /d/mycode/c/krc
$ vim k0137.c
/* 读取一个C源码文件,将其中的注释全部删除掉,并保存为新文件*_noc.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXLEN 100 //文件名称最大长度
#define FILEMAXLEN 10000 //文件内容最大长度
int readline(char str[]);
int newfilename(char file[],int len);
int main(void){
FILE *fp;
char ch,file[MAXLEN],content[FILEMAXLEN];
int len,i=0;
int lastpos=-1;//第一个斜线的位置
int iscomment=0;//是注释标志位
int isstring=0;//是字符串内
char strstart;//开始的字符串是单引号还是双引号
printf("读取当前目录下的文本文件,请输入文件名:\n");
while((len=readline(file))>0) {
if((fp=fopen(file,"rt"))==NULL){
printf("文件打开错误,请重新输入:\n");
}else{
while((ch=fgetc(fp))!=EOF){
if(isstring==1){
//字符串内,查找字符串结束字符,且其前一个字符不能是反斜线
if(ch==strstart&&content[i-1]!='\\'){
isstring=0;
}
content[i]=ch;
++i;
}else if(iscomment==2){
//多行注释,查找多行注释的结束符
if(ch=='/'){
if(i-lastpos==1){
iscomment=0;
}
}else if(ch=='*'){
lastpos=i;
}
}else if(iscomment==1){
//单行注释,查找换行符
if(ch=='\n'){
iscomment=0;
content[i]=ch;
++i;
}
}else{
content[i]=ch;
if(ch=='*'){
if(i-lastpos==1){
iscomment=2;
i-=2;//多行注释的开始符号要删除
}
}else if(ch=='/'){
if(i-lastpos==1){
iscomment=1;
i-=2;//单行注释的两个斜线要删除
}else{
iscomment=0;
lastpos=i;
}
}else if(ch=='\''||ch=='"'){
isstring=1;
strstart=ch;
}
++i;
}
}
fclose(fp);
content[i]='\0';//fputs写入文件的字符串以'\0'结束
printf("\n\n新文件的内容:\n");
i=0;
while((ch=content[i])!='\0'){
putchar(ch);
++i;
}
len=newfilename(file,len);
printf("是否保存新文件%s?(y/n):",file);
while((ch=getchar())!='y'&&ch!='n');
if(ch=='y'){
if(len>0){
fp=fopen(file,"w+");
fputs(content,fp);
fclose(fp);
printf("文件已成功保存!\n");
ch=getchar();
}
}
}
printf("请输入新的文件名:\n");
}
return 0;
}
/*
将文件名更改为*_noc.ext,.ext可以为空,*中可以包含点.
*/
int newfilename(char file[],int len){
int i,j,c;
int extflag=0,newlen=0;
char newfile[MAXLEN];
//printf("\nfile:%s,len:%d\n",file,len);
for(i=len-1,j=0;i>=0;--i,++j){
c=file[i];
newfile[j]=c;
if(extflag==0&&c=='.'){
++j;newfile[j]='c';
++j;newfile[j]='o';
++j;newfile[j]='n';
++j;newfile[j]='_';
extflag=1;
}
}
newfile[j]='\0';
if(j==len){
//文件没有后缀名称,则直接在后面加上_noc
i=len;
file[i]='_';
++i;file[i]='n';
++i;file[i]='o';
++i;file[i]='c';
++i;
}else{
newlen=j;
for(i=0,j=newlen-1;j>=0;--j,++i){
file[i]=newfile[j];
}
}
file[i]='\0';
return i;
}
/*
读取文件名,不需要后面的\n
*/
int readline(char str[]){
int i,c;
for(i=0;i<MAXLEN-1&&(c=getchar())!=EOF&&c!='\n';++i){
str[i]=c;
}
str[i]='\0';
return i;
}
编译生成可执行文件
User@User-PC MINGW32 /d/mycode/c/krc
$ gcc -o k0137 k0137.c
运行测试
User@User-PC MINGW32 /d/mycode/c/krc
$ ./k0137
读取当前目录下的文本文件,请输入文件名:
hello.c
新文件的内容:
#include <stdio.h>
int main(void){
printf("hello world!\n");
printf("世界你好!\n");
return 0;
}
是否保存新文件hello_noc.c?(y/n):y
文件已成功保存!
请输入新的文件名:
User@User-PC MINGW32 /d/mycode/c/krc
$
hello.c文件内容:
User@User-PC MINGW32 /d/mycode/c/krc
$ vim hello.c
/* C源码文件:helloworld */
#include <stdio.h>
int main(void){
printf("hello world!\n");
printf("世界你好!\n");//查看显示中文是否正常
return 0;
}