[一篇读懂]C语言一讲:数据的类型、数据的输入输出
1. 数据类型-常量-变量(整型-浮点-字符)
1 数据类型
数据类型分类:
关键字:
auto | const | double | float | int | short | struct | unsigned |
---|---|---|---|---|---|---|---|
break | continue | else | for | long | signed | switch | void |
case | default | enum | goto | register | sizeof | typedef | volatile |
char | do | extern | if | return | static | union | while |
2 常量
- 常量指在程序运行过程中,值不发生变化的量。
- 可分为整型、实型(也称浮点型)、字符型和字符串型。
- 整型 - 100,125,-100,0
- 实型 - 3.14,0.125,-3.789
- 字符型 - ‘a’,‘b’,‘2’
- 字符串型 - “a”,“ab”,“1c34”
3 变量
变量名、变量值和存储单元的关系:
- 变量指内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。
- 这些值在程序的执行过程中是可以改变的。
- 每个变量名分配对应的内存地址(空间)。
- 变量命名规定如下:只能由字母、数字和下划线三种字符组成,并且第一个字符必须为字母或下划线。
例如:
sum,_total,month,Student_name,lotus_1_2_3,BASIC,li_ling
是正确的。
而M.D.John,¥123,3D64,a>b
是错误的。
- 先定义,后使用
- 尽量做到“见名知意”,注意,变量名不能与关键字同名!
4 整型数据
4.1 符号常量
定义整型变量时要使用关键字int:
#include <stdio.h>
#define PI 3+2
int main()
{
int i = PI * 2;
printf("i = %d\n",i);
}
最终输出的结果是7,原因是符号常量PI是直接替换的效果,即3+2*2=7,而不是8。
4.2 整型变量
- 通过int i来定义整型变量,i占用4个字节空间。
5 浮点型数据
5.1 浮点型常量
- 表示浮点型常量的方式有两种,如下所示,其中e代表10的幂次,幂次可正可负。
小数形式 | 指数形式 |
---|---|
0.123 | 3e-3(为 3 × 1 0 − 3 3×10^{-3} 3×10−3,即0.003) |
- 注意,字母e(或E)之前必须有数字,且e后面的指数必须为整数。
正确示例:1e3、1.8e-3、-123e-6、-.1e-3。
错误实例:e3、2.1e3.5、.e3、e。
5.2 浮点型变量
- 通过float f来定义浮点变量,f占用4个字节空间。
6 字符型数据
6.1 字符型变量
- 用单引号括起来的一个字符是字符型常量,且只能包含一个字符! 例如, ‘a’、‘A’、‘1’。
- ’ '是正确的字符型常量。
‘abc’、“a”、" "是错误的字符型常量。
- 转义字符:以“\”开头的特殊字符,转义字符可用来表示回车、退格等功能键。
转义字符 | 作用 |
---|---|
\n | 换行 |
\b | 退格 |
\\ | 反斜杠 |
6.2 字符数据在内存中的存储形式及使用方法
- 字符型变量使用关键字char进行定义,一个字符型变量占用1字节大小的空间。
- 一个字符常量把该字符的ASCII码值放到存储单元中。
- 字符型数据和整型数据之间可以通用。
- 字符型数据既可以以字符形式输出,又可以以整数形式输出,还可以通过运算获取想要的各种字符:
#include <stdio.h>
int main()
{
char c = 'A';
printf("%c\n",c+32);
printf("%d\n",c);
}
- 对于字符型变量,无论是赋ASCII码值还是赋字符,使用%c打印输出时得到的都是字符,使用%d打印输出时得到的都是ASCII码值。
- 将小写字母转换为大写字母时,由ASCII码表发现小写字母与大写字母的差值为32,因此将a减去32就可以得到大写字母A。
7 字符串型常量
- 字符串型常量是由一对双引号括起来的字符序列。
- 例如,“How do you do.”、“CHINA”、“a”和“$123.45”。
- 注意,'a’是字符型常量,而“a”是字符串型常量,二者是不同的。
- 在字符串型常量的结尾加一个字符串结束标志’\0’,以便判断字符串是否结束。
例如,字符串型常量“CHINA”在内存中占用的内存单元不是5个字符,而是6字符,即大小为6个字节,最后一个字符为’\0’。
在内存中的存储结果:
8 ASCII码表
2. 混合运算 - printf讲解
1 混合运算
类型强制转换场景
- 整型数进行除法运算时,如果运算结果为小数,那么存储浮点数时一定要进行强制类型转换:
#include <stdio.h>
//强制类型转换
int main()
{
int i = 5;
float f = i / 2;//2.0 - 左右操作数都是整型,这里做整型运算,商为2余数1
//类型强制转换
float k = (float)i / 2;//2.5 - 表达式的类型为浮点型
printf("%f\n", f);//2.0
printf("%f\n", k);//2.5
return 0;
}
j得到的值为2,k得到的值是2.5,因为当我们整数做除法时,默认进行整除,要得到小数,需要首先进行强制类型转换操作。
2 printf函数介绍
- printf函数可以输出各种类型的数据,是printf函数将这些类型的数据格式化为字符串后,放入标准输出缓冲区,然后将结果显示到屏幕上。
#include <stdio.h>
int printf(const char *format, ...);
- 字符串格式(format)由两部分组成:显示到屏幕上的字符和定义printf函数显示的其他参数。
int age = 21;
printf("Hello %s, you are %d years old\n","Bob",age);
输出:Hello Bob, you are 21 years old
printf函数的具体代码格式:
代码 | 格式 |
---|---|
%c | 字符 |
%d | 带符号整数 |
%f | 浮点数 |
%s | 一串字符 |
%u | 无符号整数 |
%x | 无符号十六进制数,用小写字母 |
%X | 无符号十六进制数,用大写字母 |
%p | 一个指针 |
%% | 一个’%'符号 |
位于%和格式化命令之间的一个整数被称为最小字段宽度说明符,通常会加上空格来控制格式。
- 用%f精度修饰符指定想要的小数位数。例如,%5.2f会至少显示5位数字并带有2位小数的浮点数。
- 用%s精度修饰符简单地表示一个最大的长度,以补充句点前的最小字段长度。
- printf函数的所有输出都是右对齐的,除非在%符号后放置了负号。例如,%-5.2f 会显示5位字符、2位小数位的浮点数并且左对齐。
#include <stdio.h>
//练习printf
//int main()
//{
// int age = 21;
// printf("Hello %s, you are %d years old\n", "Bob", age);
// return 0;
//}
int main()
{
int i = 10;
float f = 96.3;
printf("student number =%d score=%f\n", i, f);
printf("student number =%3d score=%5.2f\n",i,f);//%3d 占三个位置 - 对齐 //%5.2f 5 - 整体占五个位置 2 - 小数点后保留两位
printf("student number =%-3d score=%-5.2f\n",i,f);//默认是右对齐,加一个负号 - %-3d - 左对齐
i = 100;//第一次是定义,再次使用不需要定义
f = 98.21;
printf("student number =%d score=%f\n", i, f);//上下不对齐
return 0;
}
运行结果:
3. 整型进制转换
1 整型常量的不同进制表示
- 计算机中只能存储二进制数,即0和1,而在对应的物理硬件上则是高、低电平。
- 除我们正常使用的十进制数外,计算机还提供了十六进制数和八进制数。
进制 | 基数 |
---|---|
二进制 | 0和1 |
十进制(%d) | 0-9 |
八进制(%o) | 0-7 |
十六进制(%x) | 0-9和a-f |
- 1字节(byte)为8位(bit),1位即二进制的1位,它存储0或1。
int型常量的大小为4字节,即32位。
- 二进制数0100 1100 0011 0001 0101 0110 1111 1110
最高位0
是符号位。
对应的是2的幂次 - 十六进制在观察内存时需要频繁使用。
- 例i的值是7b(十六进制),其十进制值为7×16+11=123,i的值是0x0000007b。
地址显示结果为7b 00 00 00,
原因是CPU采用了小端方式进行数据存储,因此低位在前、高位在后。
#include <stdio.h>
int main()
{
int i = 123;
//二进制 0000 0000 0000 0000 0000 0000 0111 1011
printf("%d\n", i);//123
printf("%o\n", i);//173
printf("%x\n", i);//7b
return 0;
}
十进制数转换为二进制的方法:
小技巧:
- 可在Windows操作系统下选择“开始”→“计算器”,打开“计算器”。
- 选择菜单项“查看”→“程序员”可以得到对应进制的转换结果。
4. scanf读取标准输入
1 常用的数据输入/输出函数
- C语言可通过函数库读取标准输入。
1 scanf函数的原理
- C语言通过scanf函数读取键盘输入,键盘输入又称为标准输入。
- 当scanf函数读取标准输入时,如果没有输入任何内容,那么scanf函数会被阻塞。
#include<stdio.h>
//scanf用来读取标准输入,scanf把标准输入内的内容,需要放到某个变量空间里,因此变量必须取地址
//scanf会阻塞,是因为标准输入缓冲区是空的
//scanf %d %f 发现里边有\n空格,忽略
//scanf %c 不忽略内容
int main()
{
int i = 10;
char c;
float f;
scanf("%d", &i);//注意一定要取地址
printf("i = %d\n", i);//把标准缓冲区中的整型数读走了
//rewind(stdin);//清空标准输入缓冲区
//scanf("%c", &c);//读取走了转义字符\n!!!
//printf("c = %c\n", c);//没有等待输入c - 输出了换行!!!
scanf("%f", &f);//忽略转义字符\n
printf("f = %f\n", f);
//fflush(stdin);//清空标准输入缓冲区
return 0;
}//直接运行程序卡住 - 阻塞
为什么第二个scanf函数不会被阻塞呢?
- 其实是因为第二个scanf 函数读取了缓冲区中的’\n’,即 scanf(“%c”,&c)实现了读取,打印其实输出了换行,所以不会阻塞。
但是如果将注释的 fflush(stdin)打开,就会发现第二个scanf(“%c”,&c)会阻塞,这是什么原因呢?
- 行缓冲:在这种情况下,当在输入和输出中遇到换行符时,将执行真正的IO处理操作。
scanf 函数在读取整型数、浮点数、字符串时,会忽略’\n’(回车符)、空格符等字符。
忽略指scanf函数执行时会首先删除这些字符,然后再阻塞。
在执行scanf(“%c”,&c)语句时,不会忽略任何字符,所以其读取了还在缓冲区中残留的’\n’。
2 多种数据类型混合输入
- 为了避免字符型数据读取时,并不会忽略空格和’\n’(回车符)。
- 如下,编写时,在%d与%c之间加入一个空格。
#include<stdio.h>
int main()
{
int i,ret;//ret是scanf匹配成功的个数
char c;
float f;
//输入100 a 98.2
//ret = scanf("%d%c%f", &i, &c, &f);//"%d%c%f"之间不加空格 i=100,c= ,f=0.00
//ret = 2 只匹配成功了两个,因为&c不会忽略任何字符 - %d读走100后,%c读走空格,%f读a时报错返回,所以只匹配成功两个。
ret = scanf("%d %c%f", &i, &c, &f);//要在%c之前加个空格
printf("i=%d,c=%c,f=%f\n", i, c, f);
return 0;
}
格式字符串中的空白字符的含义(来自http://www.cplusplus.com/reference/cstdio/scanf/?kw=scanf):
空白字符:该函数将读取并忽略在下一个非空白字符之前遇到的任何空格字符(空格字符包括空格,换行符和制表符 -
请参阅isspace).格式字符串中的单个空格验证从流中提取的任何数量的空白字符(包括无).
当您的代码是:scanf("%d%c", &x, &ch)
然后你进入
10
在你的控制台:
10
被读取并存储在x
.- 读取并存储换行符
ch
.
如果你使用scanf("%d %c", &x, &ch)
然后你进入
10
10
被读取并存储在x
.- 消费换行符和其他空白字符.程序等待非空白字符.输入一行输入并且该行中至少存在一个非空白字符后,将读入该行的第一个非白色字符
ch
.这是因为stdin
通常是行缓冲的.
总结
1.2
- 常量指在程序运行过程中,值不发生变化的量。
- 可分为整型、实型(也称浮点型)、字符型和字符串型。
1.3
- 变量指内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。
- 这些值在程序的执行过程中是可以改变的。
- 每个变量名分配对应的内存地址(空间)。
- 变量命名规定如下:只能由字母、数字和下划线三种字符组成,并且第一个字符必须为字母或下划线。
1.4
- 通过int i来定义整型变量,i占用4个字节空间。
1.5
- 表示浮点型常量的方式有两种,如下所示,其中e代表10的幂次,幂次可正可负。
- 注意,字母e(或E)之前必须有数字,且e后面的指数必须为整数。
- 通过float f来定义浮点变量,f占用4个字节空间。
1.6
-
用单引号括起来的一个字符是字符型常量,且只能包含一个字符! 例如, ‘a’、‘A’、‘1’。
-
转义字符:以“\”开头的特殊字符,转义字符可用来表示回车、退格等功能键。
-
字符型变量使用关键字char进行定义,一个字符型变量占用1字节大小的空间。
-
一个字符常量把该字符的ASCII码值放到存储单元中。
-
字符型数据和整型数据之间可以通用。
-
字符型数据既可以以字符形式输出,又可以以整数形式输出,还可以通过运算获取想要的各种字符:
-
字符型变量,用%c打印输出时得到字符,用%d打印输出时得到ASCII码值。
-
将小写字母转换为大写字母时,由ASCII码表发现小写字母与大写字母的差值为32,因此将a减去32就可以得到大写字母A。
1.7
- 字符串型常量是由一对双引号括起来的字符序列。
- 注意,'a’是字符型常量,而“a”是字符串型常量,二者是不同的。
- 在字符串型常量的结尾加一个字符串结束标志’\0’,以便判断字符串是否结束。
1.8
2.1
- 整型数进行除法运算时,如果运算结果为小数,那么存储浮点数时一定要进行强制类型转换。
2.2
位于%和格式化命令之间的一个整数被称为最小字段宽度说明符,通常会加上空格来控制格式。
- 用%f精度修饰符指定想要的小数位数。例如,%5.2f会至少显示5位数字并带有2位小数的浮点数。
- 用%s精度修饰符简单地表示一个最大的长度,以补充句点前的最小字段长度。
- printf函数的所有输出都是右对齐的,除非在%符号后放置了负号。例如,%-5.2f 会显示5位字符、2位小数位的浮点数并且左对齐。
3.1
- 计算机中只能存储二进制数,即0和1,而在对应的物理硬件上则是高、低电平。
- 除我们正常使用的十进制数外,计算机还提供了十六进制数和八进制数。
进制 | 基数 |
---|---|
二进制 | 0和1 |
十进制(%d) | 0-9 |
八进制(%o) | 0-7 |
十六进制(%x) | 0-9和a-f |
- 1字节(byte)为8位(bit),1位即二进制的1位,它存储0或1。
int型常量的大小为4字节,即32位。
- 二进制数0100 1100 0011 0001 0101 0110 1111 1110
最高位0
是符号位。
对应的是2的幂次 - 十六进制在观察内存时需要频繁使用。
- 例i的值是7b(十六进制),其十进制值为7×16+11=123,i的值是0x0000007b。
地址显示结果为7b 00 00 00,
原因是CPU采用了小端方式进行数据存储,因此低位在前、高位在后。
十进制数转换为二进制的方法:
小技巧:
- 可在Windows操作系统下选择“开始”→“计算器”,打开“计算器”。
- 选择菜单项“查看”→“程序员”可以得到对应进制的转换结果。
3.2
- 数组名作为实参传递给子函数是,是弱化为指针的。
4.1
- C语言通过scanf函数读取键盘输入,键盘输入又称为标准输入。
- 当scanf函数读取标准输入时,如果没有输入任何内容,那么scanf函数会被阻塞。
4.2
- 为了避免字符型数据读取时,并不会忽略空格和’\n’(回车符)。
- 如下,编写时,在%d与%c之间加入一个空格。