目录
2.1 字符型:char是有符号还是无符号取决于编译的实现,多数情况下char == signed char
1.数据类型介绍
- C语言用数据类型来描述生活中的各种数据。例如:身高-180 体重-120 成绩-98 年龄-22
- 生活中的数据有整数、小数、字符、字符串等。
- 整数类型(int)描述整数;字符类型(char)描述字符;浮点型类型(float)描述小数。
- C语言的各种类型:
1.1 字符型
char(character)
1.2 整型
short [int] --------- 短整型
int ---------------------- 整 型
long [int] -------------- 长整型
long long [int] -------- 更长的类型
1.3 浮点型
- 小数:3.14=0.314*10(小数点可以浮动,小数也叫浮点数)
float ------ 单精度浮点型 (精度要求低、存的数据较小时使用)
double ------ 双精度浮点型 (精度要求高、存的数据较大时使用)
long double
1.4 布尔类型
- C语言原本并没有为布尔单独设置一个类型,用整数0表示假,非零值表示真(包含负数)。
- C99中引入布尔类型,专门表示真假。表示真假的变量成为布尔值。
- 布尔类型的使用必须包含头文件 <stdbool.h>。
- 布尔类型变量的取值是:true或者false。
代码演示:
-Bool和bool都表示布尔类型,代码演示:
1.5 各种数据类型的长度
- 每一种数据类型有自己的长度,使用不同的数据类型,能创建出长度不同的变量,变量长度的不同,存储的数据范围也有差异。
1.5.1 sizeof的操作符
- sizeof是一个关键字,也是一个操作符,用来计算sizeof的操作数的类型长度,单位是字节。
- sizeof(类型)-------用来计算这个类型的长度
char类型是1个字节 short类型是2个字节 long类型是4个字节 long long类型是8个字节 int类型是4个字节 float类型是4个字节 double 类型是8个字节 double类型是8个字节
- 计算中的单位:
- bit--------------Byte-------------KB-------------MB---------------GB--------------TB---------------PB
- 1Byte=8bit 1KB=1024Byte 1MB=1024KB 1GB=1024MB 1TB=1024GB 1PB=1024TB
- 1024=2的10次方
- sizeof的操作数可以是类型,也可是变量或者表达式。
- sizeof的操作数如果不是类型,是表达式可省略后边括号。
- sizeof后边的表达式不参与运算,根据表达式的类型来得出大小。(sizeof在代码进行编译时,根据表达式类型已经确定,而表达式的执行需在程序运行期间执行,在编译期间已经将sizeof处理掉,因此在运行期间不会执行表达式)
解析-sizeof(3+3.5): 3是int整型,3.5是double类型,若此处为3.5f则是float类型。 1个int类型+1个double类型=double类型。
解析-sizeof(s=b+1): s是short类型,b是int整型类型,1是int类型。1个int类型+1个int类型=int类型,但这个结果放在s的short类型里,所以结果由s决定。s是short类型长度为2,第一个结果的长度为2。
- sizeof的计算结果是size_t类型的。sizeof打印值用%zd打印。
1.5.2 数据类型的长度
2.signed和Unsigned
- C语言中使用signed和unsigned关键字修饰字符型、整型类型的。
- signed关键字:该类型带有正负号,包含负值。例如:温度
- unsigned关键字:该类型不带有正负号,只表示0和正整数。
- int类型默认带正负号,int == signed int 。例如:signed int a==int a;
2.1 字符型:char是有符号还是无符号取决于编译的实现,多数情况下char == signed char
char //character
[signed] char //有符号的
unsigned char //⽆符号的
2.2 整型:int == signed int
//短整型
short [int]
[signed] short [int]
unsigned short [int]
//整型
int
[signed] int
unsigned int
//⻓整型
long [int]
[signed] long [int]
unsigned long [int]
//更⻓的整型,C99中引⼊
long long [int]
[signed] long long [int]
unsigned long long [int]
- 整数变量声明为 unsigned 的好处:同样长度的内存能够表示的最大整数值,增大了⼀倍。
- 16位的 signed short int 的取值范围是:-32768~32767,最⼤是32767;
- unsigned short int 的取值范围是:0~65535,最大值增大到了65,535。
- 因为 unsigned 没有负数,所以将负的数值转换为整的。
- 32位的 signed int 的取值范围可以参看 limits.h 中给出的定义。
- 下面的定义是VS2022环境中,limits.h中相关定义。
#define SHRT_MIN (-32768) //有符号16位整型的最⼩值
#define SHRT_MAX 32767 //有符号16位整型的最⼤值
#define USHRT_MAX 0xffff //⽆符号16位整型的最⼤值
#define INT_MIN (-2147483647 - 1) //有符号整型的最⼩值
#define INT_MAX 2147483647 //有符号整型的最⼤值
字符类型 char 也可以设置 signed 和 unsigned 。
signed char c; // 范围为 -128 到 127
unsigned char c; // 范围为 0 到 255
3.数据类型的取值范围
类型是用来创建变量的。每⼀种数据类型有自己的取值范围,也就是存储的数值的最⼤值和最⼩值的区间,如果要查看当前系统上不同数据类型的极限值:
limits.h ⽂件中说明了整型类型的取值范围。
float.h 这个头⽂件中说明浮点型类型的取值范围。
为了代码的可移植性,需要知道某种整数类型的极限值时,应该尽量使用这些常量。
- SCHAR_MIN , SCHAR_MAX :signed char 的最小值和最大值。
- SHRT_MIN , SHRT_MAX :short 的最小值和最大值。
- INT_MIN , INT_MAX :int 的最小值和最大值。
- LONG_MIN , LONG_MAX :long 的最小值和最大值。
- LLONG_MIN , LLONG_MAX :long long 的最小值和最大值。
- UCHAR_MAX :unsigned char 的最大值。
- USHRT_MAX :unsigned short 的最大值。
- UINT_MAX :unsigned int 的最大值。
- ULONG_MAX :unsigned long 的最大值。
- ULLONG_MAX :unsigned long long 的最大值。
4.变量
4.1 变量的创建
C语言把经常变化的值成为变量,不变的值称为常量。例如:变量-年龄-身高-体重
- 变量创建的语法形式:数据类型 + 变量名。
unsigned int age
char ch
double weight
bool flag
- 变量在创建时给一个初始值,叫初始化。
unsigned int age = 12;
char ch =‘q’;
double weight = 49.2;
unsigned int height = 102;
4.2 变量的分类
- 全局变量:大括号外部定义的变量为全局变量(共享单车),适用范围广。存放在内存的静态区。
- 局部变量:大括号内部定义的变量为局部变量(私家车),适用范围局限,只能在局部范围内使用。存放在内存栈区。
当全局变量和局部变量名字相同时,局部变量优先。
5.算数操作符:+、-、*、/、%
C语言提供了一系列操作符,其中一组操作符叫:算术操作符(双目操作符),分别是:+ - * / %,操作符也叫运算符。
+:加法
-:减法
*:乘法
/:除法
除号的两端若是整数,执行整数除法,得到结果也是整数。
13/2=6.5,商6,余5。只取商。
若想得到浮点数的结果,两个运算数必须至少有一个浮点数,此时执行浮点数除法。
例1:
例2:
%:求模/余,返回两个整数相除的余值,运算符只能用于整数,不能用于浮点数。
负数求模规则:结果正负号由第一个运算数的正负号决定。
6.赋值操作符:=和复合赋值
创建变量时给一个初始值叫初始化,变量创建好后,再给一个值叫赋值。
6.1 连续赋值
赋值操作符可以连续赋值。
6.2 复合赋值符
7.单目操作符:++、--、+、-
C语言中操作符只有一个操作数称为单目操作符,++、--、+、-。
7.1 ++和--
++:自增操作符,分为前置++和后置++。
前置++:先++,后使用。
后置++:先使用,后++。
--:自减操作符,分为前置--和后置--。
前置--:先--,后使用。
后置--:先使用,后--。
7.2 +和-
+(正号):单目操作符,运算符+对正负值没有影响,完全可以省略。
-(负号):单目操作符,-用来改变一个值的正负号,负数的前面加上-得到正数,正数前面加上-会得到负数。
8.强制类型转换
强制类型转换的语法形式:(类型)
9.scanf和printf介绍
9.1 printf
- printf():将参数文本输出到屏幕,f-format(格式化),表示可以定制输出文本的格式。
- printf()不会在行尾自动添加换行符,运行结束后,光标就停留在输出结果的地方,不会自动换行。
- 将光标移至下一行,可以在输出文本的结尾,添加一个换行符\n。
- printf()是在标准库的头文件stdio.h定义的,使用函数前必须在源码文件头部引入这个头文件。
9.1.2 占位符
printf()可以在输出文本中指定占位符。占位符:位置可以用其他值代入。
- 占位符的第一个字符一律为%,第二个字符表示占位符的类型。
- %d:代入的值必须是一个整数。
- 常用的占位符除了%d,还有%s表示代入的是字符串。
%s代表代入的是一个字符串,所以printf()的第二个参数必须是字符串。
输出文本可使用多个占位符。
输出文本 %s says it is %d o'clock有两个占位符,第一个:字符串占位符%s,第二个:整数占位符%d,分别对应printf()的第二个参数(xiaolv)和第三个参数(22).
printf()参数与占位符是一一对应关系,若有n个占位符,printf()应该有n+1个参数,若参数个数少于对应的占位符,printf()可能会输出内存中的任意值。
9.1.3 占位符列举
printf() 占位符有许多种类,与 C 语言的数据类型相对应。下面按字母顺序,列出常用的占位符。
- %a :⼗六进制浮点数,字⺟输出为⼩写。
- %A :⼗六进制浮点数,字⺟输出为⼤写。
- %c :字符。
- %d :⼗进制整数。
- %e :使⽤科学计数法的浮点数,指数部分的 e 为⼩写。
- %E :使⽤科学计数法的浮点数,指数部分的 E 为⼤写。
- %i :整数,基本等同于 %d 。
- %f :⼩数(包含 float 类型和 double 类型)。//float -%f double - %lf
- %g :6个有效数字的浮点数。整数部分⼀旦超过6位,就会⾃动转为科学计数法,指数部分的 e 为⼩写。
- %G :等同于 %g ,唯⼀的区别是指数部分的 E 为⼤写。
- %hd :⼗进制 short int 类型。
- %ho :⼋进制 short int 类型。
- %hx :⼗六进制 short int 类型。
- %hu :unsigned short int 类型。
- %ld :⼗进制 long int 类型。
- %lo :⼋进制 long int 类型。
- %lx :⼗六进制 long int 类型。
- %lu :unsigned long int 类型。
- %lld :⼗进制 long long int 类型。
- %llo :⼋进制 long long int 类型。
- %llx :⼗六进制 long long int 类型。
- %llu :unsigned long long int 类型。
- %Le :科学计数法表⽰的 long double 类型浮点数。
- %Lf :long double 类型浮点数。
- %n :已输出的字符串数量。该占位符本⾝不输出,只将值存储在指定变量之中。
- %o :⼋进制整数。
- %p :指针(⽤来打印地址)。
- %s :字符串。
- %u :⽆符号整数(unsigned int)。
- %x :⼗六进制整数。
- %zd : size_t 类型。
- %% :输出⼀个百分号。
int main()
{
printf("%hd\n", 120);//十进制,120=0*0零次方+2*10的1次方+1*10的2次方
printf("%ho\n", 120);//八进制,170=0*8零次方+7*8的1次方+1*8的2次方
printf("%hx\n", 120);//十六进制,78:120/16=7余8,7/16=0余7.倒取余
printf("%x\n", 12); //⼗六进制整数,0、1、2、3、4、5、6、7、8、9、a\b\c\d\e\f
printf("%zd\n", sizeof(short));
}
9.1.4 输出格式
printf()可以定制占位符的输出格式。
9.1.4.1 限定宽度
printf()允许限定占位符的最小宽度。
整数:
int main()
{
printf("%d\n", 172);
printf("%5d\n", 172);
printf("%-5d\n", 172);
printf("%-5dxxxxxxx\n", 172);//5d最少输出5位,不满5位,值前加空格
printf("%2d\n", 172);
printf("%5d\n", 172456);//满5位,输出相应值
return 0;
}
%5d表示占位符的宽度至少为5位,不满5位,对应的值前面会添加空格。 输出的值默认是右对齐,即输出内容前面会有空格。"%5d\n" 若改成左对齐,在输出内容后面添加空格,在占位符%后添加-号。如左图:"%-5d\n"
小数:
%f或者%lf:在打印时,小数点后默认是打印6位。
#include <stdio.h>
int main()
{
printf("%f\n", 12.34);
printf("%lf\n", 12.34);
printf("%lf\n", 123.45);
printf("%12lf\n", 123.45);
return 0;
}
%12lf:输出的浮点数最少占12位,小数的默认显示精度是小数点后6位,所以123.45输出结果的头部会添加2个空格。
9.1.4.2 显示正负号
默认情况下,printf()不对正数显示+号,只对负数显示-号,若想让正数输出+号,可在占位符%后加一个+号。
int main()
{
printf("%d\n", 12);
printf("%d\n", -12);
printf("%+d\n", 12);
printf("%+d\n", -12);
return 0;
}
让正数12输出+号,可在占位符%后加一个+号。"%+d\n"
9.1.4.3 限定小数位数
若想小数点只保留2位,占位符可写成%.2f。
int main()
{
printf("%.2f\n", 12.3456);
printf("%.1f\n", 12.34);
printf("%.3f\n", 123.45);
printf("this is %.2f\n", 12.45);
printf("%10.3f\n", 123.45);
return 0;
}
%.2f:小数点后面输出2位 %.1f:小数点后面输出1位 %.3f:小数点后面输出3位 %10.3f:输出字符串最小宽度为10,小数位数为3,所以输出字符串的头部有2个空格 。
9.1.4.4 输出部分字符串
%s占位符:输出字符串,默认全部输出,若想输出开头部分,用%.[m]s指定输出长度,m为一个数字,表示输出长度。
int main()
{
printf("%s\n", "guaishou");
printf("%.5s\n", "guaishou");
printf("%.2s\n", "guaishou");
return 0;
}
%s占位符:输出所有字符串。 %.5s占位符:字符串的前5个字符。%.2s占位符:字符串的前2个字符。
9.2 scanf
如果有变量,需要给变量输入值就可以使用scanf函数,若需要将变量的值输出在屏幕上就可以使用printf函数。
int main()
{
int score = 0; //创建变量
printf("请输入成绩:");
scanf("%d",&score);//完成输入操作
//scanf函数中占位符的后边参数需要的是地址
//&为取地址操作符,&score:取出score的地址
printf("成绩是 %d\n", score);
return 0;
}
scanf函数的占位符后边参数需要的是地址 。&为取地址操作符,&score:取出score的地址 scanf是将键盘的输入数据放到变量中。printf函数是将数据打印到屏幕上。
9.2.1 scanf用法
- scanf() 函数用于读取用户的键盘输入。
- 程序运行到这个语句时,会停下来,等待用户从键盘输⼊。
- 用户输⼊数据、按下回车键后, scanf() 就会处理用户的输入,将其存入变量。
- 它的原型定义在头文件 stdio.h 。
scanf("%d",&i); //scanf() 第⼀个参数 %d ,表示用户输入的是⼀个整数。 %d 是⼀个占位符, % 是占位符的标志, d 表示整数 。 第⼆个参数 &i 表示,将用户从键盘输入的整数存入变量i
scanf() 第⼀个参数 %d ,表示用户输入的是⼀个整数。 %d 是⼀个占位符, % 是占位符的标志, d 表示整数 。 第⼆个参数 &i 表示,将用户从键盘输入的整数存入变量i 。
scanf() 必须提前知道用户输入的数据类型,才能处理数据。
它的其余参数就是存放用户输入的变量, 格式字符串里面有多少个占位符,就有多少个变量。
int main()
{
int a = 0;
int b = 0;
float f1 = 0.0; //浮点型
float f2 = 0.0;
scanf("%d %d %f %f", &a, &b, &f1, &f2);
printf("%d %d %f %f\n", a, b, f1, f2);
return 0;
}
scanf() 处理数值占位符时,会自动过滤空白字符、包括空格、制表符、换行符等。
scanf() 处理用户输⼊的原理:用户输⼊先放⼊缓存,按回车键后,按照占位符对缓存进行解读。解读用户输⼊时,从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为止。
int main()
{
int x;
float y;
//用户输入 " -13.45e12# 0"
//0.45e12=0.45*10的12次方
scanf("%d", &x);
printf("%d\n", x);
scanf("%f",&y);
printf("%f\n", y);
return 0;
}
scanf() 读取输⼊时, %d 占位符忽略空格,从 - 处开始获取数据,读到 -13 停下, .后的不属于整数的有效字符 。 占位符 %d 只会读到 -13 。
第⼆次调用 scanf() 时,从. 往后读。 占位符是 %f ,会读取到 .45e12 ,采用科学计数法的浮点数格式。#后不属于浮点数的有效字符,停止读取。
scanf("%d,%d", &a, &b);,输入就是3,20
scanf("%d %d", &a, &b);,输入就是3 20
9.2.2 scanf返回值
- scanf() 的返回值是整数,表示成功读取的变量个数。
- 若没有读取任何项,或者匹配失败,则返回 0 。
- 若在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF(-1)。
- EOF - end of file 文件结束标志。
int main()
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int ret = scanf("%d %d %d %d", &a, &b, &c,&d);
printf("a=%d b=%d c=%d d=%d\n", a,b,c,d);
printf("ret=%d\n",ret);
return 0;
}
完全读取的情况,成功读取变量个数,返回4
第4个格式不匹配,返回3
若只有2个数据,按3次ctrl+z就可以停下,返回2
3个ctrl+z停下,读取错误,返回常量EOF(-1)。
没有读取,返回0
9.2.3 scanf常用的占位符
- %c :字符。
- %d :整数。
- %f : float 类型浮点数。
- %lf : double 类型浮点数。
- %Lf : long double 类型浮点数。
- %s :字符串。
- %[ ] :在⽅括号中指定⼀组匹配的字符(⽐如 %[0-9] ),遇到不在集合之中的字符,匹配将会停止。
上面所有占位符之中,除了 %c 以外,都会自动忽略起首的空白字符。 %c 不忽略空白字符,总是返回当前第⼀个字符,无论该字符是否为空格。
占位符%c 不忽略空白字符,例如:
%d可以忽略空格,并打印出101
%c正常输出
输入 ( 空白字符 )g, %c 不忽略空白字符,读取不到g,只能读取第一个字符-空格。
若想跳过空白读取g,在%c前面加空格。 如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上⼀个空格,表示跳过零个或多个空白字符。
占位符 %s :
占位符 %s 的规则:从当前第⼀个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。
scanf() 遇到 %s 占位符,会在字符串变量末尾存储⼀个空字符 \0 。
scanf() 不安全的原因:scanf() 将字符串读入字符数组时,不会检测字符串是否超过了数组长度。为防止这种情况,使用 %s 占位符时,应该指定读入字符串的最长长度,即写成 %[m]s ,其中的 [m] 是⼀个整数,表示读取字符串的最长度,后面的字符将被丢弃。
至多有5个字符,/0在字符末尾,因此有效字符只能是4个,"%4s"。
9.2.4 赋值忽略符
用户输入可能不符合预定的格式。
输入2024-7-17 ,则正确解读出年、月、日。若输入其他格式 2024/7/17 , scanf() 解析数据失败。为了避免这种情况, scanf() 提供了⼀个 赋值忽略符 (assignment suppression character) * 。
把 * 加在任何占位符的%号后面,该占位符就不会返回值,解析后将被丢弃。
输入2024.7.17 或2024/7/17 都会正确解读,%d-%d-%d中间的-为字符改为%c 。%*c 是在占位符的百分号后加入赋值忽略符 * ,表示这个占位符没有对应的变量,解读后不返回。
10.注意事项
注意1:
错误C4996 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 提示scanf函数不安全,考虑scanf-s来替换,若想让错位信息失效,请使用 _CRT_SECURE_NO_WARNINGS
将下述代码放置在使用scanf函数的.c文件的第一行。
#define _CRT_SECURE_NO_WARNINGS 1
注意2:
在创建变量时,给变量一个初始值,若不给变量初始化,编译器会报错。
局部变量若不初始化,值为随机的 。
全局变量可以不初始化,默认值是0。