【字符串处理算法】将输入字符串中的各个单词反序的算法设计及C代码实现

开发 开发工具 算法
今天讲一讲将输入字符串中的各个单词反序的算法设计及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”虽然要合并在一起才有意义,但我们仍然按照两个不同的单词进行处理。

四、程序代码

  1. /********************************************************************** 
  2. * 版权所有 (C)2016, Zhou Zhaoxiong。 
  3. * 文件名称: ReverseTheString.c 
  4. * 文件标识: 无 
  5. * 内容摘要: 将字符串中的单词反序 
  6. * 其它说明: 例如, 将"I'm a student"转变为"student a I'm" 
  7. * 当前版本: V1.0 
  8. * 作    者: Zhou Zhaoxiong 
  9. * 完成日期: 20160215 
  10. **********************************************************************/ 
  11. #include <stdio.h> 
  12. #include <stdlib.h> 
  13.  
  14. // 重新定义数据类型 
  15. typedef signed   char       INT8; 
  16. typedef unsigned short int  UINT16; 
  17. typedef          int        INT32; 
  18. typedef unsigned int        UINT32; 
  19.  
  20. // 函数声明 
  21. INT32 GetFieldFromString(INT8 *pszIn, INT8 cSplitter, UINT16 iIdx, INT8 *pszOut, UINT16 iLen); 
  22. void CombineSpace(INT8 *pszOldStr, INT8 *pszNewStr); 
  23.  
  24.  
  25. /********************************************************************** 
  26. * 功能描述: 主函数 
  27. * 输入参数: 无 
  28. * 输出参数: 无 
  29. * 返 回 值: 0-执行成功   其它-执行失败 
  30. * 其它说明: 无 
  31. * 修改日期        版本号     修改人            修改内容 
  32. * --------------------------------------------------------------------- 
  33. * 20160215        V1.0     Zhou Zhaoxiong        创建 
  34. ***********************************************************************/ 
  35. INT32 main() 
  36.     INT8   szTestStr[500]   = {0}; 
  37.     INT8   szTmpStr[500]    = {0};  // 用于存放经过规范化处理之后的字符串 
  38.     INT8   szResultStr[500] = {0}; 
  39.     INT8   szFieldVal[100]  = {0}; 
  40.     INT32  iPosFlag         = 0
  41.     INT32  iRetFlag         = 0
  42.     UINT32 iBlankCount      = 0
  43.      
  44.     printf("Please input the string: \n"); 
  45.     gets(szTestStr); 
  46.     printf("TestStr=%s\n", szTestStr); 
  47.      
  48.     // 去除测试字符串中多余的空格及前后的空格 
  49.     CombineSpace(szTestStr, szTmpStr); 
  50.      
  51.     // 获取测试字符串中的空格字符的个数 
  52.     iPosFlag = 0
  53.     while (szTmpStr[iPosFlag] != '\0') 
  54.     { 
  55.         if (szTmpStr[iPosFlag] == ' ') 
  56.         { 
  57.             iBlankCount ++; 
  58.         } 
  59.          
  60.         iPosFlag ++; 
  61.     } 
  62.      
  63.     // 将测试字符串中的单词按照反序来拼接 
  64.     strcat(szTmpStr, " ");   // 在测试字符串***面添加空格, 用于解析各个单词 
  65.     for (iPosFlag = iBlankCount; iPosFlag >= 0; iPosFlag --) 
  66.     { 
  67.         memset(szFieldVal, 0x00, sizeof(szFieldVal)); 
  68.         iRetFlag = GetFieldFromString(szTmpStr, ' ', iPosFlag, szFieldVal, sizeof(szFieldVal)-1); 
  69.         if (iRetFlag != 0) 
  70.         { 
  71.             printf("Exec GetFieldFromString to get FieldVal failed!\n"); 
  72.             return -1; 
  73.         } 
  74.          
  75.         if (strlen(szResultStr) > sizeof(szResultStr)-1)     // 字符串超长, 直接退出 
  76.         { 
  77.             break; 
  78.         } 
  79.         else 
  80.         { 
  81.             strcat(szResultStr, szFieldVal);     // 将各个单词拼接起来 
  82.             strcat(szResultStr, " ");            // 在各个单词后面添加空格 
  83.         } 
  84.     } 
  85.      
  86.     if (szResultStr[strlen(szResultStr)-1] == ' ') 
  87.     { 
  88.         szResultStr[strlen(szResultStr)-1] = '\0';   // 去除***面的空格 
  89.     } 
  90.      
  91.     printf("ResultStr=%s\n", szResultStr); 
  92.  
  93.     return 0;             
  94.  
  95.  
  96. /********************************************************************** 
  97. * 功能描述: 从字符串中获取字段的值 
  98. * 输入参数: 无 
  99. * 输出参数: 无 
  100. * 返 回 值: 0-执行成功   其它-执行失败 
  101. * 其它说明: 无 
  102. * 修改日期        版本号     修改人            修改内容 
  103. * --------------------------------------------------------------------- 
  104. * 20160215        V1.0     Zhou Zhaoxiong        创建 
  105. ***********************************************************************/ 
  106. INT32 GetFieldFromString(INT8 *pszIn, INT8 cSplitter, UINT16 iIdx, INT8 *pszOut, UINT16 iLen) 
  107.     INT8   *pszStart    = NULL
  108.     INT8   *pszEnd      = NULL
  109.     UINT16  iCount      = 0
  110.     UINT16  iFiledLen   = 0
  111.     INT8    szBuf[1024] = {0}; 
  112.  
  113.     if (NULL == pszIn || NULL == pszOut) 
  114.     { 
  115.         return -1; 
  116.     } 
  117.  
  118.     pszStart = pszIn
  119.     for (iCount = 0; iIdx != iCount; iCount++)   // for循环用于查找当前字段的起始位置 
  120.     { 
  121.         pszStart = strchr(pszStart, cSplitter); 
  122.         if (NULL == pszStart) 
  123.         { 
  124.             break; 
  125.         } 
  126.         else 
  127.         { 
  128.             pszStart ++; 
  129.         } 
  130.     } 
  131.  
  132.     if (NULL == pszStart) 
  133.     { 
  134.         return -2; 
  135.     } 
  136.  
  137.     pszEnd = strchr(pszStart, cSplitter); 
  138.     if (NULL == pszEnd) 
  139.     { 
  140.         return -3; 
  141.     } 
  142.  
  143.     // 判断长度大小, 防止拷贝字符串时越界 
  144.     if (pszEnd - pszStart > sizeof(szBuf)-1) 
  145.     { 
  146.         iFiledLen = sizeof(szBuf)-1; 
  147.     } 
  148.     else 
  149.     { 
  150.         iFiledLen = pszEnd - pszStart; 
  151.     } 
  152.      
  153.     strncpy(szBuf, pszStart, iFiledLen); 
  154.  
  155.     if (iLen < iFiledLen)   // 传入的长度太小 
  156.     { 
  157.         return -4; 
  158.     } 
  159.  
  160.     strncpy(pszOut, szBuf, iFiledLen); 
  161.  
  162.     return 0; 
  163.  
  164.  
  165. /********************************************************************** 
  166. * 功能描述:合并多个连续空格为一个, 并去掉首位的空格 
  167. * 输入参数:pszOldStr-合并空格之前的字符串 
  168. * 输出参数:pszNewStr-合并空格之后的字符串 
  169. * 返 回 值:无 
  170. * 其它说明:无 
  171. * 修改日期       版本号        修改人          修改内容 
  172. * ------------------------------------------------------------------- 
  173. * 20160215       V1.0      Zhou Zhaoxiong       创建 
  174. ***********************************************************************/ 
  175. void CombineSpace(INT8 *pszOldStr, INT8 *pszNewStr) 
  176.     UINT32 iOldIndex        = 0
  177.     UINT32 iNewIndex        = 0
  178.     INT8   chSingleChar     = '\0'
  179.     INT8   iIsSpace         = 0
  180.     INT8   szTmpNewStr[100] = {0}; 
  181.  
  182.     if ((NULL == pszOldStr) || (NULL == pszNewStr)) 
  183.     { 
  184.         return; 
  185.     } 
  186.  
  187.     while ('\0' != (chSingleChar = pszOldStr[iOldIndex++])) 
  188.     { 
  189.         if (chSingleChar == ' ')   // 多个连续空格只保留一个 
  190.         { 
  191.             if (iIsSpace == 0) 
  192.             { 
  193.                 iIsSpace = 1
  194.                 szTmpNewStr[iNewIndex++] = chSingleChar; 
  195.             } 
  196.         } 
  197.         else 
  198.         { 
  199.             iIsSpace = 0
  200.             szTmpNewStr[iNewIndex++] = chSingleChar; 
  201.         } 
  202.     } 
  203.  
  204.     // 如果***一个字符是空格, 则将其去掉 
  205.     if (szTmpNewStr[strlen(szTmpNewStr)-1] == ' ') 
  206.     { 
  207.         szTmpNewStr[strlen(szTmpNewStr)-1] = '\0'; 
  208.     } 
  209.  
  210.     // 如果***个字符是空格, 则将其去掉 
  211.     if (szTmpNewStr[0] == ' ') 
  212.     { 
  213.         memcpy(pszNewStr, szTmpNewStr+1, strlen(szTmpNewStr)-1); 
  214.     } 
  215.     else 
  216.     { 
  217.         memcpy(pszNewStr, szTmpNewStr, strlen(szTmpNewStr)); 
  218.     } 
  219.  
  220.     return; 

五、程序测试

我们将编写好的程序“ReverseTheString.c”上传到Linux机器,并使用“gcc -g -o ReverseTheStringReverseTheString.c”命令对该程序进行编译,生成“ReverseTheString”文件。下面对程序进行详细的测试。

1.输入字符串为“Hello, how do you do”时,程序运行情况如下:

  1. Please input the string: 
  2. Hello, how do you do 
  3. TestStr=Hello, how do you do 
  4. ResultStr=do you do how Hello, 

2.输入字符串为“ Hello, how do you do”(注意,前面有两个空格)时,程序运行情况如下:

  1. Please input the string: 
  2.   Hello, how do you do 
  3. TestStr=  Hello, how doyou do 
  4. ResultStr=do you do how Hello, 

3.输入字符串为“Hello, how do you do ”(注意,后面有两个空格)时,程序运行情况如下:

  1. Please input the string: 
  2. Hello, how do you do  
  3. TestStr=Hello, how do you do  
  4. ResultStr=do you do how Hello, 

4.输入字符串为“Hello, how do you do”(注意,中间有连续的空格)时,程序运行情况如下:

  1. Please input the string: 
  2. Hello,  how do   you  do 
  3. TestStr=Hello,  howdo   you  do 
  4. ResultStr=do you do how Hello, 

5.输入字符串为“Hello, ho w do yo u do”(注意,将几个完整的单词用空格分开)时,程序运行情况如下:

  1. Please input the string: 
  2. Hello, ho w do yo u do 
  3. TestStr=Hello, ho w do yo u do 
  4. 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)】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2016-12-30 13:32:24

字符串算法代码

2016-12-30 13:16:51

字符串算法代码

2016-12-29 17:14:41

回文串算法代码

2016-12-29 17:07:59

字符算法代码

2016-12-29 15:58:00

字符串子串算法

2021-09-10 08:31:54

翻转字符串单词

2023-02-26 22:33:32

字符串排列算法

2023-12-15 10:27:01

暴力匹配算法Python字符串

2013-05-06 10:54:08

字符串字符串匹配KMP算法

2009-08-11 10:26:49

C#算法C#字符串反转

2021-09-03 09:41:36

字符串时间复杂度

2021-09-07 09:23:07

C++字符串算法

2010-11-26 09:51:54

MySQL字符串

2013-05-06 10:49:21

Boyer-Moore算法字符串匹配

2016-12-29 16:25:32

字符串算法代码

2021-08-26 05:08:25

相邻重复项算法

2012-01-11 09:15:45

Objective-C

2023-04-11 08:54:57

字符串匹配算法

2009-08-20 18:23:29

C#中SQL连接字符串

2024-07-03 11:23:14

点赞
收藏

51CTO技术栈公众号