【字符串處理算法】將輸入字符串中的各個單詞反序的算法設計及C代碼實現
一、需求描述
輸入一個字符串,編寫程序將該字符串中的各個單詞反序拼裝并輸出。例如,如果輸入的字符串是“Hello, how do you do”,那么輸出的字符串為“do you do how Hello,”。注意保留各個單詞之間的空格及相應的標點符號。
二、算法設計
通過觀察示例字符串(即“Hello, how do you do”),我們可以看到該字符串中各個單詞與空格之間的關系為:單詞總數=空格總數+1。也就是說,示例字符串中的空格總數為4,單詞個數為5(即“Hello,”、“how”、“do”、“you”、“do”)。
因此,我們可以考慮先找出輸入字符串中的空格總數,再根據空格找出各個單詞,然后將這些單詞反序拼裝起來。
程序的總體流程如圖1所示。
圖1 程序的總體流程
三、特殊流程考慮
在編寫程序的過程中,我們要對輸入字符串的格式多做考慮,如:
1.輸入字符串的開頭幾個字符為空格,即形如“ Hello,how do you do”,我們需要先將開頭的幾個空格去掉,再進行后續處理。
2.輸入字符串的結尾幾個字符為空格,即形如“Hello, how do you do ”,我們需要先將結尾的幾個空格去掉,再進行后續處理。
3.輸入字符串的中間幾個字符為連續的空格,即形如“Hello, how do youdo”,我們需要先將連續的空格合并為一個空格,再進行后續處理。
4.只要輸入字符串中的兩個單詞之間出現了空格,我們都把它們當作兩個不同的單詞,即使這兩個單詞沒有實際的意思,即形如“Hello, how do y ou do”,其中的“y”和“ou”雖然要合并在一起才有意義,但我們仍然按照兩個不同的單詞進行處理。
四、程序代碼
- /**********************************************************************
- * 版權所有 (C)2016, Zhou Zhaoxiong。
- *
- * 文件名稱: ReverseTheString.c
- * 文件標識: 無
- * 內容摘要: 將字符串中的單詞反序
- * 其它說明: 例如, 將"I'm a student"轉變為"student a I'm"
- * 當前版本: V1.0
- * 作 者: Zhou Zhaoxiong
- * 完成日期: 20160215
- *
- **********************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- // 重新定義數據類型
- typedef signed char INT8;
- typedef unsigned short int UINT16;
- typedef int INT32;
- typedef unsigned int UINT32;
- // 函數聲明
- INT32 GetFieldFromString(INT8 *pszIn, INT8 cSplitter, UINT16 iIdx, INT8 *pszOut, UINT16 iLen);
- void CombineSpace(INT8 *pszOldStr, INT8 *pszNewStr);
- /**********************************************************************
- * 功能描述: 主函數
- * 輸入參數: 無
- * 輸出參數: 無
- * 返 回 值: 0-執行成功 其它-執行失敗
- * 其它說明: 無
- * 修改日期 版本號 修改人 修改內容
- * ---------------------------------------------------------------------
- * 20160215 V1.0 Zhou Zhaoxiong 創建
- ***********************************************************************/
- INT32 main()
- {
- INT8 szTestStr[500] = {0};
- INT8 szTmpStr[500] = {0}; // 用于存放經過規范化處理之后的字符串
- INT8 szResultStr[500] = {0};
- INT8 szFieldVal[100] = {0};
- INT32 iPosFlag = 0;
- INT32 iRetFlag = 0;
- UINT32 iBlankCount = 0;
- printf("Please input the string: \n");
- gets(szTestStr);
- printf("TestStr=%s\n", szTestStr);
- // 去除測試字符串中多余的空格及前后的空格
- CombineSpace(szTestStr, szTmpStr);
- // 獲取測試字符串中的空格字符的個數
- iPosFlag = 0;
- while (szTmpStr[iPosFlag] != '\0')
- {
- if (szTmpStr[iPosFlag] == ' ')
- {
- iBlankCount ++;
- }
- iPosFlag ++;
- }
- // 將測試字符串中的單詞按照反序來拼接
- strcat(szTmpStr, " "); // 在測試字符串***面添加空格, 用于解析各個單詞
- for (iPosFlag = iBlankCount; iPosFlag >= 0; iPosFlag --)
- {
- memset(szFieldVal, 0x00, sizeof(szFieldVal));
- iRetFlag = GetFieldFromString(szTmpStr, ' ', iPosFlag, szFieldVal, sizeof(szFieldVal)-1);
- if (iRetFlag != 0)
- {
- printf("Exec GetFieldFromString to get FieldVal failed!\n");
- return -1;
- }
- if (strlen(szResultStr) > sizeof(szResultStr)-1) // 字符串超長, 直接退出
- {
- break;
- }
- else
- {
- strcat(szResultStr, szFieldVal); // 將各個單詞拼接起來
- strcat(szResultStr, " "); // 在各個單詞后面添加空格
- }
- }
- if (szResultStr[strlen(szResultStr)-1] == ' ')
- {
- szResultStr[strlen(szResultStr)-1] = '\0'; // 去除***面的空格
- }
- printf("ResultStr=%s\n", szResultStr);
- return 0;
- }
- /**********************************************************************
- * 功能描述: 從字符串中獲取字段的值
- * 輸入參數: 無
- * 輸出參數: 無
- * 返 回 值: 0-執行成功 其它-執行失敗
- * 其它說明: 無
- * 修改日期 版本號 修改人 修改內容
- * ---------------------------------------------------------------------
- * 20160215 V1.0 Zhou Zhaoxiong 創建
- ***********************************************************************/
- INT32 GetFieldFromString(INT8 *pszIn, INT8 cSplitter, UINT16 iIdx, INT8 *pszOut, UINT16 iLen)
- {
- INT8 *pszStart = NULL;
- INT8 *pszEnd = NULL;
- UINT16 iCount = 0;
- UINT16 iFiledLen = 0;
- INT8 szBuf[1024] = {0};
- if (NULL == pszIn || NULL == pszOut)
- {
- return -1;
- }
- pszStart = pszIn;
- for (iCount = 0; iIdx != iCount; iCount++) // for循環用于查找當前字段的起始位置
- {
- pszStart = strchr(pszStart, cSplitter);
- if (NULL == pszStart)
- {
- break;
- }
- else
- {
- pszStart ++;
- }
- }
- if (NULL == pszStart)
- {
- return -2;
- }
- pszEnd = strchr(pszStart, cSplitter);
- if (NULL == pszEnd)
- {
- return -3;
- }
- // 判斷長度大小, 防止拷貝字符串時越界
- if (pszEnd - pszStart > sizeof(szBuf)-1)
- {
- iFiledLen = sizeof(szBuf)-1;
- }
- else
- {
- iFiledLen = pszEnd - pszStart;
- }
- strncpy(szBuf, pszStart, iFiledLen);
- if (iLen < iFiledLen) // 傳入的長度太小
- {
- return -4;
- }
- strncpy(pszOut, szBuf, iFiledLen);
- return 0;
- }
- /**********************************************************************
- * 功能描述:合并多個連續空格為一個, 并去掉首位的空格
- * 輸入參數:pszOldStr-合并空格之前的字符串
- * 輸出參數:pszNewStr-合并空格之后的字符串
- * 返 回 值:無
- * 其它說明:無
- * 修改日期 版本號 修改人 修改內容
- * -------------------------------------------------------------------
- * 20160215 V1.0 Zhou Zhaoxiong 創建
- ***********************************************************************/
- void CombineSpace(INT8 *pszOldStr, INT8 *pszNewStr)
- {
- UINT32 iOldIndex = 0;
- UINT32 iNewIndex = 0;
- INT8 chSingleChar = '\0';
- INT8 iIsSpace = 0;
- INT8 szTmpNewStr[100] = {0};
- if ((NULL == pszOldStr) || (NULL == pszNewStr))
- {
- return;
- }
- while ('\0' != (chSingleChar = pszOldStr[iOldIndex++]))
- {
- if (chSingleChar == ' ') // 多個連續空格只保留一個
- {
- if (iIsSpace == 0)
- {
- iIsSpace = 1;
- szTmpNewStr[iNewIndex++] = chSingleChar;
- }
- }
- else
- {
- iIsSpace = 0;
- szTmpNewStr[iNewIndex++] = chSingleChar;
- }
- }
- // 如果***一個字符是空格, 則將其去掉
- if (szTmpNewStr[strlen(szTmpNewStr)-1] == ' ')
- {
- szTmpNewStr[strlen(szTmpNewStr)-1] = '\0';
- }
- // 如果***個字符是空格, 則將其去掉
- if (szTmpNewStr[0] == ' ')
- {
- memcpy(pszNewStr, szTmpNewStr+1, strlen(szTmpNewStr)-1);
- }
- else
- {
- memcpy(pszNewStr, szTmpNewStr, strlen(szTmpNewStr));
- }
- return;
- }
五、程序測試
我們將編寫好的程序“ReverseTheString.c”上傳到Linux機器,并使用“gcc -g -o ReverseTheStringReverseTheString.c”命令對該程序進行編譯,生成“ReverseTheString”文件。下面對程序進行詳細的測試。
1.輸入字符串為“Hello, how do you do”時,程序運行情況如下:
- Please input the string:
- Hello, how do you do
- TestStr=Hello, how do you do
- ResultStr=do you do how Hello,
2.輸入字符串為“ Hello, how do you do”(注意,前面有兩個空格)時,程序運行情況如下:
- Please input the string:
- Hello, how do you do
- TestStr= Hello, how doyou do
- ResultStr=do you do how Hello,
3.輸入字符串為“Hello, how do you do ”(注意,后面有兩個空格)時,程序運行情況如下:
- Please input the string:
- Hello, how do you do
- TestStr=Hello, how do you do
- ResultStr=do you do how Hello,
4.輸入字符串為“Hello, how do you do”(注意,中間有連續的空格)時,程序運行情況如下:
- Please input the string:
- Hello, how do you do
- TestStr=Hello, howdo you do
- ResultStr=do you do how Hello,
5.輸入字符串為“Hello, ho w do yo u do”(注意,將幾個完整的單詞用空格分開)時,程序運行情況如下:
- Please input the string:
- Hello, ho w do yo u do
- TestStr=Hello, ho w do yo u do
- ResultStr=do u yo do w ho Hello,
可見,對于上面考慮到的幾種特殊情況,程序均能做出正確的處理。
六、需求擴展
基于本文中的需求和程序,我們可考慮對需求進行以下擴展:
1.將反序之后的字符串的首字母大小,并將反序之前的首字母從大寫變為小寫,即將“Hello, how do you do”轉換為“Do you do how hello,”。
2.不改變原字符串中的***的標點符號的位置,即將“Hello, how do you do!”轉換為“do you do how Hello,!”。
3.將原字符串中的標點符號去掉,即將“Hello, how do you do!”轉換為“do you do how Hello”。
【本文是51CTO專欄作者周兆熊的原創文章,作者微信公眾號:周氏邏輯(logiczhou)】