alg : 字符串按照字符进行循环移位(左旋转 or 右旋转)

来源:互联网 发布:java内存泄漏解决方法 编辑:程序博客网 时间:2024/05/22 12:29

题目需求:

算法:

/// 字符串循环左移或右移N个字符的算法/// * 将整个串全反转/// * 按照需要移动的字符个数将反转后的串分为2部分/// * 将这2个子字符串分别进行反转////// e.g. 原串: hello world, 要求循环左移3个字符/// * 将整个串反转, dlrow olleh/// * 按照循环的字符数3, 将翻转后的串分为2部分, [dlrow ol][leh]/// * 将这2个子字符串分别进行反转 [lo world][hel]/// 得到字符串按照字符为单位循环移位的结果为 lo worldhel

测试程序效果图:

测试程序算法实现:

// srcStringCirculator.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <windows.h>#include <locale.h>#include <tchar.h>#include "Helper\StringHelper.h"/// 字符串循环左移或右移N个字符的算法/// * 将整个串全反转/// * 按照需要移动的字符个数将反转后的串分为2部分/// * 将这2个子字符串分别进行反转////// e.g. 原串: hello world, 要求循环左移3个字符/// * 将整个串反转, dlrow olleh/// * 按照循环的字符数3, 将翻转后的串分为2部分, [dlrow ol][leh]/// * 将这2个子字符串分别进行反转 [lo world][hel]/// 得到字符串按照字符为单位循环移位的结果为 lo worldhelvoid DoStringCirculatorOnce();      ///< 开始一次字符串字符移位bool IsDoStringCirculatorAgain();   ///< 是否再开始一次新的字符串字符移位int _tmain(int argc, _TCHAR* argv[]){    setlocale(LC_CTYPE, ".936");    //< 控制台为中文输出    do     {        DoStringCirculatorOnce();    } while (IsDoStringCirculatorAgain());    _tprintf(L"\r\nEND, press any key to quit\r\n");    getchar();    /** run results    */return 0;}void DoStringCirculatorOnce(){    wchar_t     szBuf[_MAX_PATH];                                   ///< 用户输入的原始字符串    wchar_t *   pszBuf              =   &szBuf[0];    size_t      nInputBufLenMax     =   SIZEOF_WCHAR_ARRAY(szBuf);    bool        bLoopLeft           =   true;    size_t      nLoopCnt            =   0;    if (!GetUserInputStringCirculatorParam(pszBuf, nInputBufLenMax, bLoopLeft,nLoopCnt))        return;    if (StringCirculator(pszBuf, bLoopLeft,nLoopCnt))        _tprintf(L"\r\n循环字符移位后的串为 : [%s]\n", szBuf);    else        _tprintf(L"\r\n操作失败\r\n");}bool IsDoStringCirculatorAgain(){    bool        bRc                     =   true;    wchar_t     cInput                  =   L' ';       ///< 用户输入的单个字符    wchar_t *   pcInput                 =   NULL;    wchar_t     szloopCnt[_MAX_PATH];                   ///< 容纳用户输入的移位字符数    wchar_t *   pszloopCnt              =   NULL;    _tprintf(L"\r\n是否开始一次新的字符串字符移位? 输入'Y'为继续, 输入'N'为取消, 支持大小写\r\n");    pcInput = &cInput;    GetUsrInput(pcInput, SIZEOF_WCHAR_ARRAY(cInput));    bRc = ((L'Y' == cInput) || (L'y' == cInput));    _tprintf(L"\r\n\r\n您的选择为[%s]\r\n", bRc ? L"继续" : L"取消");    return bRc;}

/// @file           helper\StringHelper.h/// @brief          字符串辅助操作定义#ifndef __HELPER_STRING_HELPER_H__#define __HELPER_STRING_HELPER_H__#include <windows.h>#include <locale.h>#include <tchar.h>#define WCHAR_STR_END   L'\0'   ///< 串结束符#define WCHAR_WORD_END  L' '    ///< 单词结束符#define SIZEOF_WCHAR_ARRAY(x)   (sizeof((x)) / sizeof(wchar_t))/// @fn         ReverseStringByWord/// @brief      对入参串进行单词反转, 单词之间的分隔符号为空格, ///             e.g. Hello world, driver => driver world Hello/// @param      IN OUT wchar_t * pcMsgW, 输入输出串, 反转后的结果串覆盖原字符串/// @return     bool/// @retval     true, 串反转成功/// @retval     false, 串反转失败bool    ReverseStringByWord(IN OUT wchar_t * pcMsgW);/// @fn         ReverseString/// @brief      对入参串进行完全反转///             e.g. 123456 7890 => 0987 654321/// @param      IN OUT wchar_t * pcMsgW, 输入输出串, 反转后的结果串覆盖原字符串/// @param      IN size_t nLenMsg, 串长度/// @return     bool/// @retval     true, 串反转成功/// @retval     false, 串反转失败bool    ReverseString(IN OUT wchar_t * pcMsgW, IN size_t nLenMsg);/// @fn         GetStringLength/// @brief      此算法不允许用C库函数参与串长度计算, 模拟实现计算串长度/// @param      IN const wchar_t * pcMsgW, 输入串/// @param      IN const wchar_t & cEndSeparator, 串的结束分隔符/// @param      IN const wchar_t & cStrEndSeparator, 字符串结尾字符/// @return     size_t, 返回的串长度. 如果串为NULL, 返回0.size_t  GetStringLength(IN const wchar_t * pcMsgW,                         IN const wchar_t & cEndSeparator,                         IN const wchar_t & cStrEndSeparator = WCHAR_STR_END);/// @fn         GetUserInputStringCirculatorParam/// @brief      请用户输入字符串, 指定左移或右移, 移位的字符数/// @param      wchar_t *& pszUsrInput, 容纳用户输入字符的缓冲区, 外部给定, 必须有效/// @param      size_t nInputBufLenMax, 输入缓冲区最大容量/// @param      bool & bLoopLeft, 左移 = TRUE, 右移 = FALSE/// @param      size_t & nLoopCnt, 移位的字符数, 可以大于字符串长度, 也可以为零,///             最后的移位字符数为字符串实际长度(不包括结尾'\0')的模/// @return     bool/// @retval     true, 用户输入参数成功/// @retval     false, 用户输入参数失败bool    GetUserInputStringCirculatorParam(wchar_t *& pszUsrInput,                                           size_t nInputBufLenMax,                                           bool & bLoopLeft,                                           size_t & nLoopCnt);/// @fn         GetUsrInput/// @brief      给定输入缓冲区, 等待用户输入, 以回车作为结束符/// @param      wchar_t *& pszUsrInput, 输入缓冲区/// @param      size_t nInputBufLenMax, 输入缓冲区长度/// @return     voidvoid    GetUsrInput(wchar_t *& pszUsrInput, size_t nInputBufLenMax);/// @fn         StringCirculator/// @brief      对输入串进行按字符数循环移位/// @param      wchar_t *& pszUsrInput, 输入串/// @param      bool bLoopLeft, 左移 = TRUE, 右移 = FALSE/// @param      size_t nLoopCnt, 移位的字符数, 可以大于字符串长度, 也可以为零,///             最后的移位字符数为字符串实际长度(不包括结尾'\0')的模/// @return     bool/// @retval     true, 成功/// @retval     false, 失败bool    StringCirculator(wchar_t *& pszUsrInput,                         bool bLoopLeft,                         size_t nLoopCnt);#endif

/// @file           helper\StringHelper.cpp/// @brief          字符串辅助操作, 实现串反转, 字符串移位等操作#include "stdafx.h"#include "StringHelper.h"bool    ReverseStringByWord(wchar_t * pcMsgW){    size_t  nLenAll     =   0;    size_t  nPosNow     =   0;    size_t  nPosPrev    =   0;    size_t  nLenStr     =   0;    if (NULL == pcMsgW)        return false;    /// 反转整个串    nLenAll = GetStringLength(pcMsgW, WCHAR_STR_END);    if (!ReverseString(pcMsgW, nLenAll))        return false;    /// 反转每个单词    while (nPosPrev < (nLenAll - 1))    {        nLenStr = GetStringLength(pcMsgW + nPosPrev, WCHAR_WORD_END);        /// 串长度 - 1 是位置, 位置是基于0的        nPosNow = nPosPrev + nLenStr - 1;        if ((nPosNow <= nPosPrev)             || (!ReverseString(pcMsgW + nPosPrev, nLenStr)))            break;        /// 下一个单词的起点是上一个单词的起点 + 一个单词分隔符长度 + 下一个单词的首字符        nPosPrev = nPosNow + 2;    }    return true;}bool    ReverseString(IN OUT wchar_t * pcMsgW, IN size_t nLenMsg){    wchar_t *   pcBegin =   NULL;    wchar_t *   pcEnd   =   NULL;    if (NULL == pcMsgW)        return false;    if (nLenMsg <= 1)        return true;    pcBegin = pcMsgW;    pcEnd = pcMsgW + nLenMsg - 1;    while (pcBegin < pcEnd)    {        /// 交换字符        *pcBegin ^= *pcEnd;        *pcEnd ^= *pcBegin;        *pcBegin ^= *pcEnd;        /// 移动头尾指针        pcBegin++;        pcEnd--;    }    return true;}size_t  GetStringLength(IN const wchar_t * pcMsgW,                         IN const wchar_t & cEndSeparator,                         IN const wchar_t & cStrEndSeparator){    size_t          nLenCnt    =   0;    const wchar_t * pcBegin =   pcMsgW;    if (NULL == pcBegin)        return 0;    while ((*(pcBegin + nLenCnt) != cEndSeparator)        && (*(pcBegin + nLenCnt) != cStrEndSeparator))        nLenCnt++; ///< 当前字符不是cEndSeparator, 也不是字符串结尾, 计数++    return nLenCnt;}bool    GetUserInputStringCirculatorParam(wchar_t *& pszUsrInput,                                           size_t nInputBufLenMax,                                           bool & bLoopLeft,                                           size_t & nLoopCnt){    wchar_t     cInput                  =   L' ';       ///< 用户输入的单个字符    wchar_t *   pcInput                 =   NULL;    wchar_t     szloopCnt[_MAX_PATH];                   ///< 容纳用户输入的移位字符数    wchar_t *   pszloopCnt              =   NULL;    if (nInputBufLenMax < 1)    {        _tprintf(L"缓冲区长度无效, 必须 >= 1\r\n");        return false;    }    if (NULL == pszUsrInput)    {        _tprintf(L"缓冲区为空\r\n");        return false;    }    _tprintf(L"\r\n请输入字符串, 支持中文和分隔符, 以回车作为输入结束符:\r\n");    ::ZeroMemory(pszUsrInput, nInputBufLenMax * sizeof(wchar_t));    GetUsrInput(pszUsrInput, nInputBufLenMax);    _tprintf(L"\r\n该字符串是左移还是右移? 输入'L'为左移, 输入'R'为右移, 支持大小写\r\n");    pcInput = &cInput;    GetUsrInput(pcInput, SIZEOF_WCHAR_ARRAY(cInput));    bLoopLeft = ((L'L' == cInput) || (L'l' == cInput));    _tprintf(L"\r\n请输入移位字符数, 可以为0 或大于字符串长度, 最终的移位字符数为您输入的移位字符数模字符串长度\r\n");    ::ZeroMemory(szloopCnt, sizeof(szloopCnt));    pszloopCnt = &szloopCnt[0];     GetUsrInput(pszloopCnt, SIZEOF_WCHAR_ARRAY(szloopCnt));     nLoopCnt = _ttoi64(szloopCnt);    _tprintf(L"\r\n\r\n您输入的字符串为: [%s]\r\n", pszUsrInput);    _tprintf(L"\r\n字符串循环字符移位操作为: %s%d个字符\r\n", bLoopLeft ? L"左移" : L"右移", nLoopCnt);}void    GetUsrInput(wchar_t *& pszUsrInput, size_t nInputBufLenMax){    size_t      nPos    =   0;    wchar_t     cInput  =   L' ';    if ((NULL == pszUsrInput) || (nInputBufLenMax < 1))        return;    while(1)    {        cInput = getwchar();    ///< _tprintf_s 有问题,不支持','分隔, 采用getwchar循环接收代替        if (L'\n' == cInput)            break;        if (nPos >= nInputBufLenMax)            break;        *(pszUsrInput + nPos++) = cInput;    }}bool    StringCirculator(wchar_t *& pszUsrInput,                          bool bLoopLeft,                          size_t nLoopCnt){    size_t  nLenAll         =   0;    size_t  nLoopCntReal    =   0;    if (NULL == pszUsrInput)        return false;    /// 反转整个串    nLenAll = GetStringLength(pszUsrInput, WCHAR_STR_END);    if (!ReverseString(pszUsrInput, nLenAll))        return false;    if (nLenAll < 1)        return false;    nLoopCntReal = nLoopCnt % nLenAll;    if (0 == nLoopCntReal)        return true;    /// 反转2个子串, 串边界为 nLenAll - nLoopCntReal    ReverseString(pszUsrInput, bLoopLeft ? (nLenAll - nLoopCntReal) : nLoopCntReal);    ReverseString(  pszUsrInput + (bLoopLeft ? (nLenAll - nLoopCntReal) : nLoopCntReal),                     bLoopLeft ? nLoopCntReal : (nLenAll - nLoopCntReal));    return true;}