字符串操作函数总结

来源:互联网 发布:淘宝时光机 编辑:程序博客网 时间:2024/04/29 14:00
        在这里,首先感谢网络上的朋友们的资料,我把这些基本函数整理出来,和后来的读者们一起分享,有什么不正确的地方,期待您的建议。如果有朋友需要转载这篇blog,请附上我的网址吧,谢谢!

#include <stdio.h>
#include <conio.h>
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>

// 求长度
int strlen(const char *strSrc) {
     int n = 0;
     while (*strSrc++ != '/0')
         n++;
 
     return n;
}

// 复制
char* strcpy(char* strDst, char* strSrc) {
       assert(strDst != NULL && strSrc != NULL);
 
       char *address = strDst;
       while ((*address++ = *strSrc++) != '/0');
 
       return strDst;
}

// 复制
char* strncpy(char* strDst, char* strSrc, size_t num) {
     assert(strDst != NULL && strSrc != NULL && num >= 0);
 
     char *address = strDst;
     while(num--) {
          if ((*address = *strSrc) !='/0')
                strSrc++;
         address++;
     }
 
     return strDst;
}

// 字符串连接
char* strcat(char* strDst, char* strSrc) {
     assert(strDst != NULL && strSrc != NULL);
 
      char *address = strDst;
 
      while (*address)
          address++;
 
      while (*address++ = *strSrc++);
 
     return strDst;
}

// 字符串连接
char* strncat(char* strDst, char* strSrc, size_t num) {
     assert(strDst != NULL && strSrc != NULL);
 
     char *address = strDst;
 
     while (*address)
         address++;
 
     while(num--) {
         if ((*address = *strSrc) !='/0')
            strSrc++;
        address++;

     }
 
     return strDst;
}

// memset函数用来对一段内存空间全部设置为某个字符,常用于内存空间初始化
void *memset(void *pvFrom, int c, size_t n) {
     assert(pvFrom != NULL && n >= 0);
 
     char *address = (char *)pvFrom;
     while(n--) {
         *address++ = (unsigned char)c;
     }
 
     return pvFrom;
}

//源 pvFrom和pvTo所指内存区域不能重叠,函数返回指向pvTo的指针
// memcpy用汇编实现,速度要快很多,可能会产生目标字符串和字符串因为部分重叠导致的不可预知的错误现象
void* memcpy(void *pvTo, const void *pvFrom, size_t num) {
     assert(pvTo != NULL && pvFrom != NULL);
 
     if (num <= 0)
          return pvTo;
 
      char *dst = (char *)pvTo;
      char *src = (char *)pvFrom;
     assert((dst >= (src + num)) && (src >= (dst + num)));
     while (num--) {
         *dst++= *src++;
    }
 
     return pvTo;
}

// pvFrom和pvTo所指内存区域可以重叠,但复制后pvFrom内容会被更改,返回指向pvTo的指针。
void* memmove(void *pvTo, const void *pvFrom, size_t num) {
     assert(pvTo != NULL && pvFrom != NULL);
 
     if (num <= 0)
         return pvTo;
 
     char *dst = (char *)pvTo;
     char *src = (char *)pvFrom;
 
     if (dst <= src || dst >= (src + num)) {       
          while (num--) {
              *dst++= *src++;
          }
     }
    else {      
        dst = dst + num - 1;
        src = src + num - 1;
  
        while (num--) {
           *dst++= *src++;
       }
   }
 
    return pvTo;
}

// 子串
char *strstr(char *strSrc, char *needle) {
    if (strSrc == NULL || needle == NULL)
        return NULL;
 
     char *address = strSrc;   
     if ('/0' == *needle){
           return address;
     }
 
     char *str1, *str2;
     while (*address) {
           str1 = (char*)address;
           str2 = (char*)needle;
  
        while ((*str1 == *str2) && *str1 && *str2){
            str1++;
             str2++;
        }
  
        if ('/0' == *str2){
            return address;
        }   
  
        address++;
    }
 
     return NULL;
}

//  逆序
char *reverse(char *strSrc) {
     if (NULL == strSrc)
            return NULL;
 
     int n = strlen(strSrc);
 
     for (int i = 0, j = n - 1; i < j; i++, j--) {
           strSrc[i] = strSrc[j];
    }
 
     return strSrc;
}

// 字符串比较
int strcmp(char *str1, char *str2) {
     assert(str1 != NULL && str2 != NULL);
 
     while (*str1 == *str2 && *str1 && *str2) {
           str1++;
           str2++;
     }
 
      return *str1 - *str2;
}

// 回文
bool palindrome(char *str) {
    assert(str != NULL);
 
    int n = strlen(str);
 
    for (int i = 0, j = n - 1; i < j; i++, j--) {
         if (str[i] != str[j])
                return false;
    }
 
     return true;
}

// 求子串
void substring(char *strSrc, char *strSub, int pos, int len) {
      if (NULL == strSrc)
         return;
 
     int n = strlen(strSrc);
 
     assert((0 <= pos) && (pos <= n - 1));
     assert((0 <= len) &&  (len <= n - pos));
 
     n = len;
     while (n) {
          *(strSub + len - n) = *(strSrc + pos + len - n);
         n--;
     }
 
    *(strSub + len) = '/0';
}

// 串的模式匹配(简单的模式匹配算法)
int index_BF(char *strSrc, char *strSub, int pos) {
     if (NULL == strSrc || NULL == strSub)
          return -1;
 
     int n = strlen(strSrc);
 
     assert(0 <= pos && pos <= n - 1);
 
     int nSub = strlen(strSub);
     if (n < nSub)
         return -1;
 
     int i = pos;
     int j = 0;
 
     while (i < n && j < nSub) {
           if (strSrc[i] == strSub[j]) {
              ++i;
              ++j;
         }
          else {
             i = i - j + 1;
             j = 0;
         }
     }
 
    if (j >= nSub)
         return i - nSub;
   else
        return -1;
}

// next函数值
void getnext(char *t, int *next) {
     int i = 0, j = -1;
    next[0] = -1;
    int nSub = strlen(t);
    while (i < nSub) {
       if (-1 == j || t[i] == t[j]) {
           ++i;
           ++j;
           next[i] = j;
      }
      else {
          j = next[j];
      }
   }
}

// 串的模式匹配(改进的模式匹配算法)
int index_KMP(char *strSrc, char *strSub, int pos) {
    if (NULL == strSrc || NULL == strSub)
        return -1;
 
     int n = strlen(strSrc);
 
      assert(0 <= pos && pos <= n - 1);
 
      int nSub = strlen(strSub);
 
      if (n < nSub)
          return -1;

 

    // 内存分配完毕后,内存分配机制会在分配的内存空间后部添加四个FD字节
    // 以表示以上为用户的内存区域
     int *next = (int *)malloc((nSub + 1) * sizeof(int));
     if (NULL == next) {
          printf("内存分配失败");
         exit(1);
     }
     getnext(strSub, next);
 
     int i = pos;
     int j = 0;
 
   while (i < n && j < nSub) {
         if (-1 == j || strSrc[i] == strSub[j]) {
             ++i;
             ++j;
        }
        else {
            j = next[j];
        }
    }
 
    for(j = 0; j < nSub; j++)
        printf("next[%d]=%d", j, next[j]);
 
    // 必然导致了free函数内CheckBytes函数检查分配的用户内存空间不正常,导致释放内存失败
    free(next);
 
     if (j >= nSub)
          return i - nSub;
     else
          return -1;
}

// 求子串位置的定位函数
char *replace(char *strSrc, char *strSub, char *strNew) {
      if (NULL == strSrc || NULL == strSub || NULL == strNew)
           return strSrc;
 
      int n1 = strlen(strSrc);
      int n2 = strlen(strSub);
      int n3 = strlen(strNew);
 
      char *pc1, *pc2, *pc3;
       char *result;

       // 申请结果串需要的空间
        int nLen = (n3 > n2) ? (int)((float) n1 / n2 * n3 + 1) : n1; 
        result = (char *)malloc(nLen * sizeof(char));
        memset(result, '/0', nLen);
 
       // 为pc1依次复制结果串的每个字节作准备
       pc1 = result;
      while(*strSrc != '/0') {
               //为检查source与sub是否相等作准备,为pc2,pc3 赋初值
             pc2 = strSrc;
             pc3 = strSub;
            while (*pc2 == *pc3 && *pc3 != '/0' && *pc2 != '/0') {
                 pc2++;
                 pc3++;
            }

           // 如果找到子串,进行以下处理工作
          if('/0' == *pc3) {
             pc3 = strNew;

             // 将替代串追加到结果串
             while(*pc3 != '/0')
                 *pc1++ = *pc3++;
             pc2--;
             strSrc = pc2;
        }
        // 如果没找到子串,下面复制source所指的字节到结果串
         else
             *pc1++ = *strSrc;

          // 将source向后移一个字符
          strSrc++;
     }

 

     *pc1 = NULL;

     return result;
}

原创粉丝点击