[C/C++] String Reverse 字符串 反转

#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>

inline void STL_Reverse(std::string& str) // 反转string字符串 包装STL的reverse()  可以inline
{
    reverse(str.begin(), str.end());
    // STL 反转函数 reverse() 的实现
    /*     template <class BidirectionalIterator>
     *     void reverse(BidirectionalIterator first, BidirectionalIterator last)
     *     {
     *         while ((first != last) && (first != --last))
     *             swap(*first++, *last);
     *     }
     */
}

void bad_Reverse(std::string& str) // 效率低的反转字符串函数
{
    std::string tmp(str);
    std::string::size_type ix = str.length() - 1;
    for (std::string::size_type i = 0; i < str.length(); i++) {
        str[i] = tmp[ix];
        ix--;
    }
}

void good_Reverse(std::string &word)   // 仿制STL的算法的,适合string字符串反转函数
{                                      // 效率比 C++ Primer Plus 的高一点
    size_t first, last;
    first = 0;
    last = word.size();
    while ((first != last) && (first != --last))
        std::swap(word[first++], word[last]);
}

void Reverse(std::string &word)   // 适合string字符串反转函数
{                                 // 来源 C++ Primer Plus 第五章 forstr2.cpp -- reversing an array
    char temp;
    size_t i, j;
    for (j = 0, i = word.size() - 1; j < i; --i, ++j) {
        temp = word[i];
        word[i] = word[j];
        word[j] = temp;
    }
}

void bad_Reverse(char *str)  // 效率低的反转字符串函数 适合C风格字符串
{
    char * tmp = new char[strlen(str)];
    strcpy(tmp, str);
    size_t ix = strlen(str) - 1;
    for (size_t i = 0; i < strlen(str); i++) {
        str[i] = tmp[ix];
        ix--;
    }
    delete[] tmp;
}

void good_Reverse(char *word)   // 仿制STL的算法的,适合C风格字符串反转函数
{                               // 效率没有 C++ Primer Plus 的高
    size_t first, last;
    first = 0;
    last = strlen(word);
    while ((first != last) && (first != --last))
        std::swap(word[first++], word[last]);
}

void Reverse(char *word)   // 适合C风格字符串反转函数
{                          // 来源 C++ Primer Plus 第五章 forstr2.cpp -- reversing an array
    char temp;
    size_t i, j;
    for (j = 0, i = strlen(word) - 1; j < i; --i, ++j) {
        temp = word[i];
        word[i] = word[j];
        word[j] = temp;
    }
}

int main()
{
    using namespace std;
    // 1KW 字符串反序函数测试,分别测试同样算法,string 和 C风格字符串的区别

    string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (int i = 0 ; i != 10000001 ; i++)
        //  STL_Reverse(str);   //0.313秒
        //  good_Reverse(str);  //0.875秒
        //  Reverse(str);       //1.063秒
        bad_Reverse(str);       //7.016秒
    cout << str << endl;

    char cs[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    for (int i = 0 ; i != 10000001 ; i++)
        // Reverse(cs);        //0.578秒
        // good_Reverse(cs);   //0.859秒
        bad_Reverse(cs);       //13.766秒
    cout << cs << endl;

    return 0;
}

#define WIN32  // 如果VC编译器定义WIN32 使用gettimeofday()

#include <time.h>
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#ifdef WIN32
int gettimeofday(struct timeval *tp, void *tzp)
{
    time_t clock;
    struct tm tm;
    SYSTEMTIME wtm;
    GetLocalTime(&wtm);
    tm.tm_year     = wtm.wYear - 1900;
    tm.tm_mon     = wtm.wMonth - 1;
    tm.tm_mday     = wtm.wDay;
    tm.tm_hour     = wtm.wHour;
    tm.tm_min     = wtm.wMinute;
    tm.tm_sec     = wtm.wSecond;
    tm. tm_isdst    = -1;
    clock = mktime(&tm);
    tp->tv_sec = clock;
    tp->tv_usec = wtm.wMilliseconds * 1000;
    return (0);
}
#endif /* WIN32 */



// 测试执行时间代码
    timeval tv;
    gettimeofday(&tv, NULL);
    double cl = tv.tv_sec + (double)tv.tv_usec / 1000000;

// 添加测试代码

    gettimeofday(&tv, NULL);
    cl = (tv.tv_sec + (double)tv.tv_usec / 1000000) - cl;
    printf("\n执行时间 : %0.3f 秒", cl);

_strrev, _wcsrev, _mbsrev
Reverse characters of a string.

char *_strrev( char *string );

wchar_t *_wcsrev( wchar_t *string );

unsigned char *_mbsrev( unsigned char *string );

Routine Required Header Compatibility 
_strrev <string.h> Win 95, Win NT 
_wcsrev <string.h> or <wchar.h> Win 95, Win NT 
_mbsrev <mbstring.h> Win 95, Win NT 


For additional compatibility information, see Compatibility in the Introduction.

Libraries

LIBC.LIB Single thread static library, retail version 
LIBCMT.LIB Multithread static library, retail version 
MSVCRT.LIB Import library for MSVCRT.DLL, retail version 


Return Value

Each of these functions returns a pointer to the altered string. No return value is reserved to indicate an error.

Parameter

string

Null-terminated string to reverse

Remarks

The _strrev function reverses the order of the characters in string. The terminating null character remains in place. _wcsrev and _mbsrev are wide-character and multibyte-character versions of _strrev. The arguments and return value of _wcsrev are wide-character strings; those of _mbsrev are multibyte-character strings. For _mbsrev, the order of bytes in each multibyte character in string is not changed. These three functions behave identically otherwise. 

Generic-Text Routine Mappings

TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined 
_tcsrev _strrev  _mbsrev  _wcsrev  


Example

/* STRREV.C: This program checks an input string to
 * see whether it is a palindrome: that is, whether
 * it reads the same forward and backward.
 */

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

void main( void )
{
   char string[100];
   int result;

   printf( "Input a string and I will tell you if it is a palindrome:\n" );
   gets( string );

   /* Reverse string and compare (ignore case): */
   result = _stricmp( string, _strrev( _strdup( string ) ) );
   if( result == 0 )
      printf( "The string \"%s\" is a palindrome\n\n", string );
   else
      printf( "The string \"%s\" is not a palindrome\n\n", string );
}


Output

Input a string and I will tell you if it is a palindrome:
Able was I ere I saw Elba
The string "Able was I ere I saw Elba" is a palindrome


String Manipulation Routines

See Also   strcpy, _strset

#include <iostream>    // 数据流输入/输出
char * my_strrev (char * string )
{
    char *start = string;
    char *left = string;
    char ch;

    while (*string++) // 找到string 末位的'\0',
        ;             // 因为上面 string++,实际指针在 '\0'的后一个
    string -= 2;      // 所以退2格,回到字符串最后一个字母
    while (left < string) {
        ch = *left;    // 通过临时变量 ch 进行交换
        *left++ = *string;
        *string-- = ch;
    }
    return(start);
}
using namespace std;

int main()
{
    char h[] = "Hello world!";
    cout << my_strrev (h) << endl;
    return 0;
}

//通过不同的方法,实现对所输入字符串的反转,可以很好地复习巩固 C++ 基础知识
/*分析过程:
  假设要使传递的字符串为常量const字符串,这样操作更加灵活,可直接传递字符串字面值进行反转,常见的解决方法就是,定义一个新的与传递过来字符串长度
  相等的字符数组,然后进行字符串拷贝,把str字符按从左到右放置到字符数组中,然后采用循环来对字符数组中字符反转
*/
/*第一种,采用以上思路解法,传递为const类型C风格字符指针,返回为char*类型*/
//直接使用字符数组赋值
char* strrev1(const char* str)
{
   const size_t length = strlen(str);//求字符长度
   char *temp = new char[length];//新建一个等长度的字符数组
   strcpy(temp,str);//字符串拷贝
   for (size_t i = 0; i <= length/2; ++i)//对字符数组中的字符反转,循环执行条件为标识小于或等于字符长度一半
   {
      char c = temp[i];
      temp[i] = temp[length - i -1];
      temp[length - i -1] = c;
   }
   return temp;//返回反转后的字符
}
//采用指针操作方式
char* strrev2(const char* str)
{
   char* tmp = new char[strlen(str)];
   strcpy(tmp,str);
   char* ret = tmp;//用来最后返回数组指针
   char* p = tmp + strlen(str) - 1;
   while (p > tmp) 
   { 
      char t = *tmp; 
      *tmp++ = *p; 
      *p-- = t;
   }
   return ret;
}
//与上一函数基本相似,只不过本函数使用是移位操作改变字符指针指向
char* strrev3(const char* str)
{
   char* tmp = new char[strlen(str) + 1];
   strcpy(tmp,str);
   char* ret = tmp;
   char* p = tmp + strlen(str) - 1;
   while (p > tmp) 
   { 
      *p ^= *tmp;
      *tmp++ ^= *p;          
      *p-- ^= *tmp;
   }
   return ret;
}
//节省几步,直接给新建的字符数组赋反转的值,呵呵,简单明了,只不过循环多执行几次
char* strrev4(const char* str)
{
   char * temp = new char[strlen(str)];
   for(int i = 0; i <= strlen(str); i++)
   {
      temp[i] = str[strlen(str) - i -1];
   }
   return temp;
}
//使用递归进行字符反转,网上看的,不过感觉不好,限制太多
//(不能直接反转常量字符串,因为没有定义新的字符数组,而是在原数组上直接进行字符反转,节省空间,提高效率,还要传递字符长度,增加限制,但总归是个思路)
char* strrev5 (char* str,int len)
{
   if (len <= 1)
      return str;
   char t = *str;
   *str = *(str + len -1);
   *(str + len -1) = t;
   return (strrev5(str + 1,len - 2) - 1);
}
/*如果传递是std::string类型字符串且是const的!!
  返回类型为std::string
*/
std::string strrev6(const std::string str)
{
  string r ;//定义一个新的字符串变量,用来接收
  string r;
   for(int i = 0; i < str.length(); ++i)
   {
      r = str[i] + r;//注意顺序
   }
  return r;
}
/*如果传递是std::string类型字符串,但不是const的!!
  返回类型为std::string,那你将不必再定义一个新的字符串变量
  节省空间,注意:string类型可以直接接受字符串字面值就是啦..
*/
std::string strrev6(std::string str)
{
  for(int i = 0; i <= str.length()/2; ++i)
   {
      char c = str[i];
      str[i] = str[str.length() - i -1];
      str[str.length() - i - 1] = c;
     }
   return str;
}

原文链接: https://www.cnblogs.com/Areas/p/5613019.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/235707

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 下午4:45
下一篇 2023年2月13日 下午4:45

相关推荐