字符串反转系列问题

发现不论是在面试还是在平时的学习中,会碰到很多字符串反转相关的问题。之前自己也写过这方面的程序,今天突然发现自己之前的程序有一个致命的BUG,所以决定把字符串反转这一系列的问题总结下,也把自己之前程序的BUG总结下。

 

首先是我之前写的程序,同时这也是处理第一类的字符串反转问题,也就是输入This is a string.,输出为.gnirts a si sihT:

#include <stdio.h>
#include <string.h>

/*我之前的这个代码,有一个很致命的BUG,在字符串长度为奇数的时候运行时正确的
 *但是在字符串长度为偶数的时候运行却是错误的,
 *比如“ab”,str的地址为0x89,ptr的地址为0x8A,当str++,ptr--执行以后
 *str和ptr都是不会相等的,也就是不会结束while循环!!!直到碰巧两者相等
 *循环结束,但此时程序已经得不到原先想要的结果了!!!
 */

void RevStr(char *str)
{
    int len;
    char *ptr;

    len = strlen(str);
    ptr = str + len - 1;

    while(str != ptr)
    {
        char ch;
        ch = *str;
        *str = *ptr;
        *ptr = ch;
        str++;
        ptr--;
    }
}

int main()
{
    char str[] = "This is a string.";
    RevStr(str);
    printf("%s/n",str);
    return 0;
}

 

在论坛发帖求教后,发现了上述问题,然后改进后的代码如下:

 

#include <stdio.h>
#include <string.h>


void RevStr(char *str)
{
    int len;
    char *ptr;

    len = strlen(str);
    ptr = str + len - 1;

    while(str != ptr)
    {
        char ch;
        ch = *str;
        *str = *ptr;
        *ptr = ch;
        str++;
        //ptr自减前,在这里加一个判断,如果相等则结束循环
        //否则ptr就减一
        if(str == ptr)
            break;
        else
            ptr--;

    }
}

int main()
{
    char str[] = "This is a string";
    RevStr(str);
    printf("%s/n",str);
    return 0;
}

 

字符串反转问题的第二类问题是,对于This is a string,最终反转成string a is This。网上对于这个问题,有说用栈来处理。我在看到这个要求,想到上面做的反转问题,觉得可以这样来做:首先,将整个字符串都反转,得到gnirts a si sihT,然后在对每个单词进行反转得到最终的结果,string a is This。

源代码如下:

#include <stdio.h>

int Ustrlen(const char *strSource)
{
     // 声明变量
     int iLength(0);
     // 遍历字符串,查找字符'/0'
     while(*strSource++ != '/0')
     {
         ++iLength;
     }
     // 返回字符串的长度
     return iLength;
}
/************************************************************************/
// 函数名称: _ReversalChar
// 输入参数: strSouce,待反转字符串;iStart,旋转字符串开始位置;iEnd,旋转字符串结束位置
// 输出参数: char*,反转后字符串的指针;
// 描    述: 反转iStart到字符串iEnd之间的字符串
/************************************************************************/
char* _ReversalChar(char *strSouce,int iStart,int iEnd)
{
     // 反转字符串
     for(;iEnd > iStart; ++iStart,--iEnd)
     {
         char ch;
         ch = strSouce[iStart];
         strSouce[iStart] = strSouce[iEnd];
         strSouce[iEnd] = ch;
     }
     // 返回字符串指针
     return strSouce;
}
 
/************************************************************************/
// 函数名称: ReversalChar
// 输入参数: strSource,待反转字符串
// 输出参数: char*,反转字符串后的指针
// 描    述: 按单词反转字符串
/************************************************************************/
char * ReversalChar(char *strSouce)
{
     // 获取字符串的长度
     int iLength = Ustrlen(strSouce);
 
     // 反转整个字符串
     _ReversalChar(strSouce,0,iLength-1);
 
     // 声明变量(单词的开始以及结束默认从0开始)
     int iStart(0),iEnd(0);
 
     // 查找单词
     // 像上面讨论的查找单词的情况,我们只需要修改这部分,就可以实现对不
     // 同格式类型单词进行处理,为了更好的通用性,其实最好把查找单词这部分
     // 作为单独一个函数,或者一个类来处理
     for(int i = 0; i <= iLength; ++i)
     {
         // 查找空格分割符号
         //if语句里面第二个判断是用于最后一个单词,不加这个判断最后一个单词反转不了,因为
         //最后一个单词后面没有空格的,所以只能靠结束符'/0'来判断到达字符串尾,再对其反转
         if(strSouce[i] == ' ' || strSouce[i]  == '/0')
         {
              // 找到一个单词
              iEnd = i-1;
              // 对于只有一个字符的单词比如说(I)没有必要反转
              if(iStart < iEnd)
              {
                   // 反转单词
                   _ReversalChar(strSouce,iStart,iEnd);
              }
              // 记录下一个单词的开始位置
              iStart = i+1;
         }
         // 特殊处理几种常见标点符号
         else if(strSouce[i] == '!' || strSouce[i] == ',' || strSouce[i] == '.')
         {
              iStart = i+1;
         }
     }
     // 返回反转后的字符串
     return strSouce;
}

int main()
{
    char *ptr;
    char str[] = "This is a string.";

    ptr = ReversalChar(str);
    printf("%s/n",ptr);

    return 0;
}

你可能感兴趣的:(面试,String)