//strTools.c -- some utility functions about string processing /// @CopyLeft by tsaiwn@csie.nctu.edu.tw ////// 更多關於字串處理的函數 -- more string processing functions ///字串(string)在 C 語言其實就是用 0 ('\0')結束的一串字符(char)! /// 了解這觀念後, 要對字串處理應該就能得心應手了! /// 之前我們看過了 isalpha, isdigit, tolower, toupper 等, //也看過了 strlen,strcmp, strcpy,strncpy,strcat 等程式庫都很簡單! /// *本範例中共寫了 10 個很常用的字串處理 functions (不在程式庫), /// (有些之前已給過大家, 重新整理在這方便大家收藏:) /// 以後若你的工作是寫程式, 這些 functions 將會很有用 :-) /// 自己想一下, 如何寫 int startWith(char*s, char*pat); ? /// === === === #include #include #include /// 用 macro 定義一些常用看起來像"函數", 但其實是 Macro(巨集) #define max(x, y) ((x)>(y)) ? (x) : (y) #define min(x, y) ((x)<(y)) ? (x) : (y) /// 模仿 Pascal Language 的 repeat ... until #define repeat do { #define until(x) } while(!(x)); /// Declare 先宣告 char* chop(char*); // 咬掉尾巴的 NewLine '\n' if any char* squeeze(char*); // 擠掉所有的空白 (white space) char* toLower(char*p), *toUpper(char*); char* trim(char*p), *trimLeft(char*), *trimRight(char*); int sIndex(char*s, char*pat); // position of pat in s char* substr(char*s, int start, int n); // MID$(s, start, n) char* sqz22(char*); // 去掉頭尾空白, 中間則把多空白變只留一空格 /// char* chop(char*p) { // remove tail '\n' ; by tsaiwn@csie.nctu char* pOLD = p; if(p[0] == 0) return p; // NULL string while(p[0] != 0) ++p; // 到字串結束的 NULL char; p[0]就是 *p --p; // move back to the last char if(*p == '\n') *p = 0; // remove the newLine if it is return pOLD; }// chop( char* toLower(char*p){ int i; for(i=0; i< strlen(p); i++) p[i]= tolower(p[i]); return p; } // toLower char* toUpper(char*p){ char* pOLD = p; while(*p) { // *p != 0 *p = toupper(p[0]); // p[0] 就是 *p ++p; } return pOLD; } // toUpper char* squeeze(char*p) { // 擠掉所有空白 char*pOLD = p; char*p2 = p; while(*p) { // p[0] != 0 if( isspace(*p) ) { p++; continue; } *p2 = *p; ++p2; p++; } // while *p2 = 0; // NULL terminated return pOLD; } // squeeze( char* trimLeft(char*p) { // 去掉 Leading Blanks char*pOLD = p; char*p2 = p; while(*p && isspace(*p) ) ++p; // till nonSpace while(*p) { // till end of the string *p2 = *p; p2++; ++p; }//while *p2 = 0; // NULL terminated return pOLD; } // trimLeft char* trimRight(char*p) { // 只去掉尾巴的空白 char*p2 = p; if(*p == 0) return p; // EMPTY string while(*p2) ++p2; // found the end of string p --p2; // back one char while( p2 != p) { if( !isspace(*p2) ) break; // 不是空白, Done ! *p2 = 0; // 去掉尾巴 white space --p2; }//while return p; // 正確 OK } // trimRight char* trim(char*p) { // 去掉頭部(Leading)空白和尾巴的空白 trimRight(p); return trimLeft(p); // 注意 trim 不去管中間的空白喔 ! } // trim( int sIndex(char*s, char*pat) { // find position of pat in s char* p = strstr(s, pat); // find pat in s if(p == 0) return -1; // not found return p - s; // position 0..n-1 } // kIndex( char* substr(char*s, int start, int len) { // sub string 從 s[start] 開始的 len 個 char char* p = malloc(len+1); // 宣告在 內 p[len] = 0; // NULL terminated, 萬一真的 n 字還沒結束 :-) strncpy(p, s+start, len); // copy最多len字從 s+start 到 p return p; // MID$(s, start, len); // Note that this might cause memory leaking ! } // substr 注意與 Java 的 String 的 substring 用法不同喔! char* sqz22(char*s) { int hasSpace; char*pOLD=s, * p = s; // 注意這寫法, 不然寫成兩句 ! char* p2 = s; // p2 points to s[0] too trim(s); // remove leading blanks, and trailing blanks hasSpace = 0; // no space now while(*p) { if( isspace(*p) ) { if(hasSpace) { ++p; continue; } // skip it *p2 = ' '; // 換成真的空格, 不管原來是啥空白符號 hasSpace = 1; // FLAG on }else{ hasSpace = 0; // reset the FLAG, 不必管它原來怎樣! *p2 = *p; // 這 char 當然要囉 } // if ++p2; p++; }// while *p2 = 0; // NULL terminated return pOLD; } // sqz22( #include int main( ) { static char ss[ ]=" a b c123 4 5 678 "; static char tmps[99]; // temporary string char gg[ ] = "abcde1234567"; // array of char == string char *yy = "HaHeeABC135"; // yy points to a string printf("gg=%s\nyy=%s\n", gg, yy); printf("substr(gg, 3, 5)=%s\n", substr(gg, 3, 5) ); printf("substr(gg, 9, 5)=%s\n", substr(gg, 9, 5) ); printf("substr(yy, 2, 3)=%s\n", substr(yy, 2, 3) ); printf("substr(yy, 6, 5)=%s\n", substr(yy, 6, 5) ); printf("substr(yy, 9, 5)=%s\n", substr(yy, 9, 5) ); strcpy(tmps, ss); // 注意不要把常數字串傳給 trim, squeeze 等 printf(" String tmps is \"%s\"\n", tmps); /// printf("Test squeeze( tmps )=%s==\n", squeeze(tmps) ); strcpy(tmps, ss); // 重新 copy ss 到 tmps for Test printf("Test sqz22( tmps )=%s==\n", sqz22(tmps) ); strcpy(tmps, ss); // 重新 copy ss 到 tmps printf("Test trimLeft( tmps )=%s==\n", trimLeft(tmps) ); strcpy(tmps, ss); // 重新 copy 到 tmps printf("Test trimRight( tmps )=%s==\n", trimRight(tmps) ); strcpy(tmps, ss); // 重新 copy printf("Test trim( tmps )=%s==去頭尾\n", trim(tmps) ); /// printf("Test sIndex, should be 5 ? == %d\n", sIndex("abcHeHelloHaha", "Hello") ); printf("Test sIndex, should be -1 ? == %d\n", sIndex("abcHeHelloHaha", "ggHello") ); printf("Hit ENTER key..."); getchar( ); return 0; } // main( /******* D:\Test> path C:\Dev-Cpp\bin;%path% D:\Test> gcc strTools.c D:\Test> a.exe gg=abcde1234567 yy=HaHeeABC135 substr(gg, 3, 5)=de123 substr(gg, 9, 5)=567 substr(yy, 2, 3)=Hee substr(yy, 6, 5)=BC135 substr(yy, 9, 5)=35 String tmps is " a b c123 4 5 678 " Test squeeze( tmps )=abc12345678== Test sqz22( tmps )=a b c123 4 5 678== Test trimLeft( tmps )=a b c123 4 5 678 == Test trimRight( tmps )= a b c123 4 5 678== Test trim( tmps )=a b c123 4 5 678==去頭尾 Test sIndex, should be 5 ? == 5 Test sIndex, should be -1 ? == -1 Hit ENTER key... D:\test> ********************************/