title: 第四章 字符串和格式化输入/输出
author: HardyDragon
tags: C Notes
第四章 字符串和格式化输入/输出
4.1 前导程序
4.2 字符串简介
4.2.1 char类型数组和null字符
4.2.2 使用字符串
4.2.3 strlen()函数
4.3 常量和C预处理器
4.3.1 const限定符
4.3.2 明示常量
4.4 printf()和scanf()
4.4.1 printf() 函数
4.4.2 使用printf()
4.4.3 printf() 的转换说明修饰符
4.4.4 转换说明修饰符
4.4.5 使用scanf()
4.4.6 printf()和scanf()的*修饰符
4.4.7 printf()的用法提示
4.5 关键概念
4.6 本章小结
4.7 复习题
4.8 编程练习
4.1 前导程序
/* talkback.c -- 演示和用户交互*/
#include <stdio.h>
#include <string.h>
#define DENSITY 62.4
int main(int argc, char const *argv[])
{
/* code */
float weight, volume;
int size, letters;
char name[40];
printf("HI,what's your first name?\n");
scanf("%s", name);
printf("%s,what's your weight in pounds?\n", 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);
getchar();
getchar();
return 0;
}
result
HI,what's your first name?
Chen
Chen,what's your weight in pounds?
130
Well, Chen ,your volume is 2.08 cubic feet.
Also,your first name has 4 letters,
and we have 40 bytes to store it.
- 使用数组存储字符串,用户输入的名被存储在字符数组中,这个数组占用内存中连续的40个字节,每个字节存储一个字符值。
- 使用%s转换说明来处理字符串的输入和输出。注意,在scanf()中,name没有&前缀,而weight有(&weight和name都是地址)
- strlen()获取字符串长度
4.2 字符串简介
字符串是一个或多个字符的序列,双引号不是字符串的一部分,双引号只是告诉编译器它括起来的是字符串。
-
char类型数组和null字符
C语言没有专门存储字符串的变量类型,字符串都被存储在char类型的数组中。数组由连续的存储单元组成,字符串中的字符被存储在相邻的存储单元中,每个单元存储一个字符。
数组末尾的字符 ‘\0’ ,这是空字符,C语言用它来标记字符串的结束。空字符不是数字0,它是非打印字符,但是它的ASCII码为0。C中的字符串一定要以空字符结束,意味着数组的容量如要正常使用就需要比待存储的字符数多1,所以 程序中的 name[40] 数组只能存储39个字符,剩下一个字节留给空字符。
再次明确一下数组的概念,数组可以看做一行连续的多个存储单元,数组是同类型数据元素的有序序列。以下声明创建一个包含40个存储单元的数组,每个单元存储一个char类型的值。
char name[40];
name后面的方括号【】表明这是一个数组,方括号中的40表明该数组中的元素数量。char 表示每个元素的类型。记得在字符串的末尾加上一个 ‘\0’ 。
-
使用字符串
// praise1.c -- 使用不同类型的字符串 #include <stdio.h> #define PRAISE "You are an extraodinary being" int main(int argc, char const *argv[]) { char name[40]; printf("What's your name?"); scanf("%s", name); printf("Hello,%s.%s\n", name, PRAISE); getchar(); getchar(); return 0; }
result:
What's your name?Hardy Hello,Hardy.You are an extraodinary being ------------------------------------------ What's your name?Hardy Dragon Hello,Hardy.You are an extraodinary being
%s告诉printf() 打印一个字符串。一个字符串存储在name数组中,另一个有 PRAISE 表示。
我们可以不用把空字符放入字符串末尾,因为scanf() 在读取输入时就已经完成了这项工作。同样也不用在字符串常量 PRAISE 末尾添加空字符,编译器会自动帮忙在末尾加上空字符。
注意:scanf()函数只是读取了 Hardy Dragon 中的Hardy,它在遇到第一个空白(空格、制表符或换行符)时就不再读取键盘的输入了。根据%s的转换说明,scanf() 只会读取字符串的一个单词,而不是一整句。C语言当然还有其他的输入函数用于处理各种输入情况例如 fgets() 用于读取一般字符串。
字符串和字符:
字符串常量"x" 和 ‘字符常量 x’ 的不同在于字符常量 ‘x’ 是基本类型,而字符串常量"x" 是派生类型;其实字符串常量"x" 是由两个字符常量组成的,‘x’ 和 ‘\0’
-
strlen() 函数
之前用到了 sizeof 运算符,它以字节为单位给出对象大小。strlen() 函数给出字符串中的字符长度。因为1字节存储一个字符,所以sizeof() 和strlen() 对于字符串的效果是一样的么?
// praise2.c #include<stdio.h> #include<string.h> #define PRAISE "You are an extraodinary being" int main(int argc, char const *argv[]) { char name[40]; printf("What's your name?"); scanf("%s", name); printf("Hello,%s.%s\n", name, PRAISE); printf("Your name of %zd letters occupies %zd memory cells.\n", strlen(name),sizeof name)