目录
'scanf' 和 'printf' 是C语言中的两个标准库函数,用于输入和输出。'<stdio.h>' 头文件包含了 C 语言标准库中有关输入和输出的函数声明。因此,在你使用 'printf'
和 'scanf'
函数之前要包含这个头文件。
一、printf
'printf'函数用于将格式化的数据输出到标准输出流(通常是屏幕)。它名字里面的 f 代表 format (格式化),表示可以定制输出文本的格式。 它允许程序员根据格式化字符串指定的格式将数据输出到控制台或文件中。
1.1 基本用法
#include <stdio.h>
int main()
{
printf("hello world!\n");
return 0;
}
上面的代码执行结果为在屏幕上输出一行文字“hello world”。‘\n’起到换行的作用
注意:printf() 是在标准库的头⽂件 stdio.h 定义的。使用这个函数之前,必须在源码⽂件头部引⼊这 个头文件。
1.2 占位符
printf() 可以在输出文本中指定占位符。 所谓 “占位符”,就是这个位置可以用其他值代入。
#include <stdio.h>
int main()
{
printf("There are %d students",6);
return 0;
}
%c :字符%d :⼗进制整数%f :小数(包含 float 类型和 double 类型)%p :指针%s :字符串%u :无符号整数(unsigned int)%zd : size_t 类型%% :输出⼀个百分号
输出文本里面可以使用多个占位符
1.3 输出格式
1.3.1 限定宽度
1.3.2 总是显示正负号
1.3.3 限定小数位数
上面示例中与限定宽度结合使用,表示输出的宽度为12,小数位数为2。
1.3.4 输出部分字符串
二、scanf
'scanf'
函数是 C 语言标准库中的一个函数,用于从标准输入流(通常是键盘)中读取格式化输入。它允许程序员根据格式化字符串指定的格式来读取输入,并将输入的值存储到指定的变量中。
2.1 基本用法
scanf()函数的第⼀个参数是⼀个格式字符串,里面会放置占位符(与 printf() 的占位符基本⼀致),告诉编译器如何解读用户的输入,需要提取的数据是什么类型。这是因为 C 语言的数据都是有类型的, scanf() 必须提前知道用户输入的数据类型,才能处理数据。它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。上面示例中, scanf() 的第⼀个参数 %d ,表示用户输入的应该是⼀个整数。 %d 就是⼀个占位符, % 是占位符的标志, d 表示整数。第二个参数 &a 表示,将用户从键盘输入的整数存入变量a种。
注意: 变量前面必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,而是地址,即将变量 a 的地址指向用户输⼊的值。如果这里的变量是指针变量(比如字符串变量),那就不用加 & 运算符。
scanf("%d %f %c %s",&a,&b,&c,d);
103.14'w'"yunanbei"
上面示例中,用户分成四行输入,得到的结果与一行输入是完全⼀样的。每次按下回车键以后, scanf() 就会开始解读,如果第一行匹配第⼀个占位符,那么下次按下回车键时,就会从第二个占位符开始解读。 scanf() 处理用户输⼊的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。 解读用户输入时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为止。
示例代码
#include <stdio.h>
int main()
{
int x;
float y;
// ⽤⼾输⼊ " -13.45e12# 0"
scanf("%d", &x);
printf("%d\n", x);
scanf("%f", &y);
printf("%f\n", y);
return 0;
}
上面示例中, scanf() 读取用户输入时, %d 占位符会忽略起首的空格,从 - 处开始获取数据,读取到 -13 停下来 ,因为后面的 . 不属于整数的有效字符。这就是说,占位符 %d 会读到 -13 。 第二次调用scanf() 时,就会从上⼀次停止解读的地方,继续往下读取。这⼀次读取的首字符 是 . ,由于对应的占位符是 %f ,会读取到 .45e12 ,这是采用科学计数法的浮点数格式。后面的# 不属于浮点数的有效字符,所以会停在这里。
2.2 scanf的返回值
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
float f = 0.0f;
int r = scanf("%d %d %f", &a, &b, &f);
printf("a=%d b=%d f=%f\n", a, b, f);
printf("r = %d\n", r);
return 0;
}
测试1:正常输入三个数字。r是3,表示正确读取了3个数值。测试2:输⼊2个数后,按 ctrl+z ,提前结束输入。r是2,表示正确读取了2个数值。
2.3 占位符
%c: 字符%d: 整数%f:float类型浮点数%lf: double类型浮点数%Lf: long double 类型浮点数。%s: 字符串%[] :在方括号中指定⼀组匹配的字符(比如 %[0-9] ),遇到不在集合之中的字符,匹配将会停止。
上面所有占位符之中,除了%c以外,都会自动忽略起首的空白字符。%c 不忽略空白字符,总是返回当前第⼀个字符,无论该字符是否为空格。 如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上一个空格,表示跳过零个或多个空白字符。
下面要特别说⼀下占位符 %s ,它其实不能简单地等同于字符串。它的规则是,从当前第⼀个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。因为 %s 不会包含空白字符,所以无法用来读取多个单词,除非多个 %s ⼀起使用。这也意味着, scanf() 不适合读取可能包含空格的字符串,比如书名或歌曲名。另外, scanf() 遇到 %s 占位符,会在字符串变量末尾存储⼀个空字符 \0 。scanf() 将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时, 很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用 %s 占位符时,应该指定读⼊字符串的最长长度,即写成 %[m]s ,其中的 [m] 是⼀个整数,表示读取字符串的最大长度,后面的字符将被丢弃。
测试:输入" hello world",该字符串前面有两个空格,并没有读入,hello与world之间也有空格,scanf跳过了前面两个空格,遇到空白字符(空格)结束了,所以输出结果为hello
s是一个长度为12的字符数组, scanf() 的占位符 %5s 表示最多读取用户输入的5个字符,后面的字符将被丢弃,这样就不会有数组溢出的风险了。
2.4 赋值忽略符
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d-%d-%d", &year, &month, &day);
printf("%d %d %d\n", year, month, day);
return 0;
}
只要把 * 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d%*c%d%*c%d", &year, &month, &day);
return 0;
}
2.5 连续多组输入
有的时候我们需要连续多组或者循环输入,这种情况在在线OJ题中经常出现。前面我们提到scanf() 的返回值是⼀个整数,表示成功读取的变量个数。 如果没有读取任何项,或者匹配失败,则返回 0 。如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF(-1)。
代码1:
#include <stdio.h>
int main()
{
int a = 0, b = 0, c = 0;
while (scanf("%d %d", &a, &b) == 2) //如果正确输入两个数返回2满足条件,循环继续,否则跳出循环
{
c = a + b;
printf("%d\n", c);
}
return 0;
}
代码2:
#include <stdio.h>
int main()
{
int a = 0, b = 0,c = 0;
while (scanf("%d %d", &a, &b) != EOF)
{
c = a + b;
printf("%d\n", c);
}
return 0;
}
2.6 scanf函数在VS编译器不安全报错问题
这个问题,我在之前的博客中有详细介绍,感兴趣的可以参考了解一下
完