/// @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; }