常考字符串处理函数一网打尽

简介: 本文涉及的函数的写法不敢说最优,但是是作者参考了诸多文献和深入分析下总结的,并全部通过VC6.0调试通过,希望对大家有帮助。

题记

近期笔试、面试中多次出现字符串处理函数的写法。包括最经典的:strcpy、strcat、strcmp、atoi、itoa,内存拷贝函数memcpy等。

Baidu、google一下会有很多版本,良莠不齐,给大家阅读和辨识形成了负担,本就紧张的笔试、面试备战在选择中浪费了不少时间。

本文涉及的函数的写法不敢说最优,但是是作者参考了诸多文献和深入分析下总结的,并全部通过VC6.0调试通过,希望对大家有帮助。

 

这里涉及一点,面试的时候,面试官可能就一张白纸,不提供函数原型的情况下让你实现库函数。这里就需要大家对Msdn里提供的库函数有所深入,参数个数、参数类型、返回值类型、函数实现的功能。

一、函数原型

以下函数原型摘自MSDN2001,VS2008、VS2010会有新的扩展比如:strcpy_s——

函数原型 函数功能
char strcpy( char strDestination,const char *strSource); 字符串拷贝(拷贝一个字符串到另一个字符串)
int strcmp( const char string1, const char string2 ); 比较两字符串,string1>string 返回值>0;string1
char strcat( char strDestination, const char *strSource ); 字符串拼接函数
int atoi( const char *string ); 字符串转化为整形数
char _itoa( int value, char string, intradix ); 整形转化为字符串[注意]:radix取值范围是[2,36].string长度最长33个字节.10进制的数考虑负数的处理,其他进制不必考虑。
void memcpy( void dest, const void *src, size_tcount ); 内存拷贝函数,【注意】:本身并没涉及地址覆盖,但一般面试的时候需要考虑。

二、自写函数实现

1. strcpy的实现

char* strcpy_t(char* strDst, const char* strSrc)
{
assert(strDst !=NULL && strSrc != NULL);
 
char* strRst =strDst;
while( (*strDst++= *strSrc++)!='\0');
return strRst;
}

 

2. strcmp的实现[扩展:<0 返回-1; >0 返回1; 等于0 返回0]

int strCmp_t(const char* strSrcL, const char* strSrcR)
{
         assert(strSrcL!= NULL || strSrcR != NULL);
        
         int ret = 0;
         constchar* p1 = strSrcL;
         constchar* p2 = strSrcR;
        
         while(!(ret = (*p1 - *p2)) && *p2 != '\0') //注意循环终止条件
         {
              ++p1;
              ++p2;
         }
         if(ret< 0)
         {
              ret= -1;
         }
         else if(ret > 0)
         {
              ret= 1;
         }
         return ret;
}

3. strcat的实现

char* strCat_t(char* strDst, const char* strSrc)
{
         char* cp = strDst;
        
         while(*cp != '\0')
         {
                   cp++;//跳至 strDst的末尾.
         }
        
         while((*cp++= *strSrc++)!='\0');
         return strDst;
}

4.atoi的实现【扩展:考虑了正负号的处理、大、小边界数的处理、非字符的处理、status决定了是什么状态导致的返回0】

//atoi_t


enum status{kValid = 0, kInvalid};
int g_Status =kInvalid;
 
int main()
{
            int stringToInt(const char* str);
            int stringToIntCore(const char* str,bool bMinus);
           
            char* str1 = "-12345";
            cout << stringToInt(str1)<< endl;
            cout <<stringToInt("+") << endl;
           
            return 0;
}
 
//stringToIntCore核心处理函数.
intstringToIntCore(const char* str, bool bMinus)
{
         int num = 0;
        
         while(*str!= '\0')
         {
                   if(*str>= '0' && *str <='9')
                   {
                     num= num*10 + (*str -'0');
                     if((!bMinus && num >0x7FFFFFFF) || (bMinus && num < (signedint)0x80000000))
                     {
                        num= 0;  //
                        break;
                     }
                   }
                   else
                   {
                       num= 0;
                       break;
                   }
                   str++;
         }//endwhile
        
         if(bMinus)
         {
                   num= -num;
         }
        
         if(*str== '\0')
         {
                   g_Status= kValid;
         }
        
         returnnum;
}
intstringToInt(const char* str)
{
         boolbMinus = false;
         intnum = 0;
        
         if(str== NULL)
         {
               return0;
         }
         if(str!= NULL && *str != '\0')
         {
                   if(*str== '+')
                   {
                            str++;
                   }
                   else if(*str == '-')
                   {
                            bMinus= true;
                            str++;
                   }
                  
                   if(*str!= '\0')
                   {
                       num = stringToIntCore(str,bMinus);
                   }
                  
         }//endif
        
         return num;
}

5.itoa的实现[考虑,进制转换,字符串翻转]

//itoa


char* itoa_t(intvalue, char* strSrc, int radix)
{
                char strTmp[33];    //1.最大存储33个字节
                int quotient = 0;   //商数
                int residue = 0;    //余数
                int isNegative = 0;  //负数标识,1代表负数,0代表正数
                int nCnt = 0;       //统计字符个数
                char* strQ = strTmp;    //暂存strTmp.
               
                if(radix < 2 || radix >36)
                {
                   return NULL;             //2.radix[2,36]基数的大小范围
                }
               
                isNegative = (value < 0&& radix == 10); //3.对于10进制的数,考虑负数的处理.
                if(isNegative != 0)
                {
                   value = -value;
                }
                else
                {
                   value =(unsigned)value;
                }
               
                while(value != 0)
                {
                   quotient = value/radix; //商
                   residue = value%radix; //余数
                   ++nCnt;
                  
                   if(residue <10)
                   {
                       *strQ++ =(residue+'0');
                   }
                   else
                   {
                       *strQ++ =(residue+'a'-10); //>=10 的特殊处理a-->f
                   }
                   value = quotient;
                }
               
                if(strSrc == NULL)
                {
                   strSrc =(char*)malloc(nCnt+isNegative+1);
                }
               
                char* strP = strSrc;  //strP暂存strSrc变化
                if(isNegative != 0)
                {
                   *strP++ = '-';
                }
                while(nCnt >= 0)
                {
                   *strP++ = *--strQ;
                   --nCnt;
                }
                *strP = '\0';
               
                return strSrc;
}

6. memcpy的实现——见另一篇博文

http://blog.csdn.net/wojiushiwo987/article/details/8020409

7. 字符串翻转.

char* strRvs(const char* strSrc)
{
         intnLen = strlen(strSrc);
         char*strRst = new char[nLen+1];  //另外开辟空间.
         char*pRst = strRst;
         const char* pLast = strSrc + nLen-1;
 
         while(nLen>= 0)
         {
                   *pRst++= *(pLast--);
                   nLen--;
         }
 
         return strRst;
}

8.strncat写法

char *strncat_t (char * front,const char * back,size_t count)    
{    
   char *start = front;    
       
    while (*front++)    
            ;    
    front--;    
    
    while (count--) 
    {
       if (!(*front++ = *back++))
       {
           return(start); //拷贝至结尾需要返回!
       }
    }
        
    *front = '\0';    
    return(start);    
}    

9.memset写法

//memset():把指定内存区域的前count个字节设置成字符c  
void * memset_t(void* buffer, int c, size_t count)  
{  
   assert(buffer != NULL);  
   char *p = (char *)buffer;  
   cout << p << endl;
 
 
    while(count--) 
    {
        *p++ = 'c';
        cout << *p << endl;
    }
    return buffer;  
}  

10.strstr写法

/子串判定!
char *strstr_t(const char *strSrc, const char *str)     
{     
   assert(strSrc != NULL && str != NULL);     
   const char *s = strSrc;     
   const char *t = str;     
   for (; *strSrc != '\0'; ++ strSrc)     
   {     
        for (s = strSrc, t = str; *t != '\0' && *s == *t; ++s, ++t)           
        {
              NULL;  
        }
        if (*t == '\0')     
        {
             return (char *) strSrc;  //存在子串
        }
   }     
   return NULL;     
}   

【总结】:字符串处理为什么常考的原因,主要它牵涉到指针处理、分支情况的处理,考量大家的思考能力、逻辑问题分析能力、变通能力等。

肯定还有这种常考的函数,希望与大家探讨!

相关文章
|
1月前
|
算法 Java C语言
【c语言基础题】— —第一版,可当作日常练习和期末复习,有奇效哟!
【c语言基础题】— —第一版,可当作日常练习和期末复习,有奇效哟!
77 0
|
1月前
|
机器学习/深度学习 人工智能 C语言
【c语言基础题】— —第五版,可当作日常练习和期末复习,有奇效哟!
【c语言基础题】— —第五版,可当作日常练习和期末复习,有奇效哟!
42 1
|
4月前
|
存储 安全 Java
初学者对C语言的爱恨情仇之神秘的字符串
初学者对C语言的爱恨情仇之神秘的字符串
34 0
|
1月前
|
程序员 C语言 CDN
【c语言基础题】— —第三版,可当作日常练习和期末复习,有奇效哟!
【c语言基础题】— —第三版,可当作日常练习和期末复习,有奇效哟!
77 0
|
1月前
|
C语言 wax
【c语言基础题】— —第四版,可当作日常练习和期末复习,有奇效哟!
【c语言基础题】— —第四版,可当作日常练习和期末复习,有奇效哟!
90 0
|
1月前
|
机器学习/深度学习 C语言
【c语言基础题】— —第二版,可当作日常练习和期末复习,有奇效哟!
【c语言基础题】— —第二版,可当作日常练习和期末复习,有奇效哟!
79 0
|
1月前
|
人工智能 网络协议 BI
【c语言基础题】— —第七版,可当作日常练习和期末复习,有奇效哟!
【c语言基础题】— —第七版,可当作日常练习和期末复习,有奇效哟!
19 0
|
1月前
|
人工智能 网络协议 BI
【c语言基础题】— —第六版,可当作日常练习和期末复习,有奇效哟!
【c语言基础题】— —第六版,可当作日常练习和期末复习,有奇效哟!
24 0
|
9月前
|
存储
用处巨广的操作符,快来学学叭(C语言版)
用处巨广的操作符,快来学学叭(C语言版)
41 1
|
5月前
|
存储 编译器 程序员
c语言(从入门到放弃?NONONO,LET我们一步一步刨析,会发现其中蕴含的乐趣)
c语言(从入门到放弃?NONONO,LET我们一步一步刨析,会发现其中蕴含的乐趣)
45 0