#include "stdio.h" #include "stdlib.h" #include "string.h" typedef int BOOL; #define TRUE 1; #define FALSE 0; static void SplitBySeparator( char **arr, char *str, int size, char sep); void SortNums ( char* str, int size, int cnt); int CompareDigStr ( char* digStr1, char* digStr2); /* 從字符串中提取數字串並排序, 其中: 參數: str 字符串 length 字符串長度, 若 < 0 則為 str 以 '\0' 結尾 dest 存放數字串的緩沖區 size 傳入 dest 緩沖區的尺寸, 並返回數字串的長度 返回值: -2 提取失敗, 存放數字串的緩沖區尺寸太小 -1 提取失敗, 參數不合法 0 提取失敗, 無數字串 >0 提取成功, 返回數字串的項數 */ int ExtractNums(const char* str, int length, char* dest, int* size) { int result = -1; int sizeDest = 0; // 數字串長度 int cntDest = 0; // 數字串的項數(cntDest+1) BOOL isNeedSep = FALSE; // 是否需要分隔符 char ch; if (str != NULL && dest != NULL && size != NULL && *size > 0) { if (length < 0) // str 以 '\0' 結尾 { while(*str != '\0') { ch = *str; if (ch >= '0' && ch <= '9') { // 分隔符 if (isNeedSep) { if (sizeDest >= *size) { result = -2; // 提取失敗, 存放數字串的緩沖區尺寸太小 break; } dest[sizeDest++] = ' '; // 分隔符 cntDest ++; isNeedSep = FALSE; } // 數字項 if (sizeDest >= *size) { result = -2; // 提取失敗, 存放數字串的緩沖區尺寸太小 break; } dest[sizeDest++] = ch; } else if (!isNeedSep && sizeDest > 0) { isNeedSep = TRUE; // 下一數字項前需要加分隔符 } str ++; } } else { for (int i=0; i<length; i++) { ch = str[i]; if (ch >= '0' && ch <= '9') { // 分隔符 if (isNeedSep) { if (sizeDest >= *size) { result = -2; // 提取失敗, 存放數字串的緩沖區尺寸太小 break; } dest[sizeDest++] = ' '; // 分隔符 cntDest ++; isNeedSep = FALSE; } // 數字項 if (sizeDest >= *size) { result = -2; // 提取失敗, 存放數字串的緩沖區尺寸太小 break; } dest[sizeDest++] = ch; } else if (!isNeedSep && sizeDest > 0) { isNeedSep = TRUE; // 下一數字項前需要加分隔符 } } } // 輸出緩沖區太小則不進行排序 if (result != -2) { *size = sizeDest; // 數字串的長度 // 數字項大於1才進行排序 if (++cntDest > 1) { SortNums(dest, sizeDest, cntDest); result = cntDest; // 返回數字串的項數 } else if (sizeDest != 0) // 只有一個數字項 { result = cntDest; } else result = 0; // 無數字串 } } return result; } /* 數字字符串串排序(從小到大), 其中: 參數: str 數字字符串 size 數字字符串長度 cnt 數字串項數 返回值: 無 */ void SortNums(char* str, int size, int cnt) { char** arrStr = NULL; // 二級指針,用於存放分割提取好的數字項 char* strDest = NULL; // 待分隔數字串 char* arrTmp = NULL; int nLen = 0; // 數字項長度 BOOL isSorted = FALSE; if (str != NULL && size > 0) { strDest = (char*)malloc(size+1); if (strDest != NULL) { arrStr = (char**)malloc(cnt*sizeof(char *)); // 申請cnt個指針保存數字項地址 if (arrStr != NULL) { memcpy(strDest, str, size); *(strDest+size) = '\0'; // 提取數字項 SplitBySeparator(arrStr, strDest, size, ' '); // 冒泡排序 for(int i=0; i<cnt-1; i++) { isSorted = TRUE; //每一輪比較前cnt-1-i個,即已排序好的最后i個不用比較 for(int j=0; j<cnt-1-i; j++) { if(CompareDigStr(arrStr[j], arrStr[j+1]) == 1) { isSorted = FALSE; arrTmp = arrStr[j]; arrStr[j] = arrStr[j+1]; arrStr[j+1] = arrTmp; } } if(isSorted) break; // 沒有發生交換,排序已完成 } // str返回排序結果 nLen = strlen(arrStr[0]); memcpy(str, arrStr[0], nLen); str += nLen; for(int i=1; i<cnt; i++) { *str = ' '; str ++; nLen = strlen(arrStr[i]); memcpy(str, arrStr[i], nLen); str += nLen; } free(arrStr); } free(strDest); } } } /* 提取數字項(static靜態函數), 其中: 參數: arr 返回提取好的數字項 str 數字串 size 數字串長度 sep 分隔符 返回值: 無 */ void SplitBySeparator( char **arr, char *str, int size, char sep) { char* pEnd = str + size; for (*arr = str; str < pEnd; str++) if (*str == sep) { *str = '\0'; *(++arr) = str + 1; } } /* 比較數字串大小, 其中: 參數: digStr1 數字串1 digStr2 數字串2 返回值: <0 digStr1小於digStr2 0 digStr1等於digStr2 >0 digStr1大於digStr2 */ int CompareDigStr(char* digStr1, char* digStr2) { int result = -1; int dig1Len = 0; int dig2Len = 0; if (digStr1 != NULL && digStr2 != NULL) { // 除數字串頭‘0’ while(*digStr1 == '0') { digStr1 ++; } while(*digStr2 == '0') { digStr2 ++; } dig1Len = strlen(digStr1); dig2Len = strlen(digStr2); if (dig1Len > dig2Len) { result = 1; } else if (dig1Len == dig2Len) { result = strncmp(digStr1, digStr2, dig1Len); } } return result; }
