C语言scanf()和printf()函数详解
C语言scanf()和printf()函数详解
C语言中的scanf()和printf()函数是输入输出操作的基础,掌握它们的使用方法对于编程学习至关重要。本文将详细介绍这两个函数的功能、参数以及各种应用场景,通过具体的代码示例帮助读者深入理解其用法。
一、printf
1.基础用法
printf()
的作用是将参数文本输出到屏幕。
print
是打印的意思,而f
是format
(格式化)的简写,表示可以制定输出文本的格式。printf()
不会在行尾自动添加换行符\n
,运行结束后,光标会停留在输出结束的地方。printf()
需要包含头文件<stdio.h>
。
2.占位符
占位符的作用是在输出文本中预留位置,以便用其他值代入。
- 格式:
%
+ 占位符的类型 - 特点:输出文本里可以使用多个占位符,且
printf()
参数与占位符是一一对应的。如果有n个占位符,那么printf()
里的参数就有n+1个,这里的加1表示用来放置占位符的字符串。
示例:
printf("%d个星期有%d天,其中我最爱%s", 1, 7, "星期六");
// 这里有3个占位符,即要有4个参数
3.占位符列表
常用的占位符包括:
%c
: 字符%d
: 十进制整数%f
: 小数(float)%lf
: 小数(double)%s
: 字符串%hu
: unsigned short int 类型%hd
: 十进制 short int 类型%ld
: 十进制 long int 类型%lu
: unsigned long int 类型%Lf
: long double 类型浮点数%p
: 指针(用来打印地址)%u
: unsigned int 类型%zd
: size_t类型
4.限定宽度
printf()
允许限定占位符的最小宽度。
4.1 整数
如:%6d
,该占位符宽度至少为6位,若不满,则在前面添加空格。
示例:
#include <stdio.h>
int main() {
printf("%6d\n", 1234);
printf("%6d\n", 1234567);
return 0;
}
输出结果:
4.2 小数
同理,这对小数也适用,但要注意小数的默认显示精度是小数点的后六位,加上小数点,就已经占7位。
如:%9f
,减去7,这整数部分至少有2位。
示例:
#include <stdio.h>
int main() {
printf("%9f\n", 1.234);
printf("%9f\n", 100.234);
return 0;
}
输出结果:
5.限定小数位数
小数点后的位数也可以限制。
如:%.3f
,限制小数点后面输出3位。
示例:
#include <stdio.h>
int main() {
printf("%.3f", 1.2);
printf("%.4f", 1.2);
return 0;
}
输出结果:
限定宽度和限定小数位数可以结合使用,且最小宽度和小数位数这两个限定值,都可以用*
来代替,通过printf()
的参数传入。
如:%*.*f
示例:
#include <stdio.h>
int main() {
printf("%*.*f\n", 8, 4, 1.234);
printf("%*.*f\n", 8, 4, 100.234);
return 0;
}
输出结果:
6.输出部分字符串
如果只想输出字符串的前几位,可以使用该方法。
如:%.4s
,表示只输出该字符串的前4个。
示例:
#include <stdio.h>
int main() {
printf("%s\n", "abcdefg");
printf("%.4s\n", "abcdefg");
return 0;
}
输出结果:
7.显示正负号
正数前是不会显示+
号的,想要显示,只需在占位符的%
后加个+
就行。
如:%+d
示例:
#include <stdio.h>
int main() {
printf("%+d\n", 3);
printf("%+d\n", -3);
return 0;
}
输出结果:
二、scanf
1.基础用法
scanf()
的作用是给变量输入值。
scanf()
函数用于读取用户的键盘输入,且需要包含头文件<stdio.h>
。scanf()
的第一个参数是格式字符串,用来放置占位符,这和printf()
一样。scanf()
后面的每个参数前需要加个&
运算符,因为scanf()
传递的不是值,而是地址,即将变量的地址指向用户输入的值。但如果参数变量是指针变量,那就不用加&
运算符。scanf()
在处理数值位占符时,会自动过滤空白字符,包括空格、制表符、换行符等。所以用户输入的数据之间,用一个或多个空格不影响scanf()
解读数据。另外,用户使用回车键,将输入分成几行,也不影响解读。
示例:
#include <stdio.h>
int main() {
int a = 0;
int b = 0;
int c = 0;
printf("请输入3个整数\n");
scanf("%d%d%d", &a, &b, &c);
printf("输出:%d%d%d", a, b, c);
return 0;
}
输入输出结果:
scanf()
处理用户输入的原理是:
- 用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。
- 解读用户的输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存为止,或者读完缓存,或者遇到第一个不符合条件的字符为止。
示例:
#include <stdio.h>
int main() {
int a = 0;
float b = 0.0f;
printf("输入:\n");
scanf("%d", &a);
printf("输出:%d\n", a);
scanf("%f", &b);
printf("输出:%f", b);
return 0;
}
输入输出结果:
第一个scanf()
读取的是整数,所以只能读取到3
第二个scanf()
读取的是小数,所以从.
开始读取,直到5
,@
不符合条件
上面的代码还可以合着写:
#include <stdio.h>
int main() {
int a = 0;
float b = 0;
printf("输入:\n");
scanf("%d%f", &a, &b);
printf("输出:%d\n", a);
printf("输出:%f", b);
return 0;
}
结果如同:
2.scanf的返回值
scanf()
的返回值是一个整数,表示成功读取的变量个数。
- 如果没有读取任何项,或者匹配失败,则返回0。
- 如果在成功读取任何数之前,发生了读取错误或者遇到读取到文件结尾,则返回常量EOF(-1)。
- 通常会用
scanf()
的返回值来判断读取是否正确。
EOF:是end of file 的简写。
示例:
#include <stdio.h>
int main() {
int a = 0;
float b = 0.0f;
int c = 0;
printf("输入:\n");
int r = scanf("%d%f%d", &a, &b, &c);
printf("输出的数:%d %f %d\n", a, b, c);
printf("成功读取的个数:%d\n", r);
return 0;
}
输出结果:
注:在VS2022中, 输入三个ctrl+Z,会出现-1,其它的编译器应该一次就可以。
3.占位符
与printf()
的占位符基本一致:
%c
: 字符%d
: 整数%f
: float%lf
: double%Lf
: long double%s
: 字符串%[ ]
: 在括号内指定一组匹配的字符( 比如:%[0-9]
),遇到不在集合之的字符,匹配将会停止
特点:
- 除了
%c
以外,都会自动忽略起首的空白字符。若要强制跳过字符前的空白字符,可写成scanf(" %c",&c);
,即%c
前加一个空格,表示跳过零个或多个空白字符。 %s
不等同于字符串,它的规则是从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。scanf()
在将字符串读入字符数组时,不会检测字符串是否会超过数组长度,所以在使用%s
占位符时,用%[ m ]s
,限制字符串的最大长度,如:%3s
。
示例1:
#include <stdio.h>
int main() {
char c = 0;
printf("输入:\n");
scanf("%c", &c);
printf("输出的数:%c\n", c);
return 0;
}
若起首有空白字符,那输出结果:
因为%c
无法忽略起首的空白字符
示例2:
将%c
前加个空格:
#include <stdio.h>
int main() {
char c = 0;
printf("输入:\n");
scanf(" %c", &c);
printf("输出的数:%c\n", c);
return 0;
}
输出结果:
示例3:
#include <stdio.h>
int main() {
char arr[3] = {0};
printf("输入:\n");
scanf("%s", arr); //数组名是地址,不用加&
printf("输出的数:%s\n", arr);
return 0;
}
当输入的内容超过3个字符,就会发生报错,很不安全。如下:
所以我们要%3s
来限制,最多读取用户输入的第3个字符。
4.赋值忽略符
作用:用户的输入可能因为不符合预定的格式,从而scanf()
解析数据就会失败,而它可以避免发生此类情况。
示例:
#include <stdio.h>
int main() {
int year = 0;
int month = 0;
int day = 0;
printf("输入日期:\n");
scanf("%d-%d-%d", &year, &month, &day);
printf("输出日期:%d %d %d\n", year, month, day);
return 0;
}
如果按照格式来,结果:
但不按照格式来,结果:
因此我们要学会用赋值忽略符。
使用方法:将*
加在任何占位符的百分号(%)后面,该占位符就不会返回值,解析后将被丢弃。
如下,就是将-
换成%*c
:
#include <stdio.h>
int main() {
int year = 0;
int month = 0;
int day = 0;
printf("输入日期:\n");
scanf("%d%*c%d%*c%d", &year, &month, &day);
printf("输出日期:%d %d %d\n", year, month, day);
return 0;
}
这样上面的两中输入内容都可以正确解析。
5.消除scanf()警告
当我们在VS2022用scanf()
时,会出现下面的警告
它的意思是说:该scanf()
可能不安全,建议使用scanf_s()
,若想让该警告失效,要使用_CRT_SECURE_NO_WARNINGS
这里说明一下不使用scanf_s()
的原因:因为scanf_s()
不是C语言提供的,而是VS2022提供的,因此它无法在其他编译器上使用。若使用,代码就不跨平台了。
解决方法:在第一行定义#define _CRT_SECURE_NO_WARNINGS 1
(注意define
后要加一个空格)
当然若每次建立一个项目都要打印一行这代码,那也忒麻烦了。有一个一劳永逸的办法,这里我就不说明了,下次我单独出一篇。