C语言初识篇——零碎知识点(2)【printf和scanf】

Hello~我是芝士,上一篇分享了C语言常见的操作符,并且提到了一个scanf函数,那么本篇就给大家补充一个知识点:printf和scanf函数。

1. printf 函数

1.1 基本用法

printf()函数的作⽤是将参数⽂本输出到屏幕。那么我们该如何理解呢?对于printf我们可以拆分成print(打印)和f(format–格式的)进行理解,就是按照一定的格式打印数据。用具体的程序操作如下:

#include <stdio.h>//printf()需要包含的头文件
int main()
{
	printf("hello world");
	printf("你好世界\n");//  \n 是换行符号
	printf("hello \nworld\n");//文本内部换行
	printf("你好世界");
	return 0;
}

输出结果:

hello world你好世界
hello
world
你好世界

根据以上的运行结果,我们可以知道printf的基本用法是打印文本,并且printf() 不会在⾏尾⾃动添加换⾏符,运⾏结束后,光标就停留在输出结束的地⽅,不会⾃动换行,换行需要添加换行符\n。并且实现文本内部换行也是在需要换行的位置增加换行符\n。此外,printf() 是在标准库的头⽂件 stdio.h 定义的。使⽤这个函数之前,必须在源码⽂件头部引⼊这个头⽂件。

1.2 占位符

printf()除了打印简单的文本字符串之外,还可以在输出文本中指定占位符。占位符顾名思义就是暂时占用这个位置的符号,即这个位置可以用其他的值代替。具体见下面程序:

#include <stdio.h>
int main()
{
	int num = 100;
	printf("there are %d bananas\n", num);//%d是整数占位符
	printf("there are %d bananas\n", 100);//这里的%d就是占位符
	return 0;
}

⾥⾯的%d就是占位符,表示这个位置要⽤其他值来替换,
注意:占位符的第⼀个字符⼀律为百分号 %,第二个字符表示数据的类型。%d 中的 d 表示这⾥代⼊的值必须是⼀个整数。再例如字符串的占位符:

#include<stdio.h>
int main()
{
	printf("%s is a teacher", "`Zhangsan`");
	return 0;
}

输出得到

Zhangsan is a teacher

由于%s是用于接收字符串的占位符,因此printf()的第二个参数必须为字符串即Zhangsan。
当然,输出文本⾥⾯可以使⽤多个占位符,见下面的程序:

#include<stdio.h>
int main()
{
	int age = 99;
	printf("%s is %d years old", "Zhangsan", age);
	return 0;
}

输出得到:

Zhangsan is 99 years old

这里需要注意的是占位符与参数的位置相匹配的问题,以及printf参数个数。上面的程序中总共有两个占位符即%s和%d,而printf()函数中总共三个参数,“%s is %d years old”、"Zhangsan"和age,这里的%s是与参数"Zhangsan"对应,%d与参数age对应。因此可以得出printf() 参数与占位符是⼀⼀对应关系,如果有 n 个占位符, printf() 的参数就应该有 n + 1 个。如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。
对于占位符的个数,与C语言中的数据类型相对应,下面列举一些我们之前接触的占位符:

占位符对应类型
%c字符
%d⼗进制整数。int
%f⼩数(包含 float 类型和 double 类型)float–%f double–%lf
%hd⼗进制 short int 类型
%huunsigned short int 类型
%ld⼗进制 long int 类型
%s字符串
%zdsize_t 类型接收sizeof返回值
%x⼗六进制整数
%p指针(打印地址)

1.3 输出格式

printf() 可以定制占位符的输出格式,主要有以下几点:

1.3.1 限定宽度

printf() 允许限定占位符的最⼩宽度。具体见下面程序:

#include <stdio.h>
int main()
{
	printf("%6d\n", 123456789);
	printf("%6d", 123);
	return 0;
}

输出结果

123456789
   123//不满6位,前面有三个空格填充

程序例子中的%6d表示这个占位符的宽度至少为6位。如果不满6位,对应的值的前⾯会添加空格。输出的值默认是右对⻬,即输出内容前面会有空格。既然有右对齐,那么就可以设置成左对齐,可以在占位符的%的后⾯插入一个 - 号即可。具体见如下程序:

#include <stdio.h>
int main()
{
	printf("%-6d\n", 123456789);
	printf("%-6dXXX", 123);
	return 0;
}

输出结果

123456789
123   XXX//用XXX是为了更好看出%6d的效果

这里除了对整数类型的占位符进行限定之外,还可以对浮点数类型占位符(%f)进行限定。对于小数,这个限定符会限制所有数字的最小显示宽度。具体见下面程序:

#include <stdio.h>
int main()
{
	float f = 3.14159;
	printf("%9f\n", f);
	printf("%4f", f);
	return 0;
}

输出得到:

 3.141590//前面有一个空格
3.141590

程序中的%9f表示输出的浮点数至少要占据9位,而浮点数默认精度是保留6位小数,因此会增加一个小数位0,并且补齐9位(前面多了一个空格),%4f的原理相同。

1.3.2 显示正负号

我们在打印数字的时候,默认情况下, printf() 不对正数显⽰ 正号(+),只对负数显示负号(-)。如果想让正数也输出 + 号,可以在占位符的 % 后⾯加⼀个 +。具体的效果和操作见下面代码:

int main()
{
	int a = 10;
	int b = -10;
	printf("%d\n", a);
	printf("%+d\n", a);
	printf("%-d\n", b);
	return 0;
}

输出结果

10
+10
-10

综上可知:%+d 可以确保输出的数值,总是带有正负号

1.3.3 限定小数位

我们在输出小数的时候,常常希望输出的结果不要默认的6位数。举例来说,希望⼩数点后⾯只保留两位,占位符可以写成 %.2f(不要漏掉 .)

#include <stdio.h>
int main()
{
	float f = 3.1415926535;
	printf("%.2f\n", f);//保留两位小数
	printf("%.2f\n", 3.456);
	printf("%.3f", f);//保留三位小数
	return 0;
}

输出结果

3.14
3.46
3.142

根据输出结果,我们可知,对于占位符%f小数位数的保留遵循四舍五入原则。需要注意的是,这里要与前面的限定宽度进行区别,不要混淆。当然限定小数点的位数也可以与限定宽度相结合。具体见下面程序:

#include <stdio.h>
int main()
{
	float f = 3.1415926535;
	printf("%6.3f", f);
	return 0;
}

得到输出:

 3.142//前面有一个空格

程序中的 %6.3f 表示的意思是至少输出6个宽度且保留3位小数,6个宽度不够用空格在前面填充。
此外最小宽度和小数位数这两个限定值,都可以⽤ * 代替,并且通过printf()函数的传参进行设置。具体操作见下面程序:

#include <stdio.h>
int main()
{
	float f = 3.1415926535;
	printf("%*.*f", 6 , 3 , f);
	return 0;
}

得到输出结果:

 3.142//前面有一个空格

该结果与前面程序相同,这里需要注意的是printf()函数的参数对应。

1.3.4 输出部分字符串

在printf打印的时候,还可以输出部分字符串。%s 占位符⽤来输出字符串,默认是全部输出。这里与小数保留的写法相似,可以⽤ %.[m]s 指定输出的⻓度,其中 [m] 代表⼀个数字,表示所要输出的长度。具体如下面代码:

#include <stdio.h>
int main()
{
	printf("%s\n", "Hello world");
	printf("%.3s\n", "Hello world");
	printf("%.3s\n", "你好世界");
	printf("%.4s", "你好世界");
	return 0;
}

运行输出

Hello world
Hel
你?
你好

这里的%.3s表示字符串中输出3个字符,因此Hello world最终输出Hel,中文"你好世界"输出三个字符只能完全输出 :你 ,因为一个中文相当于两个两个字符,只有用%.4s时才能输出:你好

2. scanf 函数

除了printf()函数外,还有一个比较常用的函数——scanf()。当我们创建了一个变量需要给变量输入值得时,就可以使用scanf函数——从键盘上获取值,printf()是将变量值输出在屏幕上。我们可以简单看一个程序:

#include <stdio.h>
int main()
{
	int a = 0;//创建变量
	scanf("请输入一个值%d", &a);//获取变量a的值,&表示取地址
	printf("输入的值是a=%d", a);//输出打印
	return 0;
}

运行界面及结果:
在这里插入图片描述
通过程序的运行我们就可以对scanf函数和printf函数有一个直观的认识。下面将对scanf函数的用法、占位符和赋值忽略符进行介绍。

2.1 基本用法

scanf()函数主要用于读取用户键盘上的输入。程序在运行时,遇到scanf()就会停下来,等待用户从键盘输入。当用户输入数据→按下回车scanf()就会处理输入的数据,将其存储在取地址的变量中,其头文件与printf()函数相同stdio.h,语法也与printf()类似。语法结构如下:

scanf( “%d”, &a );

  1. 第一个参数:是⼀个格式字符串,里面会放置占位符(与 printf() 的占位符基本⼀致)
  2. 其他参数:用户输⼊的变量,格式字符串⾥⾯有多少个占位符,就有多少个变量。并且要用到&(取地址符号)

因此,scanf()函数输入的特点需要用户提前知道输入的数据类型
需要注意的是:

  1. 变量前⾯必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,而是地址。
  2. 如果这⾥的变量是指针变量(如字符串变量),那就不⽤加 & 运算符

关于指针变量后续将进行具体介绍。
此外,scanf() 处理数值占位符时,会⾃动过滤空⽩字符,包括空格、制表符、换⾏符等。所以用户输⼊的数据之间,有⼀个或多个空格不影响 scanf() 解读数据。另外,用户使用回车键,将输⼊分成⼏⾏,也不影响解读。
scanf() 可以处理多组数据,原理是用户的输⼊先放⼊缓存,等到按下回车键后,按照占位符对缓存进行解读。解读用户输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为止。具体可以见下面程序:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	float f = 0.0f;
	scanf("%d %d %f", &a, &b, &f);
	printf("a = %d\nb =%d\nf = %f ", a, b, f);
	return 0;
}

输出结果
在这里插入图片描述

2.2 返回值

对于scanf()的返回值,是⼀个整数,表示成功读取的变量个数。如果没有读取任何项,或者匹配失败,则返回 0。如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量 EOF (-1)。这里用程序进行演示:

#include <stdio.h>
int main()
{
		int a = 0;
		int b = 0;
		float f = 0.0f;//0.0f表示f是float类型数字,不然编译器会认为是double类型
		int r = scanf("%d %d %f", &a, &b, &f);//用r接收scanf的返回值
		printf("r = %d\n", r);
		printf("a = %d\nb =%d\nf = %f ", a, b, f);
			return 0;
}

输入及结果:
在这里插入图片描述
因此,我们通常可以使用scanf()返回值来判断数据读取是否正确
要返回EOF的值,在VS中键盘按三次Ctr + Z 并且回车,可以得到返回值-1。
在这里插入图片描述

2.3 占位符

对于我们在前面的prinf()函数也进行了一定的介绍,而scanf()占位符与printf()函数基本保持一致。这里也同样列举几个常用的占位符,见下表:

占位符对应类型
%c字符
%d整数
%ffloat 浮点数
%lfdouble 类型浮点数
%Lflong double 类型浮点数
%s字符串
%[ ]在方括号中指定⼀组匹配的字符(如 %[0~9] 遇到不在集合之中的字符,匹配将会停止)

需要注意的是,上表中的所有占位符之中,除了 %c 以外,都会自动忽略起首的空白字符。%c 不忽略空⽩字符,总是返回当前第⼀个字符,⽆论该字符是否为空格(因为%c就是读取字符的,而空格也是字符的一种)。如果要强制跳过字符前的空⽩字符,可以%c 前加上⼀个空格即scanf(" %c", &a),这样可以跳过零个或多个空⽩字符。
对于占位符%sscanf()在读取时,它的规则是,从当前第⼀个⾮空⽩字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)为⽌。因此scanf()在读取这类数据并且存放的时候,不会去检测空间存放是否合适,在运行过程中如果实际输入超过了存放空间,可能会出现不安全警告。如下程序所示:

#include <stdio.h>
int main()
{
	char name1[5];//数组大小为5
	scanf("%s", name1);//数组不需要取地址符号&,其本身就是地址。
	return 0;
}

爆出警告
在这里插入图片描述
为了防⽌这种情况,使⽤ %s 占位符时,应该指定读⼊字符串的最长的长度。写成:即写成 %[m]s ,其中的 [m] 是⼀个整数,表⽰读取字符串的最⼤⻓度,后⾯的字符将被丢弃。具体见下面程序及运行结果:
在这里插入图片描述

2.4 赋值忽略符

前面提到的,scanf函数必须预先知道我们要输入的数据类型,不然会报错。但是在实际中,有可能可能不符合预定的格式。比如下面的程序:

#include <stdio.h>
int main()
{
	int year = 0;
	int month = 0;
	int day = 0;
	printf("请输入日期:");
	scanf("%d-%d-%d", &year, &month, &day);
	printf("%d/ %d /%d", year, month, day);
	return 0;
}

只有当我们输入正确的格式:2024-7-18时,才会输出我们想要的日期。在这里插入图片描述
如果输入其他格式,比如:2024/7/18,输出结果如下:
在这里插入图片描述
这种情况下, scanf() 解析数据失败了。
因此为了避免这一情况,我们在使用scanf()函数时可以运用赋值忽略符(*)把 * 加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃。具体操作如下:

#include <stdio.h>
int main()
{
	int year = 0;
	int month = 0;
	int day = 0;
	printf("请输入日期:");
	scanf("%d%*c%d%*c%d", &year, &month, &day);//这里将 - 换成 %*c
	printf("%d/ %d /%d", year, month, day);
	return 0;
}

输入后得到的输出结果如下:
在这里插入图片描述
上面程序的%*c就是在占位符的百分号后面,加⼊了赋值忽略符 ,表示这个占位符(%c)没有对应的变量,解读后不必返回。ps:这里使用%c是因为原来的符号(-)属于字符,所以我们在使用赋值忽略符时选择它。
以上就是本次分享回顾的知识点啦~虽然这些知识点之前也学过了一遍,但是再次回顾依旧感觉收获满满。路漫漫其修远兮,加油加油加油!

  • 34
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值