首先声明,此博客不照搬抄袭,存在自己的见解,我所使用的编译器是VS2022
目录
1. 数据类型介绍
2. signed和unsigned
3. 数据类型的取值范围
4. 变量
5. 算术操作符:+、-、*、/、%
6. 赋值操作符:=和复合赋值
7. 单⽬操作符:++、--、+、-
8. 强制类型转换
9. scanf和printf介绍
1. 数据类型介绍
首先,C语言中每个数据都强烈建议需要初始化,未初始化可能会导致程序出bug
它们都有一个格式:数据类型+数据名=初始化值,如int a=0;float b=0.0f;char c=‘*’;
C语言中每个数据都有类型,整数有整数的类型,叫做整型(int);小数有小数的类型,叫浮点型(float);字符有字符的类型,叫做字符型(char);还有一个bool类型,用于判断对错
今天我们主要来介绍一下内置类型:
首先是字符型,顾名思义,用于存放字符数据的数据类型例如‘/0’ , '/n' , 'a' , b' , '\060'
char a=‘a’; [signed] char //有符号的 unsigned char //⽆符号的然后是整型,用于存放整数数据的数据类型例如1,2,3
int a=0; //短整型 short [int] [signed] short [int] //有符号短整型 unsigned short [int] //无符号短整型 //整型 int [signed] int //有符号整型 unsigned int //无符号整型 //⻓整型 long [int] [signed] long [int] //有符号长整型 unsigned long [int] //无符号长整型 //长长整型 long long [int] [signed] long long [int] //有符号长长整型 unsigned long long [int] //无符号长长整型接下来是浮点型,用于存放浮点数的数据类型例如3.14 , 6.18
float a=0.0f //浮点型 float //单精度浮点型 double //双精度浮点型 long double //长双精度浮点型接下来是布尔类型,布尔类型比较特殊,其内容只存true或者false,是专门用来判断对错的类型
但使用布尔类型需要注意,要包含头文件#include <stdbool.h>
#include <stdbool.h> _Bool flag = true; bool flag = false; //布尔类型 _Bool bool注意!!!
使用_Bool 的时候不需要头文件#include <stdbool.h>,不需要任何头文件,就能使用
但使用bool的时候必须要头文件#include <stdbool.h>
再注意!!!
注意区分:#include <stdio.h>是库函数输入输出的头文件,stdio> = Standard Input & Output,使用输入输出函数时才是需要用这个头文件
而使用char,float,double,int,_Bool时都是不需要使用头文件的,因为这些都是语言本身自带的关键字,编译器一出生就认识,不需要头文件告诉它这是什么
各种数据类型的长度
数据类型的长度就是此数据类型可以储存数据大小的长度范围
sizeof操作符
此时我们需要一个操作符:sizeof,用于计算数据类型长度的大小,单位是字节(byte)
sizeof(数据类型)
sizeof 表达式
1.sizeof 的操作数如果不是数据类型,是表达式的时候,是可以省略掉后边的括号的。
sizeof 后边的表达式是不真实参与运算的,根据表达式的类型,类型计算来得出对应的大小。
sizeof 的计算结果是 size_t 类型的。size_t就是无符号整型的意思,打印用%zu占位符最准确,%zu专为sizeof服务,也可以用%zd,%zd用于打印有符号整数
#include <stdio.h> int main() { int a = 10; printf("%zu\n", sizeof(a)); printf("%zu\n", sizeof a);//a是变量的名字,可以省略掉sizeof后边的() printf("%zu\n", sizeof(int)); printf("%zu\n", sizeof(3 + 3.5));//3是int整型,3.5是double双精度浮点型,int+double-->double return 0; }其中sizeof(3+3.5)并没有真实去计算表达式的结果,就是没有计算3+3.5=6这个结果,而是计算的表达式的类型,其中3是int整型,3.5是double双精度浮点型,int+double-->double
下面给出类型的计算公式:
一、整数 + 整数:
- char + char →int
- char + short →int
- char + int →int
- short + int →int
- int + int →int
- int + long →long
- long + long →long
二、整数 + 浮点数
- char + float →float
- short + float →float
- int + float →float
- char + double →double
- short + double→double
- int + double →double
- long + double →double
三、浮点数 + 浮点数
- float + float →float
- float + double →double
- double + double →double
四、包含 _Bool(C99 布尔)
- _Bool + char →int
- _Bool + int →int
- _Bool + float →float
- _Bool + double →double
总结:(记住以下的规律就好)
- 比 int 小的类型(char/short/_Bool)运算,一律先转 int
- 有 float 没 double → 结果 float
- 只要有 double → 结果一定是 double
- 整数 + 浮点数 → 结果是浮点数
其实也很好理解,3+3.5结果是小数,所以结果会提升至double类型,这是必然滴
以后在写代码时遇到:
int a = 5; float b = 2.2f; double c = 3.3; int ret = a + c; // 本来是double,强行塞进int❌ double ret =a + c; //int + double的类型应该是double✅这三个数,不知道这些数据类型的相加规则,就会像上述这样结果本来是double类型,最后却强行塞进int,导致警告:
注意!!!
在 C 语言里,_Bool本质就是个只能存 0 或 1 的整数类型,所以它归在整数家族里。
底层就是整数
true→ 就是整数1false→ 就是整数0
数据类型长度
下面给出内置类型数据类型的计算写法与长度:
#include <stdio.h> int main() { printf("char=%zu\n", sizeof(char));//char 1 printf("_Bool=%zu\n", sizeof(_Bool));//_Bool 1 printf("short=%zu\n", sizeof(short));//short 2 printf("int=%zu\n", sizeof(int));//int 4 printf("long=%zu\n", sizeof(long));//long 4 在64位下long 8 printf("long long=%zu\n", sizeof(long long));//long long 8 printf("float=%zu\n", sizeof(float));//float 4 printf("double=%zu\n", sizeof(double));//double 8 printf("long double=%zu\n", sizeof(long double));//long double 8 return 0; }2. signed和unsigned
signed和unsigned在C语言中是专门用来修饰int整型和char字符型的
signed的意思是有符号的,包含正负整数
unsigned的意思是无符号的,只包含正整数和0
在C语言中,int类默认就是带有符号的,所以signed int就等于int,所以signed一般省略不写,如:
注意[ ]表示里面的内容表示可以省略
[signed] int a;
signed [int] a;
unsigned [int] a;
整数变量用unsigned声明的好处是,可以表达或在内存中存储的最大整数值可以扩大一倍,⽐如,16位的 signed short int 的取值范围是:-32768~32767,最⼤是32767;⽽ unsigned short int 的取值范围是:0~65535,最⼤值增⼤到了65,535。
short类型占两个字节,16个bit位,所以是16位
char字符也可以设置signed和unsigned类型:
signed char c; // 范围为 -128 到 127
unsigned char c; // 范围为 0 到 255
但要注意的是:char在C语言中是有符号还是无符号的,是靠编译器来决定的,每个编译器下,char可能是有符号的,也可能是无符号的,所以signed char!=char,所以在用这两个关键字描述char时不能像int一样省略不写
3. 数据类型的取值范围
每个数据类型都有自己所能存储的最大值和最小值,当我们知道了最大值和最小值时,我们就能更好的在场景下更准确的使用我们的数据类型
limits.h ⽂件中说明了整型类型的取值范围
float.h 这个头⽂件中说明浮点型类型的取值范围
可以转到文档进去查看
常见类型取值范围:
| 类型 | 字节 | 取值范围 |
|---|---|---|
| char | 1 | -128~127 或 0~255(看系统) |
| signed char | 1 | -128~127 |
| unsigned char | 1 | 0~255 |
| short | 2 | -32768~32767 |
| unsigned short | 2 | 0~65535 |
| int | 4 | -2147483648~2147483647 |
| unsigned int | 4 | 0~4294967295 |
| float | 4 | ±10⁻³⁸~±10³⁸ |
| double | 8 | ±10⁻³⁰⁸~±10³⁰⁸ |
4. 变量
在C语言中,创建变量时都需要初始化,例如int a=0;把变量a初始化为0
变量初始化的公式:数据类型+变量名=初始化值
4.1变量的分类
变量分为全局变量和局部变量
• 全局变量:就是在主函数main()函数之外设置或者说在大括号外部定义的变量就是全局变量
全局变量变量可以在整个工程中使用,直到工程结束才销毁
•局部变量:在所有函数的大括号里设置的变量就叫做局部变量
局部变量只能在创建此变量的括号内使用,出了此括号便不能使用,因为出了此括号就会被销毁!!!
有一种情况,局部变量和全局变量同名时,该是什么情况呢?
#inlcude <stdio.h> int a=10; int main() { int a=5; printf("%d",a);//会打印5 return 0; }上述代码会打印5,因为当局部变量和全局变量同名的时候,局部变量优先使用
变量不初始化的后果:
全局变量如果不初始化,比如int a;会自动初始化为0
局部变量如果不初始化,比如int a;会初始化为随机垃圾值
5. 算术操作符:+、-、*、/、%
就是完成加减乘除操作的,他们都是双目操作符,双目就是有两个操作数
#include <stdio.h> int main() { int a=20; int b=10; int ret1=0;int ret2=0;int ret3=0;int ret4=0;int ret5=0; ret1=a+b;//加法 ret2=a-b;//减法 ret3=a*b;//乘法 ret4=a/b;//除法 ret5=a%b;//求余 return 0; }但要注意的是除法(/)这个操作符
除法操作符/
#include <stdio.h> int main() { float x = 6 / 4; printf("%f\n", x); // 输出 1.000000 return 0; }如上图所示,尽管x已经设置成了float类型,但打印时用%f并不会打印出正确的小数这是为什么?
这是因为在C语言中的整数除法是整除,只会返回整数部分,丢弃小数部分,想要得到正确小数的结果,那么在两个运算数中,必须有一个浮点数,才会进行浮点数运算
例如:
#include <stdio.h> int main() { float x = 6.0 / 4; // 或者写成 6 / 4.0 printf("%f\n", x); // 输出 1.500000 printf("%.2f\n",x); //输出1.50 return 0; }当只用%f时,默认输出六位小数;
如果想要控制小数的位数,那么可以在%f中加入.2,也就是%.2f表示限制小数点位数只输出两位
再给出一段代码便于理解除法浮点数的运算:
#include <stdio.h> int main() { float a = 10.0f; int b = 5; float ret = a / b; //其中a为浮点数的值,所以会进行浮点数运算 printf("%f\n", ret); //结果为2.000000 return 0; }求模(余)操作符%
有个要注意的点:求模(余)操作符%的两个操作数都只能是整数,用于整数运算,不能用于浮点数,而且此操作符的结果的正负号是由第一个操作符的符号来决定的,下面给出一些例子:
#include <stdio.h> int main() { printf("%d\n", 11 % -5); // 1 printf("%d\n",-11 % -5); // -1 printf("%d\n",-11 % 5); // -1 return 0; }6. 赋值操作符:=和复合赋值
赋值赋值操作符=
赋值操作符顾名思义:用于给变量赋值的操作符(=)如:int a=0;
当然赋值操作符也是可以进行连续赋值运算的,
例如:
#include <stdio.h> int main() { int a = 2; int b = 5; int c = b = a + b;//连续赋值 printf("%d\n", c);//结果是7 return 0; }连续赋值运算的规则是,从右到左计算,例如上述,是先计算b=a+b,把a+b等于7的值赋给了b,此时b==7,然后再计算int c=b,所以c的值就是7
复合赋值操作符
a=a+b可以简化成a+=b
a=a-b可以简化成a-=b
下面给出复合赋值操作符的表格
| 运算符 | 写法 | 等价于 |
|---|---|---|
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
7. 单目操作符:++、--、+、-
+ -
首先+就是表示整数的,例如+5,一般省略不写
而-就是表示负数的,可以把正数变为负数,也可以把负数变正数
++ --
分为前置++(--)和后置++(--)
前置的意思就是放在操作数的前面,如:++a,意思是先加后使用
后置的意思就是放在操作数的后面,如:a++,意识是先使用后加
8. 强制类型转换
强制类型转换的语法是:(转化类型)数据,如(int)3.14,(float)b
#include <stdio.h> int main() { int a = 5, b = 2; double c = a / b; // 5/2 是整数除法 → 2 printf("%d\n",c); //c打印出来是2 double d = (double)a / b;// 先把 a 转 double → 5.0/2=2.5 printf("%d\n",d); //d打印出来是2.5 return 0; }以上代码(double)a会把a强制转化为浮点数5.0从而进行小数的除法运算,最终得出正确结果5.0/2等于2.5
9. scanf和printf介绍
scanf是用于在屏幕上输入数值的库函数
printf是用于在屏幕上打印数值的库函数
它们都需要占位符来打印所想要打印的数值
printf函数
pirntf("%d\n",10);//%d就是用来打印整数的占位符
printf函数中有n个占位符,就有n+1个参数,例如上述中的:一个占位符%d,两个参数:"%d\n"和10
还有很多常用的占位符如下表所示:
| 占位符 | 作用 | 示例输出 |
|---|---|---|
%d | 输出int 十进制整数 | printf("%d", 123);→123 |
%ld | 输出long 长整型 | printf("%ld", 123456L); |
%lld | 输出long long | printf("%lld", 123LL); |
%u | 输出unsigned 无符号整数 | printf("%u", -1); |
%c | 输出单个字符 | printf("%c", 'A');→A |
%s | 输出字符串 | printf("%s", "hello");→hello |
%f | 输出float /double 浮点数 | printf("%f", 3.14);→3.140000 |
%lf | 输入用 double,printf 里同 % f | scanf("%lf", &x); |
%.2f | 保留2 位小数 | printf("%.2f", 3.1415);→3.14 |
%x | 以小写十六进制输出 | printf("%x", 26);→1a |
%X | 以大写十六进制输出 | printf("%X", 26);→1A |
%o | 以八进制输出 | printf("%o", 8);→10 |
%p | 输出指针地址 | printf("%p", &a); |
%% | 输出一个百分号本身 |
|
printf里的一些占位符用法说明
在占位符%d中加入数字,可以限制数字输出在屏幕上的格数,如下方代码所示:
#include <stdio.h> int main() { printf("%5d\n", 123); //表示限制最小宽度为五个格子,并且右对齐: 123 printf("%-5d\n", 123);//表示限制最小宽度为五个格子,并且左对齐:123 printf("%-5d\n", 123456);//如果要打印的数超出限制范围,则正常打印,不用管左对齐还是右对齐:12345 return 0; }运行截图:
对于%f,在其中加数字则是限制最小宽度,如%5.2f
#include <stdio.h> int main() { float a=3.1415926f;//%f,规定就固定打印六位小数 printf("%5f\n",a); //会打印3.141593,最小宽度是5,当打印值超过最小宽度时会正常打印 printf("%f\n",a); //会打印3.141593,因为%f默认输出 6 位小数,不够补0,多了四舍五入。 printf("%5.2f\n",a); //会打印 3.14,最小宽度是5,小数的占两位,右对齐 printf("%-5.2f\n",a); //会打印3.14 ,最小宽度是5,小数的占两位,左对齐 return 0; }运行截图:
对于%d,%+d表示总是显示正负号
一般来说,正数是不会显示正号的,只有负数会显示负号,但当我们再d前加个+时,就表示总是显示正负号
#include <stdio.h> int main() { printf("%+d\n", 12); // 输出 +12 ,只有在d前加+号,才可以达到总是显示正负号的效果 printf("%d\n", +12); // 输出 12 ,尽管在12前加+号,输出时也不会显示正号 printf("%+d\n", -12); // 输出 -12 printf("%d\n", -12); // 输出 -12 return 0; }运行截图:
%s是用来输出字符串的,%.5s贼可以限制输出的个数,只输出前五个字符,而%5s表示至少输出5个字符的长度,不够补空格。和%d一样,%5s右对齐,%-5s左对齐。也可以%10.5s,表示总宽度为10,而只截取前五个字符,不够补空格
int main() { printf("%.5s\n", "hello world");//只输出hello printf("%5s\n", "hello world");//要输出的字符超过了最小限制宽度,所以正常打印 printf("%8s\n", "hello");//输出的字符个数不够8位,只有5位,且右对齐,所以会在左边补三个空格 printf("%-8s\n", "hello");//输出的字符个数不够8位,只有5位,且左对齐,所以会在右边补三个空格 printf("%8.5s\n", "hello world");//.5限制只取前五个字符hello,%8.5是右对齐,至少输出8个宽度 return 0; }运行截图:
在C语言中,最小宽度和限制小数的值都可以用*来代替,并在printf中的参数写出来
#include <stdio.h> int main() { printf("%*.*f\n", 6, 2, 0.5);//原本是printf("%6.2f\n");6,2,可以用*代替 return 0; }运行截图:
scanf函数
基本用法
scanf函数就是用于输入变量的数值的函数,用scanf输入后便可以用printf输出
给出一段简单代码来说明scanf的用法
#include <stdio.h> int main() { int score = 0; printf("请输⼊成绩:"); scanf("%d", &score); //输入成绩 printf("成绩是:%d\n", score); //打印成绩 return 0; }运行截图:
注意!!!
scanf函数里的参数必须是地址,所以在使用scanf时都会在变量前加入取地址符号&
如上图代码scanf("%d", &score); 只有当要输入的值本身就是地址时才不需要&,比如输入字符串数组的值
scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。
int main() { int i = 0, j = 0; float x = 0.0f; double y = 0.0; //上面初始化int i = 0, j = 0; 等同于int i=0;int j=0; scanf("%d%d%f%lf", &i, &j, &x, &y); printf("%d %d %f %lf",i,j,x,y); return 0; }补充:初始化int i = 0;int j = 0 ;可以简化成 int i=0,j=0;
运行截图:
scanf会自动过滤空白字符,包括空格、制表符、换行符,如上图我1跟-20之间输入了换行符,-20和3.14之间输入了空格,3.14和-4.0e3之间输入了两个制表符,但都自动过滤忽略,不影响scanf解读,下方正常打印
补充:-4.0e3采用的是科学计数法,计算为-4.0 × 10³,结果为-4000.0,如果是3e3,计算为3 × 10³,结果为3000.0,为double类型的小数。
打印结果为六位小数是因为% f 和 % lf 和%Lf,都默认打印6 位小数。
记住:只要是小数、或带 e 的科学计数法,默认都是 double 类型
上面的示例中,scanf每读取一个数据后,遇到了会自动过滤的字符,就会自动过滤,直到读取到下一个占位符所对应的数值,存到对应的变量中,然后又遇到会自动过滤的字符,再次自动过滤,直到继续读取到下一个占位符所对应的数值,并存入占位符相对应的变量中
scanf () 处理用户输入的原理是:用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。
比如输入 123abc时,scanf("%d%c",&n,&ch),刚开始输入的时候,是把123abc都放在缓存区里,%d会读取整数,把123读走放入变量n,因为下个字符a不属于整型字符,不符合占位符的条件,所以%d读取结束,此时缓存区还剩下abc和隐藏的\0,%c会读取一个字符a,放入变量ch中,剩下的bc将不会被读取,依然放在缓存区里,直到再使用scanf继续读取,下面给出代码
#include <stdio.h> int main() { int n; char ch; // 输入:123abc scanf("%d%c", &n, &ch); printf("n = %d\n", n); printf("ch = [%c]\n", ch); return 0; }运行截图:
scanf的返回值
scanf () 的返回值是一个整数,表示成功读取的变量个数。如果没有读取任何项,或者匹配失败,则返回 0。如果在成功读取任何数据之前,发生了读取错误或者遇到文件结尾,则返回常量 EOF (-1)。EOF——end of file文件结束标志
下面给出代码演示:
#include <stdio.h> // 清空输入缓存关键,多次连续使用 scanf 时,必须清空输入缓存,否则会互相干扰! // 除非上一个scanf把缓存区的内容读完了,那么就不需要了 void flush() { while (getchar() != '\n'); } int main() { int a=0, b=0; int ret=0; // ------------- 测试1:输入 10 20 printf("输入两个整数(如:10 20):"); ret = scanf("%d%d", &a, &b); printf("scanf返回值:%d\n\n", ret); flush(); // 清空缓存,避免影响下一次输入 // ------------- 测试2:输入 abc printf("输入字母(如:abc):"); ret = scanf("%d", &a); printf("scanf返回值:%d\n\n", ret); flush(); // 清空缓存 // ------------- 测试3:触发 EOF printf("输入时按 Ctrl+Z 再回车(EOF):"); ret = scanf("%d", &a); printf("scanf返回值:%d(即 EOF = %d)\n", ret, EOF); return 0; }运行截图:
测试1中:scanf读取了两个整型的数值放入变量中,返回2
测试2中:scanf本来要读取整型数值,却输入了字符类型的数值,%d无法读取,所以一个数值都没有读取到,返回0
测试3中:我们输入三个(ctrl+z+回车),主动触发文件结束,返回EOF(-1)
解读一下:
void flush()
{
while (getchar() != '\n'){
;
}
}
此函数是用于,清空输入缓存关键,多次连续使用 scanf 时,必须清空输入缓存,否则会互相干扰!除非上一个scanf把缓存区的内容读完了,那么就不需要了
getchar的作用是每次读取一个字符,此函数循环内部内容为空,表示什么都不做,只读取,读取完就丢,直到读取完\n后,就结束循环,而我们scanf的输入,当输入数值字符在缓存区时,最终都是以\n(回车)结尾,才能输入到程序中去,此循环刚好把\n及\n之前的无用缓存字符全部清空,防止了scanf之间的互相干扰,以来到达可以正确输入读取的效果
scanf中的占位符
scanf的占位符与printf基本一致,但用读取规则稍有不同,比如%c,%s
scanf有个占位符printf里没有:%[ ]
下面我来逐一讲解一下:
%c
%c不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上⼀个空格,表示跳过零个或多个连续的空白字符。%s前加一个空格也能达到这种效果:scanf(" %s",&ch);
#include <stdio.h> void flush() { while (getchar() != '\n') ; } int main() { char ch[10] = { '\0' }; //测试一:输入( abc),不会跳过空白字符 printf("请输入 abc\n"); scanf("%3c",ch); printf("打印结果:%s\n\n", ch); flush(); //测试一:输入( a b c),只会跳过最前方的连续的空白字符,跳过之后,连续读取三个字符,读取过程中如果再遇到空白字符,无法再跳过 printf("请输入 a b c\n"); scanf(" %3c", ch); printf("打印结果:%s\n\n", ch); flush(); return 0; }运行截图:
%3c在scanf中的效果是:连续读取 3 个字符(包括空格、回车!),存入数组 ch
测试一:输入( abc),不会跳过空白字符,%3c只读取前三个字符,所以会打印( ab)
测试二:输入( a b c),只会跳过最前方的连续的空白字符,跳过之后,连续读取三个字符,读取过程中如果再遇到空白字符,无法再跳过,所以此处跳过了a前面的三个空格,然后从a开始读取,%3往后读取三个字符(a b),所以最后会打印(a b)
%s
它的规则是: 从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。和上述( %3c)c有点像,不同之处在于%s前不需要加空格,就可以跳过开头的空白字符,但当%s遇到下一个空白字符的时候,就会自动停止,比如输入Hello world,只会读取Hello,遇到空白字符就不读了
#include <stdio.h> int main() { char ch[100] = { '\0' }; scanf("%8s", ch); //输入Hello world printf("%s\n", ch); //打印 Hello return 0; }运行截图:
如图所示,开头自动忽略了连续的空格,后续使用了%8s来限制读取前8位字符,但当后续遇到空白字符时,就会停止读取,并在读取的字符串末尾自动添'\0'用于结束字符串的读取,所以只打印Hello
%[ ]
%[ ]只读取[匹配字符集]内的字符一旦遇到不在集合内的字符,会立即停止读取。
可以完美的解决%s遇到空白字符就会停止读取的限制,如%[^\n]
^
- 写在代码表达式里:
^是异或运算符- 写在
%[ ]里:^是排除符号,表示非、除了- %[^\n]表示除了'\n',遇到的字符全部读取
比如:
#includ <stdio.h> int main() { char ch[100] = { 0 }; scanf("%[^\n]s", ch); //输入Hello world printf("%s\n", ch); //打印 Hello world return 0; }运行截图:
scanf赋值忽略符%*
有时,用户输入的格式不符合规定的格式,如:
#include <stdio.h> int main() { int year = 0;int month = 0; int day = 0; scanf("%d-%d-%d", &year, &month, &day); //输入2026-4-4 printf("%d %d %d\n", year, month, day); //打印2026 4 4 return 0; }运行截图:
但当用户输入别的格式时,如2026/4/4,scanf就会解析错误,结果如下:
运行截图:
本来应该读取的-,现在输入的是/,scanf读取错误,解析错误,会直接停止工作,后续month和day的值都为初始化的0,所以会有此结果
此时!!!
我们可以使用scanf赋值忽略符%*,来忽略这些打错的格式
%*的作用是该占位符读取后不会返回值,解析后就将值丢弃,不会存储于变量中
下图代码展示其作用,如:
#include <stdio.h> int main() { int year = 0;int month = 0;int day = 0; scanf("%d%*c%d%*c%d", &year, &month, &day); printf("%d %d %d\n", year, month, day); return 0; }运行截图:
上面示例中,%*c 就是在占位符的百分号后面,加入了赋值忽略符 * ,表示这个占位符没有对应的变量,解读后不必返回,然后继续解读下一个占位符对应的数据