scanf
和 printf
都是系统自带的函数,在头文件 stdio.h
中定义的。我们要使用 printf
和 scanf
,就必须先让编译器理解它们 。用 #include
命令,我们就可以调用文件 stdio.h
的函数scanf
和 printf
。
stdio.h
名为标准输入输出文件,源于standard input & output。而.h为头文件的后缀。
printf
printf
的作用是将参数文本输出到屏幕。它名字里的 f
代表 format
(格式化),表示可以定制输出文本的内容。
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
上面命令会在屏幕上输出一行“Hello World”。
运行结束后,光标就停留在输出结束的地方,不会自动换行。
为了让鼠标的光标移到下一行的开头,我们可以在输出文本的结尾,添加一个换行符 \n
.
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
printf
可以在输出文本中指定占位符。
占位符的位置可以被其他值代入。
printf
的参数与占位符是一一对应关系。如果有n个占位符, printf
的参数就有n+1个,第一个参数为格式字符串,用于放置占位符。如果参数少于对应的占位符, printf
可能会输出内存中的任意值。
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 类型。%%
:输出⼀个百分号。printf
可以定制占位符的输出格式。
printf
允许限定占位符的最小宽度。
#include<stdio.h>
int main()
{
printf("%5d", 123);//输出结果为“ 123”
return 0;
}
%5d
表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。
输出的值默认为右对齐,即输出内容前面会有空格;如果希望改成左对齐,可以在占位符的 %
的后面插入一个 -
。
#include<stdio.h>
int main()
{
printf("%-5d", 123);//输出结果为“123 ”
return 0;
}
对于小数,这个限定符会限制所有数字的最小显示宽度。
#include<stdio.h>
int main()
{
printf("%12f", 123.4567);//输出结果为“ 123.456700”
return 0;
}
%12f
表示输出的浮点数至少要占据12位。由于小数的默认显示精度为小数点后6位,所以输出结果的头部会添加2个空格
一般来说, printf
不对正数显示正号,只对负数显示负号。如果想在正数也输入正号,可以在占位符的 %
后面加一个 +
。
#include<stdio.h>
int main()
{
printf("%+d", 12);//输出 +12
printf("%+d", -12);//输出 -12
return 0;
}
+
对正负值没有影响
输出小数时,有时候希望能限制小数的位数。
#include<Stdio.h>
int main()
{
printf("%.2f", 0.5);//输出为 0.50
return 0;
}
希望小数后面只保留两位小数,占位符写成 %.2f
#include<Stdio.h>
int main()
{
printf("%.2f", 123.456);//输出为 123.46
return 0;
}
限定的位数小于实际的最小位数,会四舍五入。
限定小数位数可以和限定宽度占位符一起使用。
#include<stdio.h>
int main()
{
printf("**%6.2f**", 0.5);//输出为" 0.50"
return 0;
}
限定最小宽度和和小数位数都可以用*代替,通过printf的参数传入。
#include<stdio.h>
int main()
{
printf("%*.*f", 6, 3, 1.23);//输出为" 1.230"
//等同于printf("%6.3f", 1.23)
return 0;
}
%s
占位符用来输出字符串,默认是全部输出。如果只想输出开头部分,那么可以用 %.[m]f
指定输出的长度。其中 [m]
代表一个数字,表示所需要输出的长度。
#include<stdio.h>
int main()
{
printf("%.5s", "hello world");//输出"hello"
return 0;
}
scanf
scanf
用于读取用户键盘的输出。
#include<stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
printf("%d", a);
return 0;
}
它的第一个参数为格式字符串,里面放置占位符,用于表明需要输入的数据类型。其余参数用于存放用户输入符变量。格式字符串中有多少的占位符,就有多少个变量。
输入多个变量:
scanf("%d%d%f%f", &i, &j, &x, &y);
scanf
处理字符占位符的时候,会自动过滤空白字符,包括空格,制表符,换行符等。
用户使用回车键将输入分成几部分,也不影响解读。
scanf
处理数据的原理是:用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。
解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符。
#include<Stdio.h>
int main()
{
int x = 0;
float y = 0;
//用户输入" -13.45e12# 0"
scanf("%d", &x);
printf("%d\n", x);//输出-13
scanf("%f", &y);
printf("%f", y);//输出449999994880.000000
return 0;
}
scanf
读取用户输入时, %d
会忽略起首的空格,从 -
处开始获取数据,读到 -13
为止,因为后面的 .
对于 %d
不属于有效字符。
第二次调用 scanf
,会从上一次停止解读的地方继续往下读取。此时读取的第一个字符为 .
,由于对应的占位符为 %f
,因此读取的字符串为 .45e12
,是0.45×10¹²次的意思。
scanf
的返回值scanf
的返回值是一个整数,表示成功读取的变量个数。
如果没有读取任何项,或者匹配失败,则返回 0
。如果在成功读取任何数据之前,发生的读取错误或者读取到文件结尾,则返回EOF(end of file),即-1 。
#include<stdio.h>
int main()
{
int a = 0;
int b = 0;
float c = 0.0f;
int r = scanf("%d %d %d", &a, &b, &c);
printf("%d %d %d\n", a, b, c);
printf("%d", r);//输出3
return 0;
}
如果输入两个数以后,按 ctrl+z
,提前结束输入:
在VS环境中按三次ctrl+z
(其他编译器中一次即可),结束输入,我们可以看到r是2,即正确读取两个数据。
如果一个数字都不输入,直接按三次ctrl+z
,输出的r是-1,即EOF。
scanf
中的占位符与 printf
基本一致。
常见占位符如下:
%c
:字符。%d
:整数。%f
: float 类型浮点数。%lf
: double 类型浮点数。%Lf
: long double 类型浮点数。%s
:字符串。%[]
:在⽅括号中指定⼀组匹配的字符(⽐如 %[0-9] ),遇到不在集合之中的字符,匹配将会上面所有的占位符中,除了 %c
以外,都会自动忽略起首的空白字符。
%c
不忽略空白字符,总是返回当前的起一个字符,无论该字符是否为空格。
如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &a)
,即在 %c
前加上一个空格,表示跳过零个或多个空白字符。
%s
并不能简单的等同于字符串。它的规则是:从当前的第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符)为止,并在字符串最后存储一个空字符 \0
。
因此 %s
不适合读取可能包含空格的字符串。
scanf
将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,在储存字符串时,可能会超出数组的边界。因此,使用 %s
时,可以指定读入字符串的最长长度,即写成 %[m]s
,其中 [m]
是一个整数,表示读取字符串的最长长度,后面的字符将被丢弃。
#include<Stdio.h>
int main()
{
char arr[10];
scanf("%10s", arr);
return 0;
}
%10s
表示最多读取10个字符,给 \0
留空间
有时,用户的输入可能不符合预定的格式。
#include<stdio.h>
int main()
{
int year = 0;
int mouth = 0;
int day = 0;
scanf("%d-%d-%d", &year, &mouth, &day);
printf("%d %d %D", year, mouth, day);
return 0;
}
如果输入2021-1-01, scanf
就会正确解读出年、月、日。但如果输入其他格式,如2021/1/01, scanf
就会即系数据失败。
因此, scanf
提供了一个**赋值忽略符 *
,**只要把 *
加在任意占位符的%后面,该占位符就不会返回值,解析后就会被丢弃。
#include<stdio.h>
int main()
{
int year = 0;
int mouth = 0;
int day = 0;
scanf("%d%*c%d%*c%d", &year, &mouth, &day);
printf("%d %d %d", year, mouth, day);
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容