C语言字符串反转函数

http://www.cnblogs.com/pianoid/archive/2011/10/30/string_reverse_in_c_language.html

找工作前写了篇blog说要做些常见的笔试面试题,像单链表反转啊字符串反转啊之类的题目,但是只写了一篇单链表反转就没再继续写下去,因为觉得实在没什么好写的,不过都是一些简单的指针操作罢了,但是还是有很多新手问这个问题,而且我在腾讯二面的时候也被要求实现这个函数,那我也写一篇blog介绍一下字符串反转吧。

  C语言中所谓的字符串不过是字符数组,后跟一个0x00字符标识结尾,所以反转起来很容易,只要一个循环依次将第一个字符和最后一个字符交换,第二个字符和倒数第二个字符交换……如果最中间有两个字符(即需要反转的字符串长度为偶数),那就交换,如果最中间有一个字符(即需要反转的字符串长度为奇数),那就不需要碰它。还有就是最后一个用来标识字符串结尾的0x00字符不用动它。

  这道题目通常是考察三个方面,一是对指针和字符串的理解,二是是否进行合法性检查,例如输入参数为空指针时是否进行检查,三是返回值是否是恰当,即使你通过参数返回了反转后的字符串指针,也建议在返回值里再返回一下,就像strcpy函数实现的那样。其实还有第四点往往是大家都忽略了的,那就是Unicode问题,如果传入的字符串指针指向的是Unicode字符串,那么反转的时候就不能一个字符一个字符的处理了,不过似乎大多数面试官都没对这一点有过要求,如果你在笔试或面试中遇到这个问题,我建议你想监考或面试官询问一下是否需要考虑Unicode。我面试的时候因为被面试官弄的很紧张,也忘记了这点,写完后检查代码准备交过去时才想起来,索性就当不知道这回事……呵呵。

  有了上面这几点,我们就可以很容易地用C语言写出这个函数了。

复制代码
char *revstr(char *str, size_t len)
{

    char    *start = str;
    char    *end = str + len - 1;
    char    ch;

    if (str != NULL)
    {
        while (start < end)
        {
            ch = *start;
            *start++ = *end;
            *end-- = ch;
        }
    }
    return str;
}
复制代码

  代码很简单,就不多介绍了,只是为什么我给这个函数叫revstr而不是strrev呢?我开始时也是给它叫strrev,只是链接时却出错了,这时我才发现VS2005的C++编译器已经在string.h中中提供了一个strrev函数(这看起来并不是C标准库函数,我不知道还有哪些编译器提供了这个函数),如果你安装了crt代码包的话可以找到这个函数的实现。我们来看一下它是如何实现的吧。

复制代码
char * __cdecl _strrev (
        char * string
        )
{
        char *start = string;
        char *left = string;
        char ch;

        while (*string++)                 /* find end of string */
                ;
        string -= 2;

        while (left < string)
        {
                ch = *left;
                *left++ = *string;
                *string-- = ch;
        }

        return(start);
}
复制代码

  这与我上面给出的函数并没有什么本质的不同,只是只传入了一个参数,并没有传入字符串长度,但是我觉得还是传入这个长度比较好,因为有可能我们并不想反转整个字符串,如果采用我给出的那种实现,一个长度为10的字符串,我们只想反转前7个字符也是可以的。还有就是微软给出的这个实现并没有判断是否传入空指针,不过我觉得这并不是个大问题,这要取决于你的具体期望,就像我在启明星辰的笔试中遇到了一道题目,要求我实现一个函数将传入的字符串中的小写字母转换成大写字母,那么如果传入的字符串是小写字母和数字混合的呢?函数应该出错还是应该跳过数字继续处理?两种方式都没错,怎么选择要取决于你或者阅卷人对这个函数的期望,在笔试或面试中你可以询问监考活面试官,如果没有得到准确的描述,你怎么实现都是正确的。


一、字符串中没有中文时。

char *consver(char *str)   
{   

        if(*str!=‘\0’)

        {
                char temp;   
                char *s1 = str;   
                char *s2 = str+strlen(str)-1;   
  
                for(;s1 < s2;s1++,s2--)   
               {   
                       temp = *s1;   
                       *s1 = *s2;   
                       *s2 = temp;   
               }   

       }
       return str;   
}  

 

测试上面的程序:

int main(int argc,char *argv[])   
{   
    char *str = "abcdefg";                                 //这里有问题哈,应该改为  char str[ ] ="abcdefg";

    char *sdest;  
    sdest = reconsver(str);   
    printf("sdest is [%s]\n",sdest);   
    getch();   
    return 0;   

原因就在于 char *str = "abcdefg";这样定义的话,会使得str默认转换为const型,即不允许被修改,故而有错!

改成,char str[] = "abcdefg";就OK了!

 

方法一样的

char * __cdecl _strrev ( char * string )  
{  
        char *start = string;  
        char *left = string;  
        char ch;  
 
        while (*string++)                 /* find end of string */ 
                ;  
        string -= 2;  
 
        while (left < string)  
        {  
                ch = *left;  
                *left++ = *string;  
                *string-- = ch;  
        }  
 
        return(start);  
}

 

二、全是中文字符串时

 

本文

#include<iostream>
using namespace std;
int main()
{
  char s[20]="游戏开发";
  int i=0,j=strlen(s)-1;
  while(i<j)
  {
    swap(s[i],s[j-1]);
    swap(s[i+1],s[j]);
    i+=2;
    j-=2;
  }
  cout<<s;
  return 0;
}

 

三、有中文又有英文的字符串

#include   <iostream.h>  
   
   
  /*     逆序输出字符串(带中文),递归方式   */  
  void   reverse(char   *str)  
  {  
            if   (   *str   ==   '\0'   )   return;  
            if   (   *str   <   0   )     
            {  
                  reverse(   str   +   2   );   
                  cout<<*str<<(*(str+1));   
            }  
            else  
           {  
                  reverse(   str   +   1   );  
                  cout   <<   *str;   
            }  
  }  
   
  void   main()  
  {   
             char   str[]   =   "AZaz冬天";   
            reverse(str);  
  }   

来自CSDN博客,转载请标明出处:http://blog.csdn.net/NowDoIT/archive/2011/01/11/6128524.aspx


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值