ACM讲课之字符串
本次讲课讲全面介绍字符串以及如何使用字符串解决具体问题。
一、什么是字符串
1.如何存储字符串
平时我们使用的变量有很多,int代表整型变量,double代表浮点型变量,char代表字符型变量,那么对于一个字符串例如“Hello World!”应该如何存储并操作呢。
在C语言里,我们可以char数组进行存储,例如:
1 char str1[] = "Hello World!"; 2 char* str2 = "Hello World!"; 3 char str3[20] = "Hello World!";
对str1、2、3进行输出都为“Hello World!”,这三种方式构造一个字符串的区别有哪些?我们输出他们的空间长度(注意是占用的空间长度而不是字符串长度)。
1 int len1 = sizeof(str1)/sizeof(char); 2 int len2 = sizeof(str2)/sizeof(char); 3 int len3 = sizeof(str3)/sizeof(char); 4 printf("%d\n%d\n%d\n",len1,len2,len3);
结果为:13
4
20
(此处应对上诉结果进行解释说明 ==)
既然字符串可以存储在一个字符数组里面,那么如何对字符串进行操作想必也就非常清楚了。需要注意的是,对于计算机可以字符和一个整型变量没有任何区别,它们都是数据,所以对整型变量可以做的操作都可以对一个字符进行同样的操作。
2.ASCII编码
众所周知字符在C/C++里面是以ASCII码的形式存储在计算机中,既然字符串是存储在字符数组里面的,其实也就是多个字符的一个有序集合。它也遵守和字符同样的的规则,例如'A'的ASCII码为65,如果我们进行下列语句
1 char ch = 'A'; 2 if(ch == 'A'){ 3 ch = ch + 5; 4 } 5 else { 6 ch = ch - 1; 7 }
那么这里ch的值应该变成多少了呢?此时的ch又代表哪个字符呢?
3.std::string
是不是没见过这是什么东西,它其实就是character string(字符串),这是一个C++的语句,意思就是调用std(标准命名空间)里面的string类,可能你也已经猜到了string是用来干什么的,是的它可以直接定义一个字符串变量,并且能够直接对串进行操作。
什么意思呢?我们既然已经能够用字符数组存储字符串了,为什么还需要多个string呢,因为我们前面说了字符串数组相当于一个字符的有序集合,归根到底还都是单个字符,而字符串变量string才是真正的字符串,它可以直接对串操作,例如下列语句:
std::string str = "Hello"; str += " World"; str += "!";
如果仅仅只是这样,那么string并不显得强大,事实上string支持下面的功能
但是值得注意的是,string是c++语言的东西,在c语言中并不能使用,而且string只能通过cin流进行读入操作,同样可以使用下标对string字符串进行每一位的访问以及操作。
C++也还有很多C语言没有的容器,通过这些容器对做题有很大帮助,而且这些容器对于一个ACMer来说是必须要掌握的,详情请戳:
STL容器(Stack, Queue, List, Vector, Deque, Priority_Queue, Map, Pair, Set, Multiset, Multimap)
二、字符串操作
1.空格、换行符
我们知道使用scanf("%s",s);读入一个字符串遇到空格和换行符自动跳出,但是对于一个字符串不可能都没有空格以及换行呀,如果是需要读入一个句子那该怎么办呢,对于C语言,我提供了下列几种方法供参考
1 //方法一——判断是否为空格选择继续读入还是跳出 2 char s[100],ch; 3 scanf("%s",s); 4 ch = getchar(); 5 while(ch == ' '){ 6 int len = strlen(s); 7 s[len] = ' '; 8 scanf("%s",s+len+1); 9 ch = getchar(); 10 } 11 12 //方法二——利用格式符%[]设置结束符 13 char s[100]; 14 scanf("%[^\n]",s); 15 16 17 //方法三——利用不安全的gets进行读入 18 char s[100]; 19 gets(s);
三种方法都可以进行读入以换行符为结束符带有空格的字符串,但是我推荐最好使用第一种,为什么?
(此处应对上述进行解释说明)
在C++语言中,想要读入这样的串,我也同样提供几种方法供参考
1 //方法一——使用cin流对字符串进行读入 2 char s[100]; 3 cin.getline(s,100); 4 5 //方法二——使用getline进行string类读入 6 string s; 7 getline(cin,s);
下面以一个例题为例,对字符串的具体操作进行讲解
题目链接:http://120.78.128.11/Problem.jsp?pid=1716
下面我贴出C语言和C++语言的代码
C语言:
1 #include <stdio.h> 2 #include <string.h> 3 char s1[10005],s2[105]; 4 5 void read(char *s){ 6 int ch; 7 scanf("%s",s); 8 ch = getchar(); 9 while(ch == ' '){ 10 int len = strlen(s); 11 s[len] = ' '; 12 scanf("%s",s+len+1); 13 ch = getchar(); 14 } 15 } 16 17 int main(){ 18 int t; 19 scanf("%d",&t); 20 while(t--){ 21 read(s1),read(s2);//读入字符串 22 int len1 = strlen(s1),len2 = strlen(s2); 23 int flag = -1,i,j; 24 for(i = 0; i < len1; i++){ 25 if(s1[i] == s2[0]){ 26 for(j = 0; j < len2; j++){ 27 if(j == len2-1 && s1[i+j] == s2[j]) 28 flag = i+1; 29 if(s1[i+j] != s2[j]) 30 break; 31 } 32 } 33 } 34 printf("%d\n",flag); 35 } 36 return 0; 37 }
C++语言:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 string s1,s2; 5 6 int main(){ 7 int t; 8 cin>>t; 9 cin.get(); 10 while(t--){ 11 getline(cin,s1),getline(cin,s2); 12 int pos = s1.find(s2); 13 cout << (pos==-1?-1:pos+1) << endl; 14 } 15 return 0; 16 }
这也是为什么要用C++的原因,C++内置函数以及操作实在是太强大了,两个C中较为冗长的函数在C++中都只要用一句便实现了。
另一个例题:http://120.78.128.11/Problem.jsp?pid=1924
C语言代码:
1 #include <stdio.h> 2 #include <string.h> 3 char s[1000005]; 4 5 void read(char *s){ 6 int ch; 7 scanf("%s",s); 8 ch = getchar(); 9 while(ch == ' '){ 10 int len = strlen(s); 11 s[len] = ' '; 12 scanf("%s",s+len+1); 13 ch = getchar(); 14 } 15 } 16 17 int main(){ 18 int t,i; 19 scanf("%d",&t); 20 while(t--){ 21 read(s); 22 int len = strlen(s); 23 for(i = 0; i < len; i++){ 24 if(i == 0){ 25 putchar(s[i]-32); 26 } 27 if(s[i] == ' '){ 28 putchar(s[i+1]-32); 29 } 30 } 31 puts(""); 32 } 33 return 0; 34 }
C++代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 string s; 5 6 int main(){ 7 int t; 8 cin>>t; 9 cin.get(); 10 while(t--){ 11 getline(cin,s); 12 int len = s.size(); 13 cout << char(s[0]-32); 14 for(int i = 1; i < len; i++){ 15 if(s[i] == ' ') 16 cout << char(s[i+1]-32); 17 } 18 cout << endl; 19 } 20 return 0; 21 }
2.字符串比较
我们知道可以通过一位一位的模拟进行字符串比较,但要是两个字符串都很长怎么办,我们容易得出暴力方法进行匹配的时间复杂度为O(n*m),n和m就是两个字符串的长度,通过一些算法我们可以进行匹配优化,例如我们可以利用KMP算法在O(n+m)的时间复杂度内进行匹配。
下面是KMP的算法讲解
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
java8学习:新的日期使用
内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 最开始java 1.0时代,开始使用Date时间类,相当难用,他是以1900年起始,月份是从0开始的,如果你要表示2018年11月25日,那么就要这样 Date date = new Date(118,10,25); System.out.println(date.toLocaleString()); //2018-11-25 0:00:00 之后Date大多数方法已经废弃,却而代之的是Calendar类,但是这个类的月份依旧是从0开始的,但是年份不是从1900开始的,但是解析日期的DateFormat方法只在Date中有,并且他不是线程安全的 Date和Calendar都是可变的,这将带来很多麻烦,java8中在java.time中整合了很多Joda-Time的特性,Joda-Time之前是第三方类库 使用LocalDate和LocalTime 从类名就可以看出,LocalDate是表示年月日,而LocalTime是表示时分秒 Loca...
- 下一篇
C++中string的用法
我们知道string可以构造一个字符串变量,那么它的操作有哪些呢。它包含在string库中(不是string.h没有.h),它可以和定义一个字符一样定义一个字符串变量,而且强大的C++还内置了各种函数,基本实现不用再手写操作函数。而且可以进行字典序的比较和串操作。 一、对位和对串操作 如何或者string串中的某一位字符呢,我们使用数组下面的方式就可以访问。 例如 string s = "abcdef"; cout << s[0] << endl; 结果就应该是输出了字符'a',同时string类型也可以直接加上另一个字符串,例如 string a = "abc", b = "bcd"; a = a + b; cout << a << endl; 结果应该输出字符串“abcbcd”。 二、内置函数 在string类型中其实包括了很多函数,例如 1 string s = "a"; 2 s.append(2,'b');//s.append(n,c);在s串后面加入n个c字符(append还有其他用法,详情可百度) 3 s.erase(s.be...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8编译安装MySQL8.0.19
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程