4. 字符串和格式化输入输出
一、字符串简介
1.1引言
-
C语言没有专门用于储存字符串的变量类型,字符串都被储存在char类型的数组中。
-
数组由连续的存储单位组成,字符串中的字符被储存在相邻的存储单元中,每个单元储存一个字符。
-
空字符\0在字符串末尾,C语言用它标记字符串的结束,是非打印字符,ASCII码值为0。
-
C语言中的字符串一定以空字符结尾,所以数组的容量必须至少比待存储字符串中的字符数少1。
如,声明一个20个存储单位的字符串,它只能存储19个字符,剩下一个字节留给空字符。
-
编译器会在字符串末尾加上空字符。
1.2 字符串与字符
- 字符串用 " " 括起来,字符用 ' ' 括起来。
- 字符是基本类型(char),字符串是派生类型(char 数组)。
- 字符串由字符和空字符\0复合组成。
- sizeof 的括号:运算对象是类型时,必不可少;是特定量时,可有可无。但建议所有情况下都使用圆括号。
1.3 strlen( ) 函数
-
strlen( ) 函数,给出字符串中的字符长度。sizeof 运算符,它以字节为单位给出对象的大小。
-
strlen( ) 计算字符串中的字符长度,包括空格和标点符号,但不把空字符算入。
sizeof 运算符把字符串末尾不可见的空字符也计算在内。
-
string.h头文件中包含strlen( ) 函数和其他多个与字符串相关的函数原型
-
strlen( ) 函数占位符用%zd,如果编译器不识别%zd,就用%u或%lu
1.4 const限定符:
-
const关键字用于限定一个变量为只读,也就是只能使用,不能修改。
-
在程序中,最好用#define 定义数值常量,用 const 关键字声明的变量为读变量。
-
在程序中使用符号常量(明示常量),提高了程序的可读性和可维护性。
二、printf( ) 函数
2.1 转换说明及打印结果
-
请求 printf( ) 函数打印数据的指令要与待打印数据的类型相匹配。
-
转换说明:指定如何把数据转换成可显示的形式的符号。
2.2 使用printf( ) 函数
- 格式:printf( 格式字符串, 待打印1, 待打印2, ....)
- 格式字符串: 是用双引号括起来的内容,包含每个待打印项对应的转换说明。
- 待打印项:要打印的项,可以是变量、常量、计算表达式 。
- 注意:格式字符串中的转换说明一定要与后面的每个项都匹配

2.3 printf( ) 的转换说明修饰符
在%和转换字符之间插入修饰符可修饰基本的转换说明。表4.4和表4.5 列出可作为修饰符的合法字符。如果要插入多个字符,其书写顺序应该与表 4.4中列出的顺序相同。不是所有的组合都可行。

2.3.1类型可移植性
sizeof 运算符 以字节为单位返回类型或值的大小,标准只规定了该值是无符号整数。在不同的实现中,它有不同的转换说明和类型,这意味着要查找你当前系统的用法,如果把程序移植到不同的系统还要进行修改。
鉴于此, C 提供了可移植性更好的类型。首先,stddef.h 头文件(在包含 200 表4.4 printf( ) 的修饰stdio.h 头文件时已包含其中)把 size_t 定义成系统使用 sizeof 返回的类型,这被称为 底层类型(underlying type)。其次,printf( ) 使用z修饰符表示打印相应的类型。同样,C 还定义了 ptrdiff_t 类型和t修饰符来表示系统使用的两个 地址差值的底层有符号整数类型。
2.3.2 float 参数的转换
对于浮点类型,有用于double 和 long double 类型的转换说明,却没有 float 类型值专用的转换说明。这是因为为保护大量假设float类型的参数被自动转换 double 的现有程序, printf( ) 函数中所有 float 类型的参数仍自动转换成 double 类型(对未使用显式原型的所有 C 函数都有效)。

2.3.3 使用修饰符和标记的示例
#include<stdio.h> // width.c -- 字段宽度
#define PAGES 959
int main(void)
{
printf("*%d*\n", PAGES); //输出结果为*959*
printf("*%2d*\n", PAGES); //输出结果为*959*
//其对应的输出结果应该是2字段宽度。因为待打印的整数有 3 位数字,所以字段宽度自动扩大以符合整数的长度。
printf("*%10d*\n", PAGES); //输出结果为* 959*
//对应的输出结果有10个空格宽度,即在两个星号之间有7个空格和3位数字,并且数字位于字段的右侧。
printf("*%-10d*\n", PAGES);//输出结果为*959 *
//对应的输出结果有10个空格宽度,-标记说明打印的数字位于字段的左侧
return 0;
}
#include <stdio.h> // floats.c -- 一些浮点型修饰符的组合
int main(void)
{
const double RENT = 3852.99;// const变量,限定变量为只读
printf("*%f*\n", RENT);//结果为 *3852.990000*,默认设置小数点 后打印6位数字
printf("*%e*\n", RENT); //结果为 *3.852990e+03*,默认设置小数点 后打印6位数字
printf("*%4.2f*\n", RENT);//结果为 *3852.99*
printf("*%3.1f*\n", RENT);//结果为 *3853.0*
printf("*%10.3f*\n", RENT); //结果为 * 3852.990*
printf("*%10.3E*\n", RENT); //结果为 * 3.853E+03*,类e
printf("*%+4.2f*\n", RENT); //结果为 *+3852.99*
printf("*%010.2f*\n", RENT); //结果为 *0003852.99*,第一个0为0标记,10.2是字符宽度
return 0;
}
#include <stdio.h> // flags.c -- 演示一些格式标记
int main(void)
{
printf("%x %X %#x\n", 31, 31, 31);//1f 1F 0x1f
printf("**%d**% d**% d**\n", 42, 42, -42); //**42** 42**-42**
printf("**%5d**%5.3d**%05d**%05.3d**\n", 6, 6, 6, 6);//** 6** 006**00006** 006**
return 0;
}
/* stringf.c -- 字符串格式 */
#include <stdio.h>
#define BLURB "Authentic imitation!"
int main(void)
{
printf("[%2s]\n", BLURB); //结果为 [Authentic imitation!]
printf("[%24s]\n", BLURB); //结果为 [ Authentic imitation!]
printf("[%24.5s]\n", BLURB); //结果为 [ Authe],精度限制了待打印字符个数
printf("[%-24.5s]\n", BLURB); //结果为 [Authe ],-标记使文本左对齐输出。
return 0;
}
2.4 转换说明的意义
- 转换说明是翻译作用,把二进制格式存储在计算机中的值转换成一系列字符(字符串)以便于显示。
2.4.1 参数传递

2.4.2 printf( ) 的返回值
- 大部分 C 函数都有一个返回值,这是函数计算并返回给主调程序(calling program)的值。例如,C库包含一个 sqrt( ) 函数,接受一 个数作为参数,并返回该数的平方根。可以把返回值赋给变量,也可以用于计算,还可以作为参数传递。总之,可以把返回值像其他值一样使用。
- printf( ) 函数也有一个返回值,它返回打印字符的个数。如果有输出错误, printf( ) 则返回一个负值。
- printf( ) 的返回值是其打印输出功能的附带用途,通常很少用到,但在检 查输出错误时可能会用到(如,在写入文件时很常用)。
2.4.3 打印较长的字符串
-
有时,printf( ) 语句太长,在屏幕上不方便阅读。如果空白(空格、制表 符、换行符)仅用于分隔不同的部分,C 编译器会忽略它们。因此,一条语句可以写成多行,只需在不同部分之间输入空白即可。但是,不能在双引号括起来的字符串中间断行。
-
在字符串中,可以使用\n 来表示换行字符,但是不能通过按下 Enter(或Return)键产生实际的换行符。
-
给字符串断行有3种方法:
方法1,使用多个 printf( ) 语句。
方法2:用反斜杠(\)和 Enter(或 Return)键组合来断行。
方法3:ANSI C 引入的字符串连接。#include <stdio.h> //打印较长的字符串三种方法示例 int main(void) { printf("Here's one way to print a "); printf("long string.\n"); printf("Here's another way to print a \ long string.\n"); printf("Here's the newest way to print a " "long string.\n"); /* ANSI C */ return 0; } /*该程序的输出如下: Here's one way to print a long string. Here's another way to print a long string. Here's the newest way to print a long string.*/
三、scanf( ) 函数
3.1 scanf( ) 与 printf( ) 函数
- printf( ) 和 scanf( ) 函数能让用户可以与程序交流,它们是输入/输出函数,或简称为I/O函数。
- scanf( ) 把输入的字符串转换成整数、浮点数、字符或字符串;而 printf( ) 正好与它相反,把整数、浮点数、字符和字符串转换成显示在屏幕上的文本。
- printf( ) 函数使用变量、常量和表达式,而scanf( ) 函数使用指向变量的指针。
3.2 scanf( ) 函数
-
scanf( ) 中的格式字符串表明字符输入流的目标数据类型。
-
scanf( ) 函数使用指针规则:如果用scanf( ) 读取基本变量类型的值,在变量名前加上一个&; 如果用scanf( ) 把字符串读入字符数组中,不用&。
3.3 从scanf( ) 的角度看输入
-
除了%c,,scanf( ) 函数读取字符,会跳过所有的空白字符,直到遇到第1个非空白字符才开始读取。
但根据%c,scanf( ) 会读取每个字符,包括空白。
-
scanf( ) 函数如果找到一个数字或符号(+ 或 -),它便保存该字符,并读取下一个字符。
-
scanf( ) 会不断地读取和保存字符,直到遇到非数字字符,并且scanf( ) 会认为读到了整数的末尾。
-
scanf( ) 就把非数字字符放回输入,程序在下一次读取输入的时候,首先会读取丢弃的非数字字符。
-
scanf( ) 计算已读取数字(可能还有符号)相应的数值,并将计算后的值放入指定的变量中。
-
如果使用字段宽度,scanf( ) 会在字段结尾或第一个空白字符处停止读取。使用%s 转换说明,scanf( ) 会读取除空白以外的所有字符。无法利用字段宽度让只有一个%s的scanf( ) 读取多个单词。
-
如果使用带多个转换说明的scanf( ),C规定在第一个出错出停止读取输入。
-
当scanf( ) 把字符串放进指定数组中时,它会在字符序列的末尾加上'\0',让数组中的内容成为一个C字符串。
-
scanf( ) 函数允许把普通字符放在格式字符串中。除空格字符外的普通字符必须与输入字符串严格匹配。
-
scanf( ) 函数的转换说明与printf( ) 函数几乎相同。主要区别是对于float 类型和double 类型,printf( ) 都使用%f,%e,%E,%g和%G转换说明,而scanf( ) 只把它们用于float 类型,对于double 类型要使用l修饰符。

3.4 scanf( ) 的返回值:
-
scanf( ) 函数返回成功读取的项数。如果没有读取任何项,且需要读取一个数字而用户却输入一个非数值字符串,scanf( ) 便返回0。
-
当scanf( )检测到“文件结尾”时,会返回EOF。
-
EOF 是stdio.h 中定义的特殊值,通常用#define 指令把EOF 定义为-1。
-
scanf( ) 的修饰符:把放在%和转换字符之间时,会使得scanf( ) 跳过相应的输出项。

浙公网安备 33010602011771号