问题引入

最近在解决AHNU在线测试http://172.16.94.19:8080/JudgeOnline/showproblem?problem_id=1496时,遇到了麻烦,问题描述如下:

Description

读取一行文本,输出相同的文本,但将所有整数中的数字替换成’x’(长度不限)。

Input

一行文本。

Output

替换后的一行文本。

Sample Input

My userID is john17 and my 4 digit pin is 12345 which is secret.

Sample Output

My userID is john17 and my x digit pin is xxxxx which is secret.

初步解决步骤如下:

①将输入的文本text按照空格为分隔符,将每个单词存到字符串数组word中(单词总数可由text字符串中空格数确定);

②对字符串数组word的每一个元素word[i]字符串进行判断,若字符串word[i]中全由数字组成,则将该串的每一个字符替换为'x';

③构造循环,依次输出字符串数组的每一个元素,实现数字替换。

基于以上想法,构造以下函数,分别为:字符串切割函数(实现步骤①)、字符串转换函数(实现步骤②)

字符串切割函数

void Split(char *text,char **word)
{int i=0;int k=0;//当前已完成单词数int j=0;while(i<strlen(text)){j=0;while(text[i]!=' '&&text[i]!='\0'){word[k][j]=text[i];j++; i++;}word[k][j]='\0';//printf("%s ",word[k]);//printf("k:%d i:%d j:%d\n",k,i,j);k++;i++;}
}

字符串转换函数

void Convert(char **word,int num)//若字符串s中全为数字,则将所有数字转化为'x'
{int i,j=0;int count=0;int R[256]={0}; /*********************初始化数组R**********************/for(i=48;i<=58;i++)R[i]=1;//数字位置置为1/*****************************************************/for(i=0;i<num;i++){j=0;count=0;while(j<strlen(word[i])){count+=R[word[i][j]];j++;}//printf("%d ",count);if(count==strlen(word[i]))//数字字符数等于字符串长度{j=0;while(j<strlen(word[i])){word[i][j]='x';j++;}}}
}

主函数

int main()
{char text[300000];//要求输入长度无限char **word;int num=0,i;gets(text);num=WordCount(text);word=(char**)malloc(num*sizeof(char*));for(i=0;i<num;i++)word[i]=(char*)malloc(50*sizeof(char));//为每个单词分配内存空间Split(text,word);Convert(word,num);for(i=0;i<num;i++)printf("%s ",word[i]);//输出测试 for(i=0;i<num;i++)free(word[i]);//释放每个单词内存空间free(word);//printf("%d",num);return 0;
}

实际运行时,对于长度在可接受范围内的字符串,运行效果良好。但对于测试数据5,输入的数据为一长度近300000的字符串,此时程序运行缓慢,近20s,提交时出现了Time Limit Exceed 的错误。通过分析,主要时间花费在字符串切割函数Split()中,因此若基于以上解题步骤,必须找到一种高效的字符串切割算法。

算法改进

实际上,C语言头文件<string.h>中提供了字符串切割函数strok(),经过测试,该函数的时间复杂度较好,能够满足要求。将其与原字符串切割函数替换后,程序执行时间大大降低,可保持在10s内。Convert()字符串转换函数思想不改,同时将字符串切割体现在主函数里。修改后的Convert()和main()函数如下:

字符串转换函数Convert()

void Convert(char *word)//若字符串s中全为数字,则将所有数字转化为'x'
{int i,j=0;int count=0;int R[256]={0}; /*********************初始化数组R**********************/for(i=48;i<=58;i++)R[i]=1;//数字位置置为1/*****************************************************/j=0;count=0;while(j<strlen(word)){count+=R[word[j]];j++;}if(count==strlen(word))//数字字符数等于字符串长度{j=0;while(j<strlen(word)){word[j]='x';j++;}}
}

主函数main()

int main(void)
{char text[3000000];gets(text);char *temp = strtok(text," ");printf("%s\n",temp);while(temp){Convert(temp);printf("%s ",temp);temp = strtok(NULL," ");}return 0;
}

结论

strotok()函数切割字符串效率较高,实际应用中应当掌握该函数的参数以及返回类型,必要时需要明白实现机制。关于strotok()函数我将在下一篇博客中详细介绍。

P.S. 20190807更新:最近重新看这题,发现一个容易理解的新的算法

大致思想是:找到字符串中所有空格出现的位置,之后判断空格之间的字符是否全部是数字,若是,则替换为'x'(实际上也是分割的思想)。这里需要注意-1和字符串长度也要作为空格出现的位置容器中(原因不解释,应该很容易理解)。

#include <iostream>
#include <vector>
#include <cctype>
using namespace std;
void showPos(vector<int> pos);
/*
New solution:
find all blank's position, and judge whether the string between near two blanks only includes digit.
*/
int main()
{string s;int i,n=0,k;int l,r;int flag;vector<int> pos;getline(cin,s);//cout<<s<<endl;pos.push_back(-1);//Attentionn++;for(i=0;i<s.length();i++){if(s.at(i)==' '){pos.push_back(i);n++;}}pos.push_back(s.length());//Attentionn++;//showPos(pos);for(i=0;i<n-1;i++){flag=0;l=pos[i]+1;r=pos[i+1]-1;//cout<<"("<<l<<","<<r<<")"<<endl;for(k=l;k<=r;k++)if(!isdigit(s.at(k)))flag=1;if(!flag)for(k=l;k<=r;k++)s[k]='x';}cout<<s<<endl;return 0;
}
void showPos(vector<int> pos)
{int i=0;int n=pos.size();for(;i<n;i++)cout<<pos[i]<<" ";cout<<endl;
}

引入:字符串切割strtok()函数相关推荐

  1. 字符串切割函数strtok、strtok_s、strtok_r的区别

    strtok函数 头文件:#include <string.h> 函数原型:char * strtok (char *str, const char * delimiters); 参数:s ...

  2. c语言中strtok函数详解,手把手教你自主实现字符串切割函数,内附详细代码。

    函数功能简介: 对字符串str进行切割,切割的标志为字符指针q指向的这两个字符 "# *":. 但是在对这个函数进行调用时,只有在第一次调用时,才会将str这个字符串的首地址传递过 ...

  3. C和指针之字符串strtok函数

    1.strtok函数 头文件:#include <string.h> 定义函数:char * strtok(char *s, const char *delim); 函数说明:strtok ...

  4. bob-tong 字符串函数之Strtok()函数

    https://www.cnblogs.com/Bob-tong/p/6610806.html Strtok()函数详解:   该函数包含在"string.h"头文件中  函数原型 ...

  5. C语言字符串函数(3)strstr,strtok函数的详解

    上一期,我讲解了关于字符串函数中,受限制的字符串函数,有想了解的小伙伴们可以点此链接去看看:C语言字符串函数(2)受限制的字符串函数 那么今天,我来讲一讲标题中这两个函数的作用和使用方法. 目录 一. ...

  6. 【摘录】C语言中利用 strtok函数进行字符串分割

    C语言不像Java,Php之类的高级语言,对象中直接封装了字符串的处理函数.C语言中进行普通的字符串处理也经常会让我们焦头烂额--不过好在C语言 中还是提供了像strtok这样功能强大的字符串处理函数 ...

  7. C/C++根据特定字符分割字符串、读取文件去掉逗号等特定字符、strtok()函数详解

    字符串分割情况 读取文件时,C++识别的是空格和换行符,但有时候文件是以符号分割的,如逗号等 字符串本身含有特殊符号,如逗号,@等 strtok()函数 strtok()函数能够按照特定的字符分解字符 ...

  8. C语言strtok()函数:字符串分割

    1.头文件:#include <string.h> 2.定义函数:char * strtok(char *s, const char *delim);      分解字符串为一组字符串.s ...

  9. C++中使用strtok函数分割字符串String

    C++中使用strtok函数分割字符串String string str; getline(cin,str); vector<string> vec; char *p = strtok(( ...

最新文章

  1. C语言static 具体分析
  2. 并行计算与分布式计算
  3. 多维分析中的 UV 与 PV
  4. 安卓系统曝漏洞!有人可能正在用你的手机秘密拍照
  5. 锂电池电量百分比计算_锂电池充放电理论及电量计算方法设计
  6. 消费者启动,允许期间报task supervisor timed out 异常,解决
  7. cocos2d学习之路四(添加遥控杆)
  8. 获取extjs 选择后的表头_OD数据获取脚本分享
  9. 压力测试的轻量级具体做法
  10. android Camera framework层解析
  11. Javaweb - JSP章节 - MVC和三层架构案例总练习(下) - “回显数据”-“修改数据”功能实现
  12. Guava的Splitter和Joiner
  13. 在股东协议中,如何设定关于股权转让的相关规定,如股东优先购买权、股权出售限制、股权转让审批流程等?
  14. centos7防火墙命令
  15. Cesium量算-贴地形距离
  16. JS实现Canvas中图片淡出效果_艾孜尔江撰
  17. c语言基础知识题目,C语言基础知识复习题
  18. 小票打印ESC/POS命令集
  19. VS2010 C# ReportViewer控件新手上路心得
  20. P1498 南蛮图腾(C++_递推)

热门文章

  1. 【推荐】编程语言学习网站
  2. 什么叫软文营销,软文营销应该怎么做
  3. 【vue】canvas图片剪切
  4. wp优秀个人博客网站模板推荐
  5. Openstack : 17、在vmware的centos7虚拟机中通过packstack安装openstack queen版本
  6. 购物车,朋友圈等测试点
  7. 生活-MBTI职业性格测试
  8. 混合(Blending)
  9. u大侠制作linux启动盘,U大侠U盘启动盘制作教程
  10. IOMMU/SMMUV3代码分析(8)函数dma_map_sg()