* erase.cpp
*
* Created on: 2013/6/6
* Author: YYP
*/
#include <iostream>
#include <io.h>
#include <stdio.h>
#include<fcntl.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
void remove_comment(char *buf, size_t size) {
char *p, *end, c;
char* sq_start, *dq_start;
//single qote單引號開始
//double qoute雙引號開始
char* lc_start, *bc_start;
//lc_start:(//)狀況用,指向斜線當作標記
//bc_start:(/*)狀況用,指向斜線當作標記
size_t len;
p = buf;
//檔案初始位置
end = p + size;
//檔案結尾=檔案初始+檔案大小
sq_start = NULL; //單引號 single quote
dq_start = NULL; //雙引號 double quote
lc_start = NULL;
bc_start = NULL;
while (p < end) {
c = *p; //p指向的字元assign給c
switch (c) {
case '\'': //單引號
if (dq_start || lc_start || bc_start) {
//忽略字串與注視中的單引號
p++; //不做任何事,指標移動到下一個
continue;
}
if (sq_start == NULL) {
sq_start = p++;
} else {
len = p++ - sq_start;
if (len == 2 && *(sq_start + 1) == '\\') { //忽略字元中的單引號
continue;
}
sq_start = NULL;
}
break;
case '\"': //遇到雙引號
if (sq_start || lc_start || bc_start) {
p++;
continue;
}
if (dq_start == NULL) {
dq_start = p++;//dq_start指向第一個引號(標記起來),
//之後p往後移動
} else {
if (*(p++ - 1) == '\\') {
//p-1若是斜線
//忽略字串中的雙引號
continue;
}
dq_start = NULL;//在這邊p已經指到第2n個雙引號
//在code裡面雙引號表示字串 雙雙城隊
//所以這裡要將dq_start=NULL
}
break;
case '/': //遇見斜杠
if (sq_start || dq_start || lc_start || bc_start) {
//會進入這裡表示目前的斜線是被包在字元字串注釋之中
//忽略自串字元或注釋中的斜線
p++;
continue;
}
c = *(p + 1);//斜線的下一個字元,丟給C
if (c == '/') {//如果c是斜線
//有進入這裡就表示雙斜線了
lc_start = p;
//標記第一個斜線
p += 2;
//指標移動兩字元,指向雙斜線之後的字元
} else if (c == '*') {
bc_start = p;
//標記斜線
p += 2;
} else {
//進入這裡就表示該斜線是除號
p++;
}
break;
case '*'://遇到星號
if(sq_start|| dq_start||lc_start||bc_start==NULL)
{ //bc_start不為NULL表示目前p已經指向區塊註解的第一個斜線
//忽略字元、字串或行注釋的星號 還有忽略乘號
p++;
continue;
}
if(*(p+1)!='/')//下一個字元不是斜線"/",也就是說現在的星號不是區塊註解尾端
{
//游標繼續移動,這個星號並非刪除的標的物
//可能是乘號或指標
p++;
continue;
}
p+=2;//p往後移動兩個字元,跳過星號與反斜線(*)
//這樣做是因為要連同將區塊註解符號刪掉
memset(bc_start,' ',p - bc_start);
//將bc_start之後的p-bc_start區塊,全部變成空白自原
bc_start=NULL;
//恢復原狀
break;
case '\n': //遇到分行符號
if(lc_start == NULL){
//lc_start專門指向單行註解,雙斜線之後的第一個字元
//如果遇到單行註解,那麼lc_start不會是NULL
p++;
continue;
}
c=*(p-1);// 反斜線n(\n)的前面是哪個字元
memset(lc_start,' ',(c=='\r'?(p++ -1 ):p++)-lc_start);
//從lc_start開始之後的(c=='\r'?(p++ -1 ):p++)-lc_start字元換成空白字元
//因為windows與linux文字文件換行字元布一樣所以要c=='\r'?(p++ -1 ):p++)
lc_start=NULL;
//清掉註解之後,lc_start就不用標記斜線了
break;
default:
p++;
break;
}
}//while
if(lc_start){
memset(lc_start,' ',p - lc_start);
}
}
int main() {
int fd, n;
char buf[102400];
//裝載102400個字元,讀取檔案太大,會執行不完
fd = open("D:\\uuu.txt", _O_RDONLY, 0);
//open是fcntl.h裡面的東西
//open回傳檔案代號,如果沒有檔案則回傳-1
if (fd == -1) {
cout << "file not open" << endl;
return -1;
}
n = read(fd, buf, sizeof(buf));
//read(檔案,存放點,讀進多少個字元);
//read()回傳讀進多少字元
if (n == -1 || n == 0) {
close(fd);
return -1;
}
remove_comment(buf, n);
*(buf + n) = '\0';
//在buf最末端加上\0以示檔案結束
//不加上此行,printf(buf)會印出,刪掉註解前的部分檔案資訊
printf(buf);
close(fd);
// cout << "file open" << endl;
return 0;
}
沒有留言:
張貼留言