.前导程序:
/*
2020年5月27日11:15:32
目的:了解字符串的格式化输入输出
*/
#include <stdio.h>
#include <string.h> //提供strlen()函数
#define DENSITY 62.4 //人体密度
int main()
{
float weight, volum;
int size, letters;
char name[40]; // name 是一个可以容纳40个字符的数组
printf("海,你的姓名是\n");
scanf("%s", name);
printf("%s,你有多重呢?\n", name);
scanf("%f", &weight);
letters = strlen(name); //计算字符数。
printf("你的名字有%d个字", letters);
return 0;
}
字符串简介:
-
一个或多个字符的序列。 如: “好好学习,加油” ------- 注:双引号告知编译器这是字符串
-
C语言没有专门用于存储字符串的变量类型,
字符串都被存储在char类型的数组中。
char 类型数组和null字符
C语言使用— \0
----来标记字符串的结束。不是表示数字 0 这是非打印字符,其ASCII 的值为 0。
- 注:数组的容量至少比待存字符串中字符数多 1 ,用来存放
\0
如何使用字符串:
/*
2020年5月27日11:33:36
目的:使用字符串。
*/
#include <stdio.h>
#define PRAISE "You are an extraordinary being"
int main()
{
char name[40]; //定义一个字符数组
printf("What's your name? \n");
scanf("%s", name); //从键盘指定输入字符串,scanf()函数会自动将 \0 读入末尾。
printf("Hello, %s.%s\n", name, PRAISE);
return 0;
}
字符串和字符:
strlen()函数:
- sizeof 运算符,它是以字节为单位给出对象大小。strlen()函数给出字符串字符串中的字符长度。
- 程序实例:
/*
2020年5月27日11:52:37
目的:在计算字符串长度中-----测试sizeof 运算符 与 strlen()函数 的差别。
*/
#include <stdio.h>
#include <string.h>
#define PRAISE "You are an extraordinary being."
int main()
{
char name[40];
printf("What's your name? \n");
scanf("%s", name);
printf("Hello, %s.%s\n", name, PRAISE);
printf("sizeof_name = %zd, strlen_name = %zd\n", sizeof name, strlen(name));
printf("sizeof_PRAISE = %zd, strlen_PRAISE = %zd\n", sizeof PRAISE, strlen(PRAISE));
return 0;
}
总结:
- sizeof 计算name 数组时,是计算name数组占用的内存的字节数,而 strlen是计算数组中的字符数
- 对于上述字符串 PRAISE 来说:strlen 得出的也是字符串的
字符数(包括空格与标点
)。不包括\0
- 然而 sizeof 运算符给出的数更大,因为
它把字符串末尾不可见 的空字符也计算在内。
注意:对于类型,应写 成sizeof(char)或sizeof(float)
;对于特定量,可写成sizeof name或sizeof 6.28
。建议所有情况下都使用圆括号,如sizeof(6.28)。
常量和C预处理器
如何创建一个符号常量:
例:
#define TAXRATE 0.015
- 编译程序时,程序中所有的TAXRATE都会被替换成0.015。这一过程被 称为编译时替换(compile-time substitution)。
- 定义的常量也称为
明示常量
(manifest constant)
格式:#define NAME value
- 符号常量名和合适的值来替换NAME和value。
末尾不用加分号
。- 符号常量的命名规则与变量相同。可以使用大小写字母、数字和下划线 字符,首字符不能为数字。
- #define指令还可定义字符和字符串常量。前者使用单引号,后者使用双 引号。
程序示例:
/*
2020年5月27日13:05:52
目的: 测试 define 定义符号常量
*/
#include <stdio.h>
#define PI 3.14159
int main()
{
float area, circum, radius;
printf("What is the radius of your pizza?\n");
scanf("%f", &radius);
area = PI * radius * radius;
circum = 2.0 * PI * radius;
printf("area = %1.2f--------------circum = %1.2f\n", area, circum); //%1.2f表明,结果被四舍五入为两位小数输出。
return 0;
}
const 限定符:
C90标准新增了const关键字,用于限定一个变量为只读。
- 声明如下:
- const int MONTHS = 12; // MONTHS在程序中不可更改,值为12
4.3.2 明示常量:
C头文件limits.h和float.h
分别提供了与整数类型和浮点类型大小限制相 关的详细信息
。每个头文件都定义了一系列供实现使用的明示常量。
- ----------------------
limits.h
中的一些明示常量
- ----------------------
float.h
中的一些明示常量`中的一些明示常量
程序示例:
/*
2020年5月27日13:27:30
目的:测试 整数类型与浮点数类型大小相关限制相关信息
*/
#include <stdio.h>
#include <limits.h>
#include <float.h>
int main()
{
printf("整数类型与浮点数类型大小相关限制相关信息\n");
printf("Biggest int = %d\n", INT_MAX);
printf("Smallest long long = %lld\n", LLONG_MIN);
printf("One byte = %d\n",CHAR_BIT);
printf("Largest double: %e\n", DBL_MAX);
printf("Smallest normal float = %e\n", FLT_MIN);
printf("float precision = %d\n", FLT_DIG);
printf("float epsilon = %e\n", FLT_EPSILON);
return 0;
}
printf()和scanf() 函数:
printf()函数:
请求printf()函数打印数据的指令要与待打印数据的类型相匹配
。
- 例如, 打印整数时使用%d,打印字符时使用%c。这些符号被称为
转换说明
------------------------------- 转换说明及其打印的输出结果
程序示例:
/*
2020年5月27日13:39:44
目的:测试printf 转换说明
*/
#include <stdio.h>
#define PI 3.141593
int main()
{
int number = 7;
float pies = 12.75;
int cost = 7800;
printf("number = %d-----pies = %f\n", number, pies);
printf("PI = %f\n", PI);
printf("%c%d",'&', 2*cost);
return 0;
}
printf()函数的格式:
- printf( 格式字符串, 待打印项1, 待打印项2,…);
- 待打印项1、待打印项2等都是要打印的项。它们可以是
变量、常量,甚 至是在打印之前先要计算的表达式
。 - 格式字符串应包含每个 待打印项对应的转换说明。
- 格式字符串中的转换说明一定要与后面的每个项相匹配。
- 待打印项1、待打印项2等都是要打印的项。它们可以是
printf()的转换说明修饰符:
在%和转换字符之间插入修饰符可修饰基本的转换说明
。下面列出可作为修饰符的合法字符。如果要插入多个字符,其书写顺序应该与下表 中列出的顺序相同。不是所有的组合都可行
。- 表中有些字符是C99新增 的,如果编译器不支持C99,则可能不支持表中的所有项。
printf()中的标记:
程序示例:
/*
2020年5月27日14:07:51
目的:字段宽度测试
*/
#include <stdio.h>
#define PAGES 959
int main()
{
printf("*%d*\n", PAGES);
printf("*%2d*\n", PAGES);
printf("*%10d*\n", PAGES);
printf("*%-10d*\n",PAGES);
return 0;
}
/*
输出结果:
*959*
*959*
* 959*
*959 *
*/
说明:
- 第1个转换说明%d不带任何修饰符,其对应的输出结果与带整数字段宽 度的转换说明的输出结果相同。
- 第2个转换说明是%2d,其对应的输出结果应该是 2 字段宽度。因为待打印的整数有 3 位数字,所以
字段宽度自动扩大以符合整数的长度。
- 第3个转换说明是%10d,其对应的输出结果有10个空格宽度,实际上在
两个星号之间有7个空格和3位数字,并且数字位于字段的右侧。
- 最后一个转换说明是%-10d,其对应的输出结果同样是 10 个空格宽度
,-标记说明打印的数字位于字段的左侧
/*
2020年5月27日14:23:09
目的: 测试浮点型修饰符的组合
*/
#include <stdio.h>
int main()
{
const double RENT = 3825.99; //const 常量
printf("*%f*\n", RENT);
printf("*%e*\n", RENT);
printf("*%4.2f*\n", RENT);
printf("*%3.1f*\n", RENT);
printf("*%10.3f*\n", RENT);
printf("*%10.3E*\n", RENT);
printf("*%+4.2f*\n", RENT);
printf("*%010.2f*\n", RENT);
return 0;
}
/*
输出结果:
*3825.990000*
*3.825990e+003*
*3825.99*
*3826.0*
* 3825.990*
*3.826E+003*
*+3825.99*
*0003825.99*
*/
说明:
- 第1个转换说明是%f。在这种情况下,
字段宽度和小数点后面的位数均为系统默认设置,
即字段宽度是容纳带打印数字所需的位数和小数后打印6位数字 - 第2个转换说明是%e。
默认情况下,编译器在小数点的左侧打印1个数 字
,在小数点的右侧打印6个数字。这样打印的数字太多!解决方案是指定 小数点右侧显示的位数。 - 第4个和第6个例子对输出结果进行了四舍五入
- 第7个转换说明中包含了+标记,这使得打印的值前面多了一个代数符 号(+)。
0标记使得打印的值前面以0填充以满足字段要求。
- %010.2f的第1个0是标记,
句点(.)之前、标记之后的数字(本例为10) 是指定的字段宽度。
/*
2020年5月27日14:38:32
目的:测试一些格式标记
*/
#include <stdio.h>
int main()
{
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);
return 0;
}
/*
输出结果:
1f 1F 0x1f
**42** 42**-42**
** 6** 006**00006** 006**
*/
说明:
- 第1行输出中,1f是十六进制数,等于十进制数31。第1行printf()语句 中,根据
%x打印出1f,%F打印出1F,%#x打印出0x1f。
- 第 2 行输出演示了如何在转换说明中用空格在输出的
正值前面生成前导空格
,负值前面不产生前导空格。
这样的输出结果比较美观,因为打印出来 的正值和负值在相同字段宽度下的有效数字位数相同。 - 第3行输出演示了
如何在整型格式中使用精度(%5.3d)
生成足够的前 导0以满足最小位数的要求
(本例是3)。然而,使用0标记会使得编译器用 前导0填充满整个字段宽度
。最后,如果0标记和精度一起出现,0标记会被 忽略。
/*
2020年5月27日14:48:42
目的:测试字符串格式
*/
#include <stdio.h>
#define BLURB "Authentic imitation!"
int main()
{
printf("[%2s]\n", BLURB);
printf("[%24s]\n", BLURB);
printf("[%24.5s]\n", BLURB);
printf("[%-24.5s]\n", BLURB);
return 0;
}
/*
输出结果:
[Authentic imitation!]
[ Authentic imitation!]
[ Authe]
[Authe ]
*/
说明:
- 虽然第1个转换说明是%2s,但是字段被扩大为可容纳字符串中 的所有字符。
- 精度限制了待打印字符的个数。
.5告诉printf()只打 印5个字符
。另外,-标记使得文本左对齐输出
.
printf()的返回值:
printf()函数也有一个返回值,它返回打印字符的个数。
/*
2020年5月27日15:03:20
目的:测试 printf() 函数返回值
*/
#include <stdio.h>
int main()
{
int a;
a = printf("哈哈哈%d\n", 222);
printf("%d\n",a);
return 0;
}
/*
输出结果:
哈哈哈222
10
*/
说明:
- 返回值是,
格式化字符串中的所有字符,包括 \n
注意:
printf("The printf() function printed %d characters.\n"
rv);
该语句在逗号和 rv之间断行。为了让读者知道该行未完,示例缩rv。C编译器会忽略多余的空白。
但是,不能在双引号括起来的字符串中间断行。如果这样写:
printf("The printf() function pr
inted %d characters.\n", rv);
- C编译器会报错:字符串常量中有非法字符。在字符串中,
可以使用\n 来表示换行字符,但是不能通过按下Enter(或Return)键产生实际的换行 符
解决方法:这是为了解决字符串很长问题。
示例:
#include <stdio.h>
int main()
{
printf("哈哈哈哈哈哈哈哈哈"); //方法一
printf("whs\n");
printf("哈哈哈哈哈哈哈哈哈\ //方法二
whs\n");
printf("哈哈哈哈哈哈哈哈哈" //方法三
"whs\n");
return 0;
}
/*
输出结果:
哈哈哈哈哈哈哈哈哈whs
哈哈哈哈哈哈哈哈哈whs
哈哈哈哈哈哈哈哈哈whs
*/
说明:
- 方法1:使用多个printf()语句。因为第1个字符串没有以\n字符结束,所 以第2个字符串紧跟第1个字符串末尾输出。
- 方法2:
用反斜杠(\)和Enter(或Return)键组合来断行。这使得光标 移至下一行
,而且字符串中不会包含换行符。其效果是在下一行继续输出。但是,下一行代码必须和程序清单中的代码一样从最左边开始
。如果缩进该 行,比如缩进5个空格,那么这5个空格就会成为字符串的一部分 - ANSI C引入的字符串连接。
在两个用双引号括起来的字符串之 间用空白隔开,
C编译器会把多个字符串看作是一个字符串。
scanf()函数:
- scanf()是最通用的一个,因为它可以读取不同格式的数据。当 然,从键盘输入的都是文本,因为键
盘只能生成文本字符:字母、数字和标 点符号。
如果要输入整数 2014,就要键入字符 2、0、1、4。如果要将其储 存为数值而不是字符串,程序就必须把字符依次转换成数值,这就是scanf() 要做的。 - scanf()把
输入的字符串转换成整数、浮点数、字符或字符串
,而 printf()正好与它相反,把整数、浮点数、字符和字符串转换成显示在屏幕上 的文本
- scanf()和 printf()类似,也使用格式字符串和参数列表。
- 两个函数主要的区别在参数列表 中。printf()函数使用变量、常量和表达式,而scanf()函数使用指向变量的指 针。
程序示例:
#include <stdio.h>
int main()
{
int age;
float assets;
char pet[30];
printf("Enter your age, assets, and favorite pet.\n");
scanf("%d %f", &age, &assets);
scanf("%s", pet);
printf("%d $%.2f %s\n", age, assets, pet);
return 0;
}
说明:
- scanf()函数使用空白(换行符、制表符和空格)把输入分成多个字段。 在依次把转换说明和字段匹配时跳过空白。
- 唯一例外的是
%c转换说明。根据%c,scanf()会读取每个字符,包括空 白。
scanf()中的转换说明:
- scanf()函数所用的转换说明与printf()函数几乎相同。主要的区别是,对 于float类型和double类型,printf()都使用%f、%e、%E、%g和%G转换说 明。而scanf()只把它们用于float类型,
对于double类型时要使用 l (不是数字1)修饰符
。
scanf()中转换说明的修饰符:
(百分号和转换字符之间)使用修饰 符。
scanf()总结
- scanf()函数每次读取一个字符,跳过所有的 空白字符,直至遇到第1个非空白字符才开始读取。(
除了%c,
其他转换说明都会自动跳过待输入值前面所有的空白) scanf()函数每次读取一个字符,跳过所有的 空白字符,直至遇到第1个非空白字符才开始读取
。- scanf()函数允许把普通字符放在格式字符串中。除空格字符外的普通字 符必须与输入字符串严格匹配。
scanf("%d,%d", &n, &m)------------scanf()函数将其解释成:用户将输入一个数字、一个逗号,然后再输入一个数字。
scanf()函数返回成功读取的项数。如果没有读取任何项,且需要读取一 个数字而用户却输入一个非数值字符串,scanf()便返回0。当scanf()检测 到“文件结尾”时,会返回EOF(EOF是stdio.h中定义的特殊值,通常用 #define指令把EOF定义为-1)。
printf()和scanf()的*
修饰符:
- printf()函数:
- 如果
你不想预先指定字段宽度,希望通过程序来指定
,那么可以用*修 饰符代替字段宽度。但还是要用一个参数告诉函数,字段宽度应该是多少。 也就是说,如果转换说明是%d,那么参数列表中应包含和 d对应的值。这 个技巧也可用于浮点值指定精度和字段宽度。
- 如果
程序示例:
#include <stdio.h>
int main()
{
double weight = 242.5;
printf("Weight = %0*.*f\n", 10, 3, weight);
return 0;
}
- scanf()函数:
- 把*放在%和转换字符之间时,
会使得 scanf()跳过相应的输出项
。
- 把*放在%和转换字符之间时,
程序示例:
#include <stdio.h>
int main()
{
int n;
scanf("%*d %*d %d", &n);
printf("%d\n", n);
}
/*
输入样例:
1 2 3
输出结果:
3
*/