分析:一次讀取一行,分兩種情況,因為有兩種注釋:
(1)在讀取到的一行中查找“//”,如果找到,則把“//”及其后的部分扔掉。
(2)在讀取到的一行中查找“/*”,記錄位置pos1,然后再在這行中查找“*/”,如果找到,也記錄位置pos2,扔掉它們與其中的內容,以pos2開始,繼續查找“/*”;如果在當前行中沒有找到,則去掉當前行中“/*”及其后的內容,讀取新的一行,查找“*/”,如沒有。則去掉讀取到的這一行,再讀一行,查找“*/”,如找到,記錄位置pos2,去掉這一行的0到pos2之間的字符。
(3)進行步驟1、步驟2,直到程序結束。
編程時要考慮的特殊情況i:
“”中的“//”“/*”
''中的“//”“/*”
“//”與“/*”的嵌套關系,比如///* 、/* //*/ *********************************************************/
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <unistd.h>#include <sys/types.h>void remove_comment(char *buf, size_t size){ char *p, *end, c; //p-動態移動的字符指針,end-指向文件末尾的字符指針,c-存儲沒一個p指向的字符 char *sq_start, *dq_start; //sq_start-單引號開始位置(single),dq_start-雙引號開始(double) char *lc_start, *bc_start; //lc_start-//的開始位置,bc_start-/*的開始位置 size_t len; //記錄某符號結束和開始的位置之差(長度,偏移量) p = buf; end = p + size; sq_start = dq_start = NULL; lc_start = bc_start = NULL; while (p < end) /*當指針沒有到達文件末尾 */ { c = *p; //用字符變量c存儲指針指向的字符 switch (c) //根據c的值做相應處理 { case '/'': /*處理單引號*/ { if (dq_start || lc_start || bc_start) //當遇到過雙引號、//或/*的時候,則不需要再判斷'//'的情況了。 { p++; continue; //繼續下一個,對while而言的 } /*******************************以下是沒有遇到過雙引號或//或/*的時候*******************************/ if (sq_start == NULL) /****如果未遇到單引號****/ { sq_start = p++; //start指向單引號的開始位置,p指向下一個</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:tahoma,arial,宋體,sans-serif; font-size:15px; line-height:18px"> } else /*如果遇到過單引號,sq_start指向單引號開始位置*/ { len = (p++) -sq_start; if (len == 2 && *(sq_start+1) == '//'){ /*若遇到 “ '/'' ”這種情況則兩個單引號并未匹配,遇到的“'”是“/' ”中的,而不是與sq_start所指向單引號匹配*/ continue; } sq_start = NULL; //否則將sq_start置位為NULL } /*******************************以上是沒有遇到過雙引號或//或/*的時候*******************************/ break; } case '/"': /*處理雙引號*/ { if (sq_start || lc_start || bc_start) //當遇到過單引號、//或/*的時候,則不需要處理 { p++; continue; } /*****************以下是沒有遇到過單引號或//或/*的時候*****************/ if (dq_start == NULL) /*如果沒有遇到過雙引號*/ { dq_start = p++; //標記遇到了雙引號 } else if (*((p++) -1) =='//') /*若遇到 “" ab/''cd" ”這種情況則兩個雙引號并未匹配,遇到的“"”是“/"”中的,而不是與dq_start所指向雙引號匹配*/ continue; } dq_start = NULL; //如果雙引號中不是//,標記為NULL /*****************以上是沒有遇到過單引號或//或/*的時候*****************/ } case '/': //斜杠,注意這個斜杠也可以是'//',"//",//,/*/中的第二個斜杠,但會在下面第二行代碼中被忽略掉 { if (sq_start || dq_start || lc_start || bc_start) //如果是單引號、雙引號、斜杠、/*的后面 { p++; continue; } /***********************下面是遇到注釋//或/*的時候****************************/ c = *(p + 1); //否則c取p指向字符的下一個字符 if (c == '/') //遇到了雙斜杠 { lc_start = p; //標記雙斜杠的開始 p += 2; //p指向雙斜杠后面的字符 } else if (c == '*') //遇到了/* { bc_start = p; //標記/*的開始 p += 2; //p指向/*后面的字符 } /*************************上面是遇到注釋//或/*的時候**************************/ else { p++; } } case '*': //星號,同斜杠,但少了如果遇到/*的情況,因為遇到這種情況后,要判斷是不是遇到結束的地方*/了 { if (sq_start || dq_start || lc_start) //如果是單引號、雙引號、斜杠、/*的后面 { p++; continue; } if (*(p + 1) != '/') //如果星號后面緊跟的不是斜杠,那么忽略過。 { p++; continue; } p += 2; //否則p指向斜杠后面那個字符。注意下面的清空語句,p指向的那個字符并不會被清除。 memset(bc_start, ' ', p-bc_start); //清空/* …… */中間的內容包括注釋符號本身。 bc_start = NULL; break; } case '/n': /*換行符,主要處理遇到雙斜杠時,需要清除雙斜杠到/n的前面的字符*/ { if (lc_start == NULL) //如果還沒有遇到雙斜杠,那么忽略 { p++; continue; } c = *(p - 1); /*如果遇到過雙斜杠,清空雙斜杠本身和到/n前面的那個字符,p指向下一個字符,/r是回車符(光標退回到最前面),這里要判斷</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:tahoma,arial,宋體,sans-serif; font-size:15px; line-height:18px"> c == '/r'是因為在UNIX系統下文件結尾的換行只有/n,而windows系統下文件結尾的換行為/r/n */</p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:tahoma,arial,宋體,sans-serif; font-size:15px; line-height:18px"> memset(lc_start, ' ', (c == '/r'? ((p++) -1) : p++) - lc_start); lc_start = NULL; break; } default: p++; break; } /**************************************************** 如果遇到雙斜杠,這個if語句存在的意義在于萬一最后 一行代碼是帶有雙斜杠但沒有給換行符/n的,也要清除掉。 *****************************************************/ if (lc_start) { memset(lc_start, ' ', p - lc_start); } }}/********************************************** main函數的開始***********************************************/int main (int argc, char *argv[]){ int fd, n; char buf[102400]; if (argc != 2) { PRintf("command error: Input as ./command <file>/n"); } fd = open(argv[1], O_RDONLY); /*只讀打開*/ if (fd == -1) { return -1; } n = read(fd, buf, sizeof(buf)); if (n == -1 || n == 0) { close(fd); return -1; } printf("test/n"); remove_comment(buf, n); *(buf + n) = '/0'; printf("%s", buf); close(fd); return 0;}
新聞熱點
疑難解答
圖片精選