從字符串中提取數字串並排序(C語言實現)


#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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM