/// @file SrcReverseWord.cpp
/// @brief 实现对串的单词逆序 e.g. Hello world driver => driver world Hello
/// 算法:
/// * 先对串进行整体逆序,
/// * 再找每个单词的分隔符' ', 确定每个单词内容
/// * 对每个单词进行逆序
/// @note 测试环境: vs2008 + win7x64sp1
#include "stdafx.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);
int _tmain(int argc, _TCHAR* argv[])
{
size_t nLen = 0;
size_t nPos = 0;
wchar_t cInput = L' ';
wchar_t cBuf[_MAX_PATH];
::ZeroMemory(cBuf, sizeof(cBuf));
setlocale(LC_CTYPE, ".936"); //< 控制台为中文输出
_tprintf(L"请输入字符串, 支持中文和分隔符, 以回车作为输入结束符:\r\n");
nLen = SIZEOF_WCHAR_ARRAY(cBuf);
/// 测试用的字符串如下:
/// Hello world, Alg! 这是一个单词反转算法, 先进行字符串全反转, 再进行每个单词的反转.
while(1)
{
cInput = getwchar(); ///< _tprintf_s 有问题,不支持','分隔, 采用getwchar循环接收代替
if (L'\n' == cInput)
break;
if (nPos >= nLen)
break;
cBuf[nPos++] = cInput;
}
_tprintf(L"\r\n您输入的字符串为: [%s]\r\n", cBuf);
if (ReverseStringByWord(cBuf))
_tprintf(L"\r\n单词反转后的串为 : [%s]\n", cBuf);
else
_tprintf(L"\r\n输入串无效\r\n");
_tprintf(L"\r\n运行完成, 按任意键退出\r\n");
/** runresult
请输入字符串, 支持中文和分隔符, 以回车作为输入结束符:
Hello world, Alg! 这是一个单词反转算法, 先进行字符串全反转, 再进行每个单词的反转
.
您输入的字符串为: [Hello world, Alg! 这是一个单词反转算法, 先进行字符串全反转,
再进行每个单词的反转.]
单词反转后的串为 : [再进行每个单词的反转. 先进行字符串全反转, 这是一个单词反转算
法, Alg! world, Hello]
运行完成, 按任意键退出
*/
getchar();
return 0;
}
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;
}