当前课程知识点:高级语言程序设计 >  字符串 >  8.1 字符串的存储及输入输出 >  字符串的存储及输入输出

返回《高级语言程序设计》慕课在线视频课程列表

字符串的存储及输入输出在线视频

字符串的存储及输入输出

下一节:系统字符串处理函数

返回《高级语言程序设计》慕课在线视频列表

字符串的存储及输入输出课程教案、知识点、字幕

大家好

本讲介绍字符串的基本概念

字符串的存储及输入输出

来看一个引例

这是我们前面编写的程序中的一个

计算全班C语言考试的平均分数

并且统计高于平均分的学生人数

我们通常都是要求计算

最高分 最低分 平均分 人数

或者根据分数排序等等这一类操作

现在我们的需求增加了

不仅要处理数值型数据

还希望能处理学生的姓名 住址等文本信息

我们就要学习在计算机里处理非数值类型数据

字符型数据和字符串型数据

数据在计算机中的表示主要有两大类

数值型数据和非数值型数据

本讲学习非数值型数据的存储和操作

先来看看什么是字符常量和字符串常量

字符常量只能是单个字符

用单引号括起来

字符串常量可以含有一个或多个字符

由双引号括起来

如"Zhangsan"

"I love China!"等

字符串常量才能表达一个语义

字符常量相当于英语中的字母

字符串常量相当于英文中的单词或句子

可以把一个字符常量赋值给一个字符变量

但不能把一个字符串常量赋给一个字符变量

在C语言中没有字符串这种类型的变量

字符常量占一个字节的内存空间

字符串常量占的内存字节数

等于字符串中字符数加1

增加的这个字节中

是用来存放ASCII码为0的空字符'\0'

这是字符串结束的标志

例如

字符常量'a'和字符串常量"a"

虽然都只有一个字符

但在内存中的情况是不同的

字符 'a'在内存中占一个字节

而字符串"a"在内存中占二个字节

其中一个字节要用来存放'\0'

如果双引号里没有任何字符

表示空串

在内存中保存的空串是空字符'\0'

占一个字节

"How are you"这个字符串

共有11个字符

包括两个空格字符

在内存里

该字符串占12个字节

字符串的末尾有'\0'这个结束标志符

C语言中没有字符串类型变量

那么字符串的存储一般有两种方法

一种字符数组

一种是使用字符指针

先来看字符数组

字符数组里存放的不一定是字符串

字符串的最后一个元素必须是'\0'

在定义数组时

用初始化列表

把各个字符依次赋给数组中各元素

数组长度为10

初始化列表里刚好有10个字符常量

存放在数组里后

是字符数组

但不代表字符串

再来看

初始化列表里只有9个字符常量

字符数组长度还是10

系统将字符存放在数组中

还在最后自动加入一个空字符

那么这个是字符数组

也代表字符串

也就是说

长度为10的数组

初始化列表中字符常量的个数最多为9

不能超过9

可以小于9

上面数组长度为10

初始化列表里

刚好有10个字符常量

存放在数组里后

系统没有地方在最后加空字符了

也就是字符串的结束标志了

我们还可以在定义数组时

用字符串常量来对字符数组初始化

这个花括号还可以省略

赋初值时

还可以省略数组长度

系统自动计算字符串的长度

并且将这个数组的大小设置为字符串长度+1

这是初始化后字符数组的状态

因为系统会在最后

加入一个空字符作为结束标记

用字符数组存放字符串时要注意

定义一个字符数组str

并且初始化

存放了一个字符串"Hello China"

如果我们想用这个数组

来存放另一个字符串“How are you!";”

这样写是不对的

字符数组只能在定义时初始化

数组名是指针常量

不能这样引用

后面我们会讲如何通过调用库函数来实现

将另一个字符串存入到这个字符数组中

这里我们要强调一下字符数组与字符串的关系

字符数组并不限定最后一个字符应该是什么

什么情况下字符数组可以看做“字符串变量”

字符串必须要有“字符串结束标志”

即空字符’\0’

因此字符数组必须含有“串尾标志”

如果字符数组没有“串尾标志”

那就只是普通数组

必须一个一个元素进行操作

用空字符作为字符串结束标志

不会产生附加的操作或增加有效字符

只起一个供辨识的标志

可以对“字符串变量”进行整体操作

C语言还可以使用字符指针来处理字符串

来看看字符指针存放的字符串

ps是指向字符的指针变量

"Hello China"是字符串常量

是存放在内存的常量区的

变量ps本身在动态存储区

这里ps存放的是

"Hello China"这个字符串的第一个字符'H'的地址

字符数组存放的字符串

这里定义一个长度为12的字符数组str

并且初始化

存放了一个字符串"Hello China"

str数组定义在动态存储区的

"Hello China"的值是存放在数组中的

也就是说"Hello China"是在动态存储区的

数组名str是动态存储区中的指针常量

用字符指针变量存放字符串时要注意

如果我们定义了一个基类型

为字符型的指针变量ps

那么这个ps可以存放一个字符串常量的首地址

还可以用ps存放另一个字符串常量的首地址

ps是字符型指针变量

可以指向不同的字符串常量

还可以指向字符数组

请看

定义并且初始化了一个字符数组str

ps可以存放字符数组str的首地址

也就是指向这个字符数组

注意使用字符串指针变量与字符数组的区别

字符串本身是存放在一块连续的内存空间中

并以‘\0’作为字符串的结束标记

字符串指针变量本身是一个变量

用于存放字符串的首地址

字符数组是由若干个数组元素组成的

它可用来存放整个字符串的所有字符

注意这三条语句都是对的

最后这条语句不对

现在来看字符串的输入输出

字符串可以按字符逐个输入输出

可以整体输入输出

先来看逐个输出

这里有一个字符串“china”

存放在长度为12的字符数组str中

字符串的长度取决于空字符的位置

而不是字符数组的长度

所以呢

我们可以用这样的一个循环语句

来实现对字符串进行逐个字符输出

直到遇到字符串结束标记为止

不能用数组长度作为循环结束条件

用这个循环语句逐个输入字符时

因为不知道要输入的字符串的长度

我们只能假定输入长度为11的字符串

显然这是不明智的

是不可行的

用循环语句对字符串逐个字符进行输入输出

是不方便的

但在字符串拷贝 连接 比较等操作中

要用循环语句对字符串逐个字符进行处理

我们后面会讲到

这里定义了一个长度为12的字符数组str

可以存放字符串

通过调用库函数来实现

按字符串整体进行输入/输出

有scanf和printf这一对函数

还有gets和puts这一对函数

这条语句scanf呢

就表示从键盘输入一个字符串

存入到str数组里面

要用s格式符

str是数组名

它代表了这个数组的首地址

这里强调一下

不需要在str的前面加一个取地址运算符了

而这条printf语句

就是将str数组中存放的字符全部输出到屏幕上

直到遇到字符串结束标志为止

再来看

gets和puts函数

这两个函数是专用的

针对字符串的输入输出函数

圆括号里是数组名

不需要格式字符

scanf函数

不能输入带空格的字符串

gets函数

可以输入带空格的字符串

这两对函数有什么区别呢

scanf函数

在遇到回车

空格或tab键时

会自动在字符串后面添加空字符

但是回车

空格或tab键仍会留在输入的缓冲区中

可能会影响后面数据的输入

gets函数

可接受回车键之前输入的所有字符

并用‘\0’替代 ‘\n’

回车键不会留在输入缓冲区中

printf函数和puts函数区别不大

puts函数输出完字符串后会自动换行

而printf函数不会

现在来看一个实例演示字符数组

存储字符串及输入输出

定义了两个字符数组

首先用sacnf函数输入一个字符串

用printf函数输出读入的字符串

再用gets函数读入一个字符串

用puts函数输出读入的字符串

如果我们希望输入一个学生的姓名张三

保存在str1里

输出

在输入另一个学生的姓名李四

保存在str2里

输出

运行

结果和我们希望的不同

我们来看看原因

将光标放在gets函数前

单击右键

选择运行到光标处

输入zhang san

在监视窗口输入str1 str2

观察str1数组的情况

再看str2数组

执行gets函数之前是随机值

执行之后是空格

san

是前面sacnf语句执行后

残留在输入缓冲区的字符

被gets函数读入到str2中

怎么解决这个问题呢

可在gets函数读入字符串之前

用系统函数fflush( )清空输入缓冲区

在这里加一条语句fflush(stdin)

再次运行到光标处

再次可以输入李四

运行结果达到我们的期望

大家还可以自己试试

将gets函数放在scanf函数之前

还有没有这个问题

再来看例2

演示字符指针存储字符串及输入输出

str和ps存储的字符串的值都是 "Hello China"

但这两个字符串存放的内存区域是不同的

数组str中的字符串地址是00B3F9F0

在内存的动态存储区

ps中存储的字符串

在常量区

字符串第1个字符’H’的地址是 00D75810

数组str中字符是可以修改的

ps指向的字符串的字符是不能被修改的

ps还可以指向另一个字符串常量

ps也可以指向一个字符数组

好啦

这就是我们这一节的内容

谢谢大家

高级语言程序设计课程列表:

程序设计和C语言

-1.1 计算机程序和计算机语言

--计算机程序和计算机语言

--致敬先辈:伟大的C语言之父——丹尼斯·里奇 程序员

-1.2 C程序的构成

--C程序的构成

--当前主流程序设计语言各自都有什么优势?

-1.3 C语言编辑、编译、运行(VC++2010学习版)

--C语言编辑、编译、运行(VC++2010学习版)

-练习题

顺序结构程序设计

-2.1 变量的定义和使用

--变量的定义和使用

-2.2 数据类型

--数据类型简介

--整型数据

--实型数据

-2.3 格式输出和格式输入

--格式输出printf函数

--格式输入scanf函数

--单个字符的输入输出

-2.4 运算符和表达式

--运算符和表达式

-2.5 结构化程序设计入门

--结构化程序设计入门

-练习题

选择结构程序设计

-3.1 为什么要用选择结构解决问题

--为什么要用选择结构解决问题

-3.2 如何正确表示选择结构中的条件

--如何正确表示选择结构中的条件

-3.3 用if语句及if语句嵌套实现选择结构

--用if语句及if语句嵌套实现选择结构

-3.4 用switch语句实现选择结构

--用switch语句实现选择结构

-练习

循环结构程序设计

-4.1 循环的引入

-- 为什么要用循环结构解决问题

-4.1 循环的引入--作业

-4.2 用while语句实现循环

--用while语句实现循环

-4.3 用do-while语句实现循环

-- 用do-while语句实现循环

-4.4 用for语句实现循环

-- 用for语句实现循环

-4.4 用for语句实现循环--作业

-4.5 何时需要用循环的嵌套

--何时需要用循环的嵌套

-4.6 如何提前终止循环和提前结束本次循环

--如何提前终止循环和提前结束本次循环

-习题--作业

数组

-5.1 数组类型的引入

--数组类型的引入

-5.2 一维数组的定义和初始化

--一维数组的定义和初始化

-5.3 一维数组的使用

--一维数组的使用

-5.4 二维数组的定义和初始化

--二维数组的定义和初始化

-5.5 二维数组的使用

--二维数组的使用

-习题--作业

指针

-6.1 什么是指针

--什么是指针

-6.2 指针类型及相关概念

--指针类型及相关概念

-6.3 指针变量的定义、赋值与使用

--指针变量的定义、赋值与使用

-6.4 指针的运算

--指针的运算

-6.5 指针与一维数组

--指针与一维数组

-6.6 指针的指针

--指针的指针

-6.7 指针与二维数组

--指针与二维数组

-习题--作业

函数

-7.1 为什么要自定义函数

--为什么要自定义函数

-7.2 函数的定义

--函数的定义

-7.3 函数的调用

--函数的调用

-7.4 函数参数的传递

--函数参数的传递

-7.5 函数的嵌套调用和递归调用

--函数的嵌套调用和递归调用

-7.6 变量的作用域和存储类型

--变量的作用域和存储类型

-习题--作业

字符串

-8.1 字符串的存储及输入输出

--字符串的存储及输入输出

-8.2 系统字符串处理函数

--系统字符串处理函数

-8.3 自定义字符串处理函数

--自定义字符串处理函数

-习题--作业

结构体和共用体

-9.1 结构体类型的定义

--结构体类型的定义

-9.2 结构体变量及指针变量的定义及使用

--结构体类型变量和指针变量的定义和使用

-9.3 结构体变量和指针变量作函数的参数

--用结构体变量和指向结构体的指针作函数参数

-9.4 结构体数组的定义和使用

--结构体数组的定义和使用

-9.5 共用体类型和枚举类型

--共用体和枚举类型

-习题--作业

动态内存分配

-动态内存分配--习题

文件

-习题--作业

字符串的存储及输入输出笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。