教你一招如何半小时把C语言的 scanf printf sscanf sprintf fscanf fprintf wscanf wprintf 玩出花来

本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!
在这里插入图片描述

前言

相比友友们都接触 scanf printf
同时小编在 《用C语言了解文件那些下 ‘流‘ 事》 (http://t.csdnimg.cn/1s3Ek)的那篇文章中也详细介绍过fprintf 与 fscanf 的各种细节。 😍 😍 😍
而在本篇文章中小编会带着大家一起来梳理我们庞大的且常用的 格式化输入输出 的大家庭。 💖 💖 💖

目录

  1. scanf 与 printf
  2. sscanf 与 sprintf
  3. fscanf 与 fprintf
  4. wscanf 与 wprintf 💕 💕 💕

一.scanf 与 printf

1. printf

printf() 的作用是将参数文本输出到屏幕。它名字里面的 f 代表 format (格式化),表示可以定制输出文本的格式。

<1>. printf 简介

在这里插入图片描述
返回类型: int (返回的是输出打印的字符个数)
参数:可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:从 格式化参数中 打印到 标准输出流(屏幕)

<2>. 栗子说明

#include<stdio.h>

int main(void)
{
	printf("Hello\nWorld\n");
	printf("Hello\n");
	printf("World\n");
	return 0;
}

上面命令会在屏幕上输出一行文字 “Hello World”
printf() 不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行。

为了让光标移到下一行的开头,可以在输出文本的结尾,添加一个换行符 \n

在这里插入图片描述

鱼式疯言

printf() 是在标准库的头文件 <stdio.h> 定义的。

使用这个函数之前,必须在源码文件头部引入这个头文件。

<3>.占位符(可变参数)

printf() 可以在输出文本中指定占位符。
所谓 “占位符”,就是这个位置可以用其他值代入。

#include<stdio.h>

// 输出 There are 3 apples

int main()
{
	printf("There are %d apples\n", 3);
	return 0;
}

在这里插入图片描述
这时爱发问的小爱同学又来特意问,这是咱们替换的🤔 🤔 🤔
怎么那么神奇呢 😲 😲 😲
那么小编就为这位好学的同学解答吧 ! ! !
上面示例中, There are %d apples\n 是输出文本,里面的%d 就是占位符,表示这个位置要用其他值来替换。

占位符的第一个字符一律为百分号% ,第二个字符表示占位符的类型, %d 表示这里代入的值必须是一个整数。

printf() 的第二个参数就是替换占位符的值,上面的例子是整数 3 替换 %d

执行后的 输出结果 就是 There are 3 apples 。

<4>. 占位符列举

常用的占位符除了 %d ,还有 %s 表示代入的是字符串。

#include<stdio.h>


int main()
{
	printf("%s says it is %d o'clock\n", "lisi", 21);
	return 0;
}

在这里插入图片描述
上面示例中,输出文本%s says it is %d o’clock 有两个占位符
第一个是字符串占位符 %s
第二个是整数占位符 %d
分别对应printf() 的第二个参数 ( lisi )和第三个参数( 21 )。
执行后的输出就是 lisi says it is 21 o’clock 。

printf() 参数与占位符是一一对应关系,如果有n 个占位符
printf() 的参数就应该有n +1 个。
如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。

像类似这些占位符在我们C语言中是很多的
小编还特意整理了一下常用的占位符,需要的宝子们可以自取哦 😊 😊 😊

%a :十六进制浮点数,字母输出为小写。
• %A :十六进制浮点数,字母输出为大写。
• %c :字符。
• %d :十进制整数。
• %e :使用科学计数法的浮点数,指数部分的e 为小写。
• %E :使用科学计数法的浮点数,指数部分的E 为大写。
• %i :整数,基本等同于%d 。
• %f :小数(包含float 类型和double 类型)。
• %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 类型。
• %% :输出一个百分号。

<5>. 限制整数宽度

printf() 允许限定占位符的最小宽度。

#include <stdio.h>
int main()
{
printf("%5d\n", 123); // 输出为 " 123"
return 0;
}

在这里插入图片描述
上面示例中, %5d 表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。
输出的值默认是右对齐,即输出内容前面会有空格;
如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的% 的后面插入一个 - 号。

#include <stdio.h>
int main()
{
	printf("%-5d**\n", 123); // 输出为 "123 "
	return 0;
}

在这里插入图片描述

上面示例中,输出内容123 的后面添加了空格。

<6>. 限制小数位数和宽度

// 输出为 " 0.50"
#include <stdio.h>
int main()
{
printf("%6.2f\n", 0.5);
return 0;
}

在这里插入图片描述
上面示例中, %6.2f 表示输出字符串最小宽度为6,小数位数为2 。所以,输出字符串的头部有两个空格。

鱼式疯言

大伙看累了吧,小编就传授大家一个绝招 💖 💖 💖
让友友们感受到写 printf 可以写的那么 丝滑

最小宽度和小数位数这两个限定值,还可以用 * 代替,通过 printf() 的参数传入。

#include <stdio.h>
int main()
{
printf("%*.*f\n", 6, 2, 0.5);
return 0;
}
// 等同于printf("%6.2f\n", 0.5);

在这里插入图片描述

上面示例中, %*.*f 的两个星号通过 printf() 的两个参数6 和2 传入。

鱼式疯言

关于 printf()这个输出函数
小编有几点心得想和大家分享

1.无占位符时,可变参数原样输出

2.有占位符时,先替换占位符,再原样输出

3.可变参数本质上是字符串,不管可变参数写的是啥,都会以字符的形式输出

4.字符串的本质也是从首字符的地址开始输出的,直到遇到 ‘\0’

5.如果宝子们只想普通输出一个数据到屏幕,调用 printf() 是再合适不过了

如果宝子们理解了我以上5个总结,就能明白小编下面的代码了🤔 🤔 🤔

#include <stdio.h>
int main()
{
	char arr[20] = "abcdef";
	printf("abcdef\n");
	
	printf("%s\n", arr);
	
	printf(arr);
}

在这里插入图片描述

2. scanf

当我们有了变量,我们需要给变量输入值就可以使用 scanf 函数
如果需要将变量的值输出在屏幕上的时候可以使用 prinf 函数,下面看一个例子:

#include <stdio.h>
int main()
{
	int score = 0;
	printf("请输入成绩:");

		scanf("%d", &score);
	printf("成绩是:%d\n", score);
	return 0;
}

在这里插入图片描述

<1>. scanf 的简介

返回类型: int (返回的是输入的字符个数)
参数:可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:从 标准输入流(键盘)存入数据

<2>. scanf 的单变量的使用

在这里插入图片描述
scanf() 函数用于读取用户的键盘输入。
程序运行到这个语句时,会停下来,等待用户从键盘输入。
用户输入数据、按下回车键后
scanf() 就会处理用户的输入,将其入变量。
它的原型定义在头文件stdio.h 。
scanf() 的语法跟printf() 类似

scanf(“%d”, &i);

它的第一个参数是一个格式字符串,里面会放置占位符(与printf()
的占位符基本一致),告诉编译器如何解读用户的输入,需要提取的数据是什么类型。

这是因为 C 语言的数据都是有类型的, scanf() 必须提前知道用户输入的数据类型,才能处理数据。
它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。
上面示例中, scanf() 的第一个参数%d ,表示用户输入的应该是一个整数。%d 就是一个占位符, % 是占位符的标志, d 表示整数。

第二个参数&i 表示,将用户从键盘输入的整数存入变量 i 。

友友们会不会觉得文字太文绉绉啦 😣 😣 😣
小编就画图演示下吧! ! !
在这里插入图片描述

鱼式疯言

突然发现小爱同学犯了一个大家都有可能犯的错误
忘记了 “&”
所以小编特别温馨提醒宝子们 ❤️ ❤️ ❤️

注意:变量前面必须加上& 运算符(指针变量除外),因为scanf() 传递的不是值

而是地址,即将变量i 的地址指向用户输入的值。

如果这里的变量是指针变量(比如字符串变量),那就不用加& 运算符。

如果宝子们想普通从键盘输入一个数据,调用 scanf()就再合适不过了

<2>. scanf 的多变量的使用

#include <stdio.h>
int main()
{
	int i = 0,j=0;
	float x = 0.0, y = 0.0;
	scanf("%d%d%f%f", &i, &j, &x, &y);
	printf("%d %d %f %f\n", i, j, x, y);
	return 0;
}

在这里插入图片描述

上面示例中,用户分成四行输入,得到的结果与一行输入是完全一样的。每次按下回车键以后,scanf() 就会开始解读。

如果第一行匹配第一个占位符,那么下次按下回车键时,就会从第二个占位符开始解读。

scanf() 处理用户输入的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。

解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。

<3>. 占位符的列举

关于 scanf() 占位符的列举 与 printf () 是一致的

小编在这里就不赘述啦啦啦啦啦 ! ! !
感兴趣的友友可以参考上面这些printf()的占位符进行学习哦😊 😊 😊

二. sscanf 与 sprintf

1.sprintf

<1>.sprintf 的简介

在这里插入图片描述
返回类型: int (返回的是输出到字符串的字符个数)
参数:可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:从 格式化参数中 输出打印到 字符指针(字符串)

<2>.栗子说明

//结构体类型声明
typedef struct Stu
{
	char name[20];
	int age;
	float soare;
}Stu;


#include<stdio.h>

int main()
{
	//结构体初始化
	Stu s = { "zhangsan",20,89.3f };
	
	//将数组置为0
	char arr[30] = { 0 };

	// sprintf 可以将结构体数据里的任何数据转化为字符串
	// 字符串再放入arr中
	sprintf(arr, "%s %d %f", s.name, s.age, s.soare);
	
	//验证 arr 是否被传入
	printf("%s\n",arr);
	return 0;
}

在这里插入图片描述
以上栗子充分说明了咱的 sprintf 是可以把任何数据转化为字符串
从而放入我们的字符数组中

鱼式疯言

是不是宝子们还是有的不理解呢 💕 💕 💕

不妨和小编这样思考一下,原先我们 printf() 是 将我们的内容输出到屏幕上

现在我们用 fprinf()仅仅只是把输出对象由屏幕改成了我们的字符指针(字符串)

如果宝子们想输出一个数据到字符数组中,调用 sprintf() 就再合适不过了

2.sscanf

<1>.sscanf 的简介

在这里插入图片描述

返回类型: int (返回的是输入的字符个数)
参数:可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:从 字符指针(字符串)存入相对应的类型变量中

<2>. 举个栗子

//printf与sscanf
typedef struct Stu
{
	char name[20];
	int age;
	float soare;
}Stu;


#include<stdio.h>

int main()
{
	//结构体初始化
	Stu s = { "zhangsan",20,89.3f };
	
	//将数组置为0
	char arr[30] = { 0 };

	// sprintf 可以将结构体数据里的任何数据转化为字符串
	// 字符串再放入arr中
	sprintf(arr, "%s %d %f", s.name, s.age, s.soare);
	
	//验证 arr 是否被传入
	printf("%s\n",arr);
	
	//再初始化一个置为0的结构体
	Stu u = { 0 };

	// sscanf 将arr中字符串按照占位符 转化为对应的数据类型
	// 转化后的数据放入对应的结构体成员中
	sscanf(arr, "%s%d%f", u.name, &u.age, &u.soare);

	//验证结构体成员的数据是否被放入
	printf("%s %d %f\n", u.name, u.age, u.soare);
	
	return 0;
}

在这里插入图片描述

鱼式疯言

首先小编说说对于sscanf()我个人的理解吧 😁 😁 😁

1.第一点也是最重要的一点就是:

千万 千万 千万不要忘记取地址 “&”

2.与 scanf()相比较, scanf()是从键盘输入到屏幕上

那我们的 输入对象就由我们的 键盘 变成 字符指针(字符串)

我们的 接收对象 由我们的 屏幕 变成了 各种类型的变量

3.无论是输出还是输入,小编都建议咱宝子们一定要 一 一 应对,空格也要 一 一 对应,否则就有可能有问题呢

  1. 如果宝子们想字符串或字符指针中输入一个数据,调用 sscanf() 是再合适不过了

三. fscanf 与 fprintf

友友们是不是觉得这个函数很眼熟啊,似乎在哪里见过这俩小玩意 😃 😃 😃
没错,这就是我们前几期文章写过的文件操作处理的相关的俩函数。

关于什么是文件“流”,文件“流”怎么打开的,怎么关闭的 ? ? ?

具体文件操作还来没及理解的宝子们可以参考小编的 《用C语言了解文件那些下 ‘流‘
事》
[http://t.csdnimg.cn/k2rVO] 结合起来学习效果更佳哦 💖 💖 💖

今天小编就再带着宝子们在复习回顾一下我们的 fscanf() ,fprintf()

1.fprintf

<1>. fprintf 的简介

在这里插入图片描述

宝子们可以观察两者的参数的异同 🤔 🤔 🤔

在这里插入图片描述

返回类型:int(输出到 “流” 的字符个数)
参数:“流”,可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:将类型变量参数的 数据 输出写入到 “流”

<2>. 举个栗子

在这里插入图片描述

//fprintf_test

typedef struct Stu
{
	char name[20];
	int age;
	float soare;
}Stu;


#include<stdio.h>

int main()
{
	Stu s = { "zhangsan",20,89.3f };
	
	//写入文件
	//又称输出到文件中
	FILE* pfwrite = fopen("data.txt", "w");
	if (pfwrite==NULL)
	{
		perror("fopen()->pfwrite");
		return 1;
	}

	//结构体输出到文件流中
	fprintf(pfwrite,"%s %d %f", s.name, s.age, s.soare);


	return 0;
}

在这里插入图片描述

鱼式疯言

小编有言曰:

1.对比我们最原始的 printf()最本质的区别就在于,我们的输出对象由我们的屏幕变成了我们的文件流

2.一般我们还要判断我们的文件“流”指针是否为 NULL ,一旦为 NULL 是无法对该文件进行操作的

3.如果宝子们想输出一个数据到文件中,调用 fprintf() 是再合适不过了

2. fscanf

<1>. fscanf 的简介

返回类型:int(从流中读取到的字符个数)
参数: “流”,可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:从 “流” 将类型变量参数的 数据 输出

在这里插入图片描述

宝子们可以观察两者的参数的异同 🤔 🤔 🤔

在这里插入图片描述

<2>. 举个栗子

在这里插入图片描述

//fscanf_test
#include<stdio.h>

typedef struct Stu
{
	char name[20];
	int age;
	float soare;
}Stu;


int main()
{
	Stu u = { 0 };
	
	//读取文件
	//又称从文件中输入到其他变量中
	FILE* pfread = fopen("data.txt", "r");
	if (pfread == NULL)
	{
		perror("fopen()->pfwrite");
		return 1;
	}

	//从文件中格式化输入到结构体成员
	fscanf(pfread, "%s %d %f", u.name, &(u.age), &(u.soare));
	
	//结构体输出到标准输出流中
	fprintf(stdout, "%s %d %f", u.name, u.age, u.soare);
	
	return 0;
}

在这里插入图片描述

鱼式疯言

友友们是不是和我一样都理解到了
与之我们的 scanf()对比

键盘 换成了文件“流”

其他依然 岁月如旧

温馨提示:不要忘记没有地址不要忘记带上 “&” 符哦 💕 💕 💕

四. wprintf与wscanf

1.wprinf

<1>. wprintf的简介

返回类型: int (返回的是输出打印的宽字符个数)
参数:可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:从 格式化参数中 打印到 标准输出流(屏幕)
在这里插入图片描述

宝子们可以观察两者的参数的异同 🤔 🤔 🤔
在这里插入图片描述

<2>. 输出单个宽字符

小爱同学很疑惑,啥叫 宽字符 呢 🤔 🤔 🤔
其实啊 😁 😁 😁
在这里插入图片描述

在我们这里的字符占两个byte(字节),所以我们把他们称之为 宽字符

//wprintf_test
//宽字符函数需要的头
#include<wchar.h>

//实现本地化的头文件
#include<locale.h>

int main()
{
	//实现本地化,可以输出空字符
	setlocale(LC_ALL, "");
	

	//输出单个宽字符
	wprintf(L"%lc\n", L'◆');
	wprintf(L"%lc\n", L'●');
	
	
	return 0;
}

在这里插入图片描述

鱼式疯言

这里小编要说明几点重要的细节

  1. 由我们的与我们的 printf() 对比 由输出普通字符变成输出我们的宽字符,还有形式上有区别,其他依然岁月如旧
  1. 要输入单个宽字符,需要 本地化,就是说输出它就需要移植到本地操作 setlocale(LC_ALL, “”) ,宝子们记住这条语句就好,具体细节比较多,日后小编再一 一讲解
  1. 本地化声明就需要我们的头文件 <locale.h>
  1. 要打印宽字符还需要注意我们的占位符和参数,这是与printf()形式不同,我们一般而言:L“%lc” 作为我们的可变参数,L‘●’ 作为我们的类型参数,L可是我们宽字符的标志哦,这点可不能少呢 😊 😊 😊
  1. 用我们的 wprintf() 打印宽字符时,需要引用我们的头文件 <wchar.h>
  1. 如果宝子们想输出一个宽字符到屏幕中,调用 wprintf() 是再合适不过了

<3>. 输出宽字符串

//wprintf_test
//宽字符函数需要的头

#include<wchar.h>
int main()
{
	//当我们输出宽字符串
	//此处不需要本地化

	//宽字符放在字符数组
	char arr1[80] = "●◆●◆●●●●★◆";

	// wprintf 打印
	wprintf(L"%hs\n", arr1);
	
	//printf 也可打印
	printf("%s", arr1);
	return 0;
}

在这里插入图片描述

鱼式疯言

宝子们是否也看到了,我们的宽字符串的输出就没有宽字符那么严格了

首先我们不需要 本地化 和对应的本地化 头文件

其次我们原先的 L“%lc” 换成我们的 L“%hs”

最后就是无论我们的 wprintf() 还是我们的 printf() 输出宽字符串
小编认为竟然我们是 宽字符串 输出,建议最好还是用标准的 wprintf() 输出
当然友友们觉得哪个更好,就用哪个哦,两者都是不错哒 💕 💕 💕

2.wscanf

<1>.wscanf 的简介

在这里插入图片描述

宝子们可以观察两者的参数的异同 🤔 🤔 🤔

在这里插入图片描述
返回类型: int (返回的是输入的宽字符个数)
参数:可变参数 (逗号坐边) 与 类型变量参数 (逗号右边)
作用:从 标准输入流(键盘)存入数据

<2>. 举个栗子


#include<wchar.h>
int main()
{

	char arr[30] = { 0 };
	wscanf(L"%hs", arr);

	wprintf(L"%hs\n",arr);

	return 0;
}

在这里插入图片描述

鱼式疯言

最终我们用到的 wscanf 格式是与 wprintf 格式是一致哒
但小编建议在使用 wscanf 最好不要加上 ‘\n’ ,否则很有可能会容易出错呢 ❤️ ❤️ ❤️
虽然友友应该知道普通scanf()的输入的宽字符串,但我们宽字符串的输入,小编还是建议选这个使用呢 😎 😎 😎

总结

相信圆满读完小编文章的友友们一定很硕果累累吧,小编也是这样想哒 😁 😁 😁
下面小编将给本篇文章最后来收个小尾巴 💕 💕 💕
scanf 与 printf :我们详细讲解了printf的各种输出的形式和宽度,scanf强调了 “&” 的重要性
sscanf 与 sprintf :我们从键盘到我们的字符指针(字符串)的迁移
fscanf 与 fprintf:同时文件的格式化输入和输出也少不了他们俩
wscanf 与 wprintf:最终的宽字符我们更贴切的体会的宽字符与普通格式化输入与输出的不同之处 ❤️ ❤️ ❤️

如果觉得小编写的还不错的咱可支持三关下,不妥当的咱评论区指正

希望我的文章能给各位家人们带来哪怕一点点的收获就是 小编创作 的最大动力 💖 💖 💖

在这里插入图片描述

  • 69
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 40
    评论
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邂逅岁月

感谢干爹的超能力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值