第四章 字符串和格式化输入/输出
4.1前导程序
- #include<stdio.h>
- #include<string.h>
- #define DENSITY 62.4
- int main()
- {
- float weight,volume;
- int size,letters;
- char name[40];
- scanf("%s",name);
- scanf("%f",&weight);
- size=sizeof name;
- letters=strlen(name);
- volume=weight/DENSITY;
- printf("Well,%s,your volume is %2.2f cubic feet.\n",name,volume);
- printf("Also,your first name has %d letters.\n",letters);
- printf("and we have %d bytes to store it.\n",size);
- return 0;
- }
4.2字符串简介
字符串就是一个或多个字符的序列,例如“Zing went”,但双引号不是字符串的一部分。
4.2.1char数组类型和空字符
C没有为字符串定义专门的变量类型,而是把它存储在char数组中,字符串中字符存在在相邻的存储单元中,每个字符占用一个单元,数组由相邻存储单元组成。
数组的最后一个位置显示字符\0,即空字符,C用它来标识记字符的结束。该字符的存在意味着数组的单元数至少比要存储的字符数多1。
数组:同一类型的数据元素的有序序列。
4.2.2使用字符串
%s告诉printf要打印一个字符串。您无需亲自把空字符插入name数组中,scanf()会在读取输入时完成。
scanf()开始读取输入以后,会在遇到的第一个空白字符空格、制表符或者换行符处停止读取。
‘x’和“x”不同,前者是基本类型,后者是派生类型。
4.2.3strlen()函数
sizeof以字节为单位给出数据大小,strlen()函数以字符为单位给出字符串的长度,不包括空字符。
char name[40],则sizeof name==40。char name[]="Mo" sizeof name==3;
使用sizeof后面如果接类型则必须使用圆括号,如sizeof(char),对于具体量则可选。
4.3常量和C预处理器
#define NAME value 编译时将会用value代替NAME,这称为编译时代入法。没有使用分号是因为这是一种替代机制,而不是C的语句。
4.3.1const修饰符
C90:使用const关键字把一个变量声明转换成常量声明。例const int MONTHS=12;
4.3.2系统定义的明显常量
C头文件limits.h和float.h分别提供有关整数类型和浮点类型的大小限制的详细信息。例如INT_MAX,INT_MIN等。
4.4研究和利用printf()
4.4.1printf()函数
请求printf()打印变量的指令取决于变量的类型。使用%c%d这些转换说明,它们指定了如何把数据转换成可显示的形式。
%%:打印一个百分号。%g根据数值不同自动选择%f或%e。
printf()使用的是值,无论该值是变量、常量还是表达式。
4.4.2printf()的转换说明修饰符
-:左对齐
+:有符号的值若为正,则显示带加号的符号,若为负,则带减号的符号。
空格:有符号的值为正,则显示时带前导空格;若为负,则带减号符号。
#:使用转换说明的可选形式,对于所有的浮点形式,保证了即使不跟任何数字,也打印一个小数点字符。
0:对于所有的数字格式,用前导零而不是空格填充字段宽度。
示例
- #include<stdio.h>
- int main(void)
- {
- printf("%x %X %#x\n",31,31,31);
- printf("**%d**% d**% d**\n",42,42,-42);
- printf("**%5d**%5.3d**%05d**%05.3d**\n",6,6,6,6); //如果0标志和精度符同时出现,那么0标志就会被忽略。
- printf("/%24.5s/\n","Authentic imitation! ")
- return 0;
- }
输出如下
1发1F 0x1f
**42** 42**-42**
** 6** 006**00006** 006*
/ Authe/
4.4.3printf()的返回值
它返回所打印的字符的数目,但不包括空字符。如果有输出错误,那么printf()会返回一个负数。
4.4.4打印较长的字符串
如果在一个用双引号引起来的字符串后面跟有另一个用双引号引起来的字符串,而且两者之间仅用空白字符分隔,那么C会把该组合当作一个字符串来处理。
例: “young” "lovers"变成“younglovers”。
4.5研究和利用scanf()
如果使用scanf()来读取前面讨论过的某种基本变量类型的值,请在变量名之前加上一个&。
如果使用scanf()把一个字符串读进一个字符数组中,请不要使用&。
printf()把%f、%e、%E、%g、%G同时用于float类型和double类型,而scanf()只把他们用于float类型,而用于double类型时要使用l修饰符。
4.5.1scanf()的格式字符
如果使用字段宽度,scanf()在字段的结尾或者第一个空白字符处停止。不能通过字段宽度使得scanf()用一个%s说明符读取多于一个字的输入。
scanf("%c",&ch)读取在输入中遇到的第一个字符,而scanf(" %c",&ch)读取遇到的第一个非空白字符。
4.5.2scanf()的返回值
scanf()函数返回成功读入的项目的个数,如果它没有读取任何项目,返回0,当它检测到文件结尾,返回EOF。
4.6printf()和scanf()的*修饰符
printf()中,如果您不想事先指定字段宽度,而是希望由程序来指定该值,那么您可以在字段宽度部分使用*代替数字来达到目的,但是你也必须使用一个参数来告诉函数字段宽度应该是什么。
例如printf("Weight = %*.*f\n",width,precision,weight);
scanf()中,当把*放在%和说明字母之间时,它使函数跳过相应的输入项目。
例如scanf("%*d %*d %d",&n); //跳过两个整数,并把第三个整数复制给n。