我们经常需要使用计算机处理大量的字符,因而C/C++引入字符串(string)以支持对大量字符操作。
其中,C++语言提供了C风格字符串和C++风格字符串(STL)两种选择:C风格的字符串操作与C语言完全一致,而C++风格的字符串则以面向对象的范式支持了更多操作。
字符串常量
C/C++中的字符串常量就是以英文双引号括起来的一段字符:
1 | "hello,world" |
像scanf,printf函数,传的参数也就是字符串常量。
C风格的字符串
在C语言中,字符串就是一种特殊的字符型数组,唯一与普通字符型数组不同的是,字符串以一个特殊字符’\0’(ASCII码也为0)结尾。
1 | char a[100]={'a','b','c'};//这是一个字符型数组 |
由于数组初始化时会将未赋值的空间赋为0,因此字符数组a也可以看做一个字符串,而b[3]==’\0’就是一个字符串。但为了区分,我们有必要在字符串结尾加一个’\0’做标志。
C风格输入输出
引入字符串概念后,就可以对字符进行整体的输入输出操作了。
1 | char s[100]; |
输入:
abc
输出:
abc
使用scanf将字符串”abc”整体读入字符串s,并使用printf进行整体的输出。
这里有个重要的细节:用scanf输入变量时,需要使用取地址运算符&进行操作,而输入字符串时则不加,这一差异需要用心记忆。(原因则较为复杂不必深究,与数组类型的本质有关。数组名实际上是指向首元素的一个特殊指针,因而字符串传入时相当于直接传入了地址。)
C风格字符串的操作
另外,C语言还提供了更多现成的字符串操作(即定义了许多现成的字符串函数),都在头文件string.h中;如果使用C++,头文件则是cstring,里面的内容是完全一样的。这里只是简单介绍常用的一些操作,更多操作如有需要可以自行查询。
gets、puts
与scanf,printf类似,是字符串的输入输出函数。只是scanf读取字符串和其他数据一样,遇到空白符号即停止(空格、回车),而gets允许读取代空格的字符串:
1 |
|
输入:
abc def
输出:
abc
1 |
|
输入:
abc def
输出:
abc def
strcpy
和数组一样,C风格的字符串不允许直接赋值为一个字符串常量:
1 | char s[10]; |
要赋值一个字符串,需要使用函数strcpy(string copy):
1 | char s1[10]; |
输出:
hello
hello
strcmp
用于比较两个字符串的大小(也就是字典序,就是英文字典中单词的排序方式)。
strcmp(s1,s2):如果s1>s2返回正整数,s1=s2返回0,s1<s2返回负整数:
1 | char s1[20],s2[20]; |
输出:
application
strlen
返回一个字符串的长度(字符数,’\0’不计在内):
1 | printf("%d\n",strlen("apple")); |
输出:
5
4
字符串的一般操作
和数组一样,我们也可以使用下标访问、操作字符串的每一个字符:
1 | char s[20]; |
输入:
abcde
输出:
bcdef
我们发现,字符串中的每一个字符,都通过访问下标的方式加一,最后整体输出。
其它字符串函数
以上列出的是最常用的一些字符串函数,而string.h(C++中cstring)还提供更多字符串函数供使用。这里不作要求,只是简单列出,如在编写过程中有需要可以自行查询。
- strcat(s1,s2):将参数s2字符串拷贝到参数s1字符串尾
- strlwr(s):将字符串中的大写字母转化为小写
- strupr(s):将字符串中的小写字母转化为大写
- strchr(s,c):在一个串中查找给定字符的第一个匹配之处
- strrev(s):将一个字符串反向
C++风格的字符串
C++除了支持使用C风格字符串和所有的C字符串函数外,还提供另一种“C++风格的字符串”。(与C风格的最大区别是,C++字符串是建立在面向对象的基础上的一个字符串类,属于C++的标准模板库(STL),除了提供更多操作和封装带来更好的稳定性外,字符串作为一个类型还可以与STL中的其他容器协同工作)
string类型
在学习面向对象编程的概念之前,我们只需知道,C++风格的字符串是C++内置的一种类型:string类型。
要使用string类型,我们首先要使用头文件string(不是C语言的string.h,也不是C++的cstring)
1 |
|
这样,就简单完成了两个字符串s1,s2的定义,并给字符串s2赋了初值”hello”。我们发现:string类型是可以用字符串常量赋值的。
string操作
和C++的其他类型一样,string也可以使用cin/cout进行简单的输入输出:
1 | string s1; |
输入:
1234
输出:
1234
string之间、string和字符串常量可以进行赋值:
1 | string s1,s2="hello"; |
输出:
hello
abc
string类型提供一些简单的运算,简化了字符串处理的流程:
1 | 运算符有: |
如:
1 | string s1="aaa",s2="bbb"; |
输出:
aaabbb
bbbaaa
与C风格一样,string类型也可以通过下标访问每一个字符,下标从0开始:
1 | string s="abcde"; |
输出:
bcdef
string还能以一个C风格字符串为初值,还可以转换成一个C风格字符串(这里的语法还没有涉及,不作要求,如有需要须强行记忆,可了解面向对象编程的构造函数、成员函数等知识)
1 | char s1[10]={'a','b','c'}; |
输出:
abc
hello
这样,我们可以通过两种字符串操作的转化实现按需求灵活使用。
string类型的成员函数
成员函数这个概念在学习面向对象编程之前还有再放一放,我们只需知道,string类型和C风格一样使用函数支持很多的字符串操作,只是并不是使用C语言中(也就是我们之前学过)的那种函数。
比如,类似于strlen函数,string类型则有:
1 | string s1="apple"; |
输出:
5
成员函数的调用方式如上。
由于string类型的面向对象特性已超出本教程的范围,更多的string类型成员函数有余力可自行查询。
作业
思考
1、什么是字符串,字符串和字符型数组有什么共同点?有什么区别?
2、C风格的字符串和C++风格的字符串有什么区别?
3、区分头文件string.h、cstring、string
习题
1、密码
2、表达式括号匹配
*3、实现一个能计算一位正整数+、-运算表达式的计算器
例:
输入:
1+3+2-5-7
输出:
-6
**4、实现一个能计算一位正整数+、-、*、/运算表达式的计算器
例:
输入:
1+3*5-4
输出:
12
***5、实现一个能计算正整数+、-、*、/运算表达式的计算器
例:
输入:
12+3*5-45
输出:
-18