前言
相信大家在学习期间或多或少都会接触到算法题目,而这时候scanf与printf这两个函数就会显得尤为重要了,如果scanf与printf用不好的话,那我相信写算法题目一定是会非常痛苦的。那么好,就让我们一起来学习一下这两个函数把!
printf 详解
1. 基本用法
printf () 的作用在于将参数文本输出到终端。其中末尾的f 表示格式化,可以指定输出文本的格式
int main()
{
// 最简单的使用方法,直接传递参数
printf("1111111\n");
return 0;
}
2. 占位符
占位符在scanf与printf中是一个非常重要的概念。printf可以在输出⽂本中指定占位符,等待数据代替占位符输出。
占位符的特点:占位符的第一个字符一律为百分号(%),第二个字符表示占位符的类型
printf() 中可以在输出文本中可以指定N个占位符,等待N个指定的值输入进来
printf() 中的参数与占位符是一一对应的,如果有N个占位符,那么printf() 参数也应该有N个
int main()
{
//特点:占位符的第一个字符一律为百分号(% ),第二个字符表示占位符的类型
//Printf() 中可以在输出文本中指定占位符,等待其他指定的值输入进来
printf("你的期末考试成绩是%d\n", 100);
printf("你的期末考试成绩是%d\n", 10);
//Printf() 中可以在输出文本中可以指定N个占位符,等待N个指定的值输入进来
printf("你的期末考试成绩是%d,你的语文成绩是%d,你的数学成绩是%d\n", 10, 1, 10);
return 0;
}
那么这里就要介绍一下C语言中占位符的种类了:
类型 | 介绍 |
---|---|
%a |
⼗六进制浮点数,字⺟输出为⼩写
|
%A | ⼗六进制浮点数,字⺟输出为⼤写 |
%c | 字符 |
%d | ⼗进制整数 // int |
%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 类型 |
%% | 输出⼀个百分号 |
虽然C语言中的占位符很多,但是我们在日常使用中也不过就那其中几个,无非是:
类型 | 介绍 |
---|---|
%c |
字符
|
%d |
⼗进制整数 // int
|
%f |
⼩数(包含 float 类型和 double 类型)
|
%ld |
⼗进制 long int 类型
|
%p |
指针(⽤来打印地址)
|
%s |
字符串
|
%u |
⽆符号整数(unsigned int)
|
%x |
⼗六进制整数
|
3. 输出格式
printf的输出方式可以被定制
3.1 限定输出宽度
printf允许限定占位符的最小宽度,需要在占位符(%)后加上一个限定宽度的数字(N)
如果输出的内容不满N位,对应的值的前⾯会添加空格。输出的值默认是右对⻬
int main()
{
//Printf() 允许限定占位符的最小宽度
char str[] = "abcdefg";
printf("%5sefg\n", str);// 输出为" abcd"
// %5s 表示这个占位符的最小宽度为5,如果不足5位,会使用空格代替
return 0;
}
如果希望改成左对⻬,可以在占位符的 % 的后⾯插⼊⼀个 - 号
int main()
{
//Printf() 允许限定占位符的最小宽度
char str[] = "abcdefg";
printf("%5sefg\n", str);// 输出为" abcd"
// %5s 表示这个占位符的最小宽度为5,如果不足5位,会使用空格代替
// 代替的空格默认是右对齐的,如果希望改变方向,需要在占位符%后加 -
printf("%-5sefg\n", str);// 输出为"abcd efg"
return 0;
}
3.2 总是显示正负号
默认情况下使用printf 输出数字不会显示+号,只会显示-号
当我们在占位符%后加 +,输出的正数前会带+号,负数还是-号
int main()
{
// 默认情况下使用printf 输出数字不会显示+号,只会显示-号。
// 当我们在占位符%后加 +,输出的正数前会带+号,负数还是-号
int num = 8;
int num2 = -8;
printf("%d\n", num); // 输出 8
printf("%+d\n", num); // 输出 +8
printf("%+d\n", num2); // 输出 -8
return 0;
}
3.3 限定小数位位数
在输出小数时,经常性的会有小数位数的要求,此时占位符的格式就可以写成 %.[N] lf 的形式来限定小数位数,N表示需要保留的小数位数
在截取小数位数时默认会进行四舍五入,如果小数位不足时会在后面补0
int main()
{
// 在输出小数时,经常性的会有小数位数的要求,此时占位符的格式就可以写成 %.[N] lf 的形式来限定小数位数,N表示需要保留的小数位数
// 在截取小数位数时默认会进行四舍五入,如果小数位不足时会在后面补0
double num3 = 3.1415926;
printf("%.2lf\n", num3); // 输出 3.14
printf("%.3lf\n", num3); // 输出 3.141
printf("%.4lf\n", num3); // 输出 3.1416
printf("%.12lf\n", num3); // 输出 3.141592600000
return 0;
}
当然限定小数位数与限定占位符最小宽度可以结合在一起使用
可以用 * 代替,通过参数传入进来
int main()
{
// 当然限定小数位数与限定占位符最小宽度可以结合在一起使用
double num = 3.14;
printf("%5.2lf\n", num); // 输出 " 3.14"
// 可以用 * 代替,通过参数传入进来
printf("%*.*lf\n", 5, 2, num);// 输出 " 3.14"
return 0;
}
3.4 限定字符串输出长度
%s占位符默认情况下会把所有字符全部输出。此时占位符的格式就可以写成 %.[N]s 的形式来限定输出的字符数量,N表示需要输出的字符数量
int main()
{
// %s占位符默认情况下会把所有字符全部输出。此时占位符的格式就可以写成 %.[N]s 的形式来限定输出的字符数量,N表示需要输出的字符数量
char str2[] = "qwertyuiop";
printf("%.1s\n", str2); // 输出 q
printf("%.2s\n", str2); // 输出 qw
printf("%.3s\n", str2); // 输出 qwe
return 0;
}
scanf 详解
1. 基本用法
Scanf函数用于读取用户在键盘上的输入,⽤⼾输⼊数据、按下回⻋键后, scanf 就会处理⽤⼾的输⼊,将其存⼊变量
Scanf函数与printf的语法十分相识,利用占位符代替用户输入进来的值,格式字符串⾥⾯有多少个占位符,就有多少个值等待输入
注意:变量前⾯必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,⽽是地址, 即将变量 i 的地址指向⽤⼾输⼊的值
如果这⾥的变量是指针变量(⽐如字符串变量),那就不⽤加 & 运算符
int main()
{
int num = 0;
int num2 = 0;
int num3 = 0;
// 从键盘中读取一个数放入进 num 中
scanf("%d", num); // error 变量前面必须要加上 & ,scanf() 传递的不是值,⽽是地址
scanf("%d", &num); // yes
// 下⾯是⼀次将键盘输⼊读⼊多个变量
scanf("%d %d %d", &num, &num2, &num3);
return 0;
}
scanf() 处理数值占位符时,会⾃动过滤空⽩字符,包括空格、制表符、换⾏符等
int main()
{
// Scanf()函数用于读取用户在键盘上的输入
int num1 = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
// scanf() 在处理占位符时,会自动过滤空白字符、空格、制表符、换行符等
scanf("%d %d %d %d", &num1, &num2, &num3, &num4);
// 用户输入
// 输入方式一:1 2 3 4
// 输入方式二:
// 1
// 2
// 3
// 4
// 输入方式三:
// 1 2
// 3 4
// 以上输入方式都是等价的,一样的
return 0;
}
2. scanf的返回值
scanf() 的返回值是⼀个整数,表⽰成功读取的变量个数,如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量 EOF
int main()
{
int num1 = 0;
int num2 = 0;
int num3 = 0;
// scanf() 的返回值是⼀个整数,表⽰成功读取的变量个数
int num = scanf("%d %d %d", &num1, &num2, &num3);
printf("%d\n", num); // 输出 3
return 0;
}
当我们在一些算法竞赛或者日常练习中难免会出现以上类型的题目,题目只说明了有两个数将要被读入进来,却没有告诉我们有多少组这样的数,这个时候就可以用到我们scanf的返回值EOF来进行判断了
int main()
{
// 如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量 EOF
long long a = 0;
long long b = 0;
// 不管有多少组数据我都一直读取,直到发⽣了读取错误或者遇到读取到⽂件结尾,我就结束
while (scanf("%ld %ld", &a, &b) != EOF)
{
printf("%ld\n", a + b);
}
return 0;
}
3. 占位符
scanf() 常⽤的占位符与 printf() 的占位符基本⼀致,我就不过多介绍了,这里讲一下连个特殊的占位符(%c、%s)
3.1 %c
除了 %c 以外,都会⾃动忽略空⽩字符
int main()
{
char ch1;
char ch2;
// 除了 %c 以外,都会⾃动忽略掉起首空⽩字符
// 输入:" 12"
scanf("%c %c", &ch1, &ch2);
printf("-%c- -%c-\n", ch1, ch2);
return 0;
}
结果:
如果要强制跳过字符前的空⽩字符,可以在% c 前加上⼀个空格,表⽰跳过零个或多个空⽩字符
int main()
{
char ch1;
char ch2;
// 如果要强制跳过字符前的空⽩字符,可以在% c 前加上⼀个空格,表⽰跳过零个或多个空⽩字符
scanf(" %c %c", &ch1, &ch2);
printf("-%c- -%c-\n", ch1, ch2);
return 0;
}
3.2 %s
它的规则是,从当前第⼀个⾮空⽩字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)就停止读取
那么这就会导致一个问题出现,假如我们像读取一句英文或者句子时就会导致不能够完全读取
int main()
{
char str[100] = "";
// 它的规则是,从当前第⼀个⾮空⽩字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)就停止读取
// 输入:"are you ok"
scanf("%s", str);
printf("%s\n", str); // 输出 are
return 0;
}
gets()函数 会读取整行输入行,直至遇到换行符,然后丢弃换行符,储存其余字符,并在字符末尾添加一个空字符使其成为C字符串(头文件 <stdio.h>)
int main()
{
char str[100] = "";
// 它的规则是,从当前第⼀个⾮空⽩字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)就停止读取
// 输入:"are you ok"
// gets()函数 会读取整行输入行,直至遇到换行符
gets(str);
printf("%s\n", str); // 输出 are you ok
return 0;
}
scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度
由于这个因素就会导致scanf这个函数十分的不安全,如果输入的字符串的长度超过了字符数组的长度,就会导致预想不到的结果
int main()
{
// scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度
char str[5] = "";
// 输入:"123456789"
scanf("%s", str);
return 0;
}
4. 赋值忽略符
有时输⼊可能不符合预定的格式,避免这种情况, scanf() 提供了⼀个赋值忽略符( *),只要把 * 加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃
int main()
{
int year = 0;
int month = 0;
int day = 0;
// 有时输⼊可能不符合预定的格式
// 比如:1/1/1 1--1--1--
scanf("%d-%d-%d", &year, &month, &day);
// 就会导致输出的数可能不是我们想要的
printf("%d %d %d\n", year, month, day);
// 把 * 加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃
// 此时不论时 1/1/1,1--1--1还是什么都可以精准读取
scanf("%d%*c%d%*c%d", &year, &month, &day);
return 0;
}