在写c语言时,printf和scanf是我们必不可少且常用的关键字,相信大多数人对它们俩的认识只是停留在表面上,并没有深入了解过它们吧,那么这一篇文就来深入对它们俩来说道说道

Printf

Printf:输出函数,将参数输出到屏幕上

案例:

int main(){printf("hello \nworld\n");return 0;}

printf(“hello \nworld\n”):将hello word打印到屏幕上,在使用printf函数时可以多次使用换行符\n,想在哪里加都可以

占位符

占位符:在printf中,占位符可以被指定的数值替换

案例:

int main(){printf("there are 3 apples\n");……1printf("there are %d apples\n", 3);……2printf("there are %d apples\n", 6);……3printf("%s will come to tonight\n", "李四");……4printf("%s says it is %d O'clock\n", "lisi", 21);……5return 0;}
  1. 1和2、3的区别是1这一代码的数字3是不能改变的,而且2/3语句中因为使用了占位符%d,所以是可以改变相应数字的,只需要将后面的数字更改为定义的变量就可以
  2. 4这句代码中,%s代表字符占位符,可以输入相应的字符,注意字符要用双引号
  3. 5这句代码中混合使用了字符占位符和整型占位符,可以输入相应的内容,注意后面输入的内容的顺序和前面的占位符的顺序要相同

常见占位符

%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 类型

%%

输出⼀个百分号

限定宽度

限定宽度:限定占位符的最小宽度

案例:

int main(){printf("%5d\n", 123);printf("%-5d\n", 123);printf("%12f\n", 123.45);printf("%12f\n", 123.45);return 0;}
  1. printf(“%5d\n”, 123);printf(“%-5d\n”, 123):以十进制的方式打印,让输出的值有5位宽,但现在只有3位宽,那么就默认在前面加2个空格以达到最小5位,那么在将5变为-5意思是将空格补到右边如结果图所示
  2. printf(“%12f\n”, 123.45):用十进制的方式打印,限定12位宽,现在有6位宽了(小数点也算一位)又因为小数默认有6位,所以系统会在前面加上2位空格已达到最小12位宽

结果:

总是显示正负号

让正负号显示出来,但其实默认负号本身就要显示,所以可以说是怎么显示正号

案例:

int main(){printf("%+d\n", 12);printf("%+d\n", -12);return 0;}
  1. printf(“%+d\n”, 12):以十进制的方式打印12,+d的意思就是在12前面显示正号
  2. printf(“%+d\n”, -12):以十进制的方式打印-12,+d在-12前加入正号,但-12是负数,有负号了,故最终还是-12

限定小数位

限定小数位:因为小数默认显示6位,但我们是可以进行限定小数后面的位数的

案例:

int main(){printf("%f\n", 123.45);printf("%.2f\n",123.45);printf("%6.2f\n", 0.5);printf("%*.*f\n",6,2,0.5);return 0;}
  1. printf(“%.2f\n”,123.45):以浮点数的形式打印123.45,在%和f中间加上一个 . 就是表示限定小数后面的位数了,想要几位就在 .后面输入数字就行,比如现在是.2表示显示2位小数
  2. printf(“%6.2f\n”, 0.5):以浮点数的形式打印0.5,,那么6.2中的6表示总共6位宽,小数点后有2位
  3. printf(“%*.*f\n”,6,2,0.5):以浮点数的形式打印0.5,,*.*表示总位宽和小数位宽由后面输入的值确定,也就是后面的6和2

注意:如果限定的位数大于实际位数,系统会补上零

输出部分字符串

输出部分字符串:%s占位符用来输出字符串,默认是全部输出。如果如果只想输出开头的部分,可以⽤ %.[n]s指定输出的⻓度,其中[m]代表⼀个数字,表⽰所要输出位宽

案例:

int main(){printf("%.5s\n", "hello world");return 0;}

printf(“%.5s\n”, “hello world”):以字符串的形式打印hello world.5表示只要5位宽,和上面的概念一样,故最终结果就只有 hello

那么对printf的解说就结束了

Scanf

Scanf:定义了变量后,scanf可以接受用户输入的内容并且存放到指定位置

案例:

int main(){int a = 0;printf("请输入成绩:");scanf("%d", &a);printf("成绩=%d", a);return 0;}
  1. int a = 0:定义一个整型变量a,初始化位0
  2. printf(请输入成绩:”):在屏幕上打印请输入成绩:
  3. scanf(“%d”, &a):scanf将等待用户输入整型数值,并且将输入的值存放在整型变量a中
  4. printf(成绩=%d”, a):以十进制的方式将刚刚输入的a在值打印出来,并在前面加上成绩=

注意:遇到scanf的安全问题请参考“变量的使用中注意”来解决,然后不要忘了scanf有取地址符号&

基本用法

Scanf的语法和printf的语法基本相同,还有scanf()必须提前知道数据的整型,也就是%什么,语句中有几个占位符,就必须有几个变量

案例:

int main(){int a = 0;int b = 0;float x = 0.0;float y = 0.0;scanf("%d %d %d %f %f", &a, &b, &x, &y);printf("%d %d %d %f %f", a, b, x, y);return 0;}
  1. int a = 0;int b = 0;float x = 0.0; float y = 0.0:定义整型变量a和b,浮点数x和y,都初始化为0
  2. scanf(“%d %d %d %f %f”, &a, &b, &x, &y):scanf等待用户输入内容,并且将内容存放在指定位置,这里的%d%f之间其实可以不用空格,但用户在输入数值的时候每组数值要空格,不让会识别成一组是数值
  3. printf(“%d %d %d %f %f”, a, b, x, y):分别就输入的值按照格式打印出来

注意:scanf函数不能加\n,并且用户输入时,要空格或用制表符或回车

补充:scanf函数再处理占位符时,会自动过滤空白字符,空格,回车,换行,制表符

补充:处理⽤⼾输⼊的原理是,⽤⼾的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存进⾏解读。解读⽤⼾输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。

案例:

int main(){int x;float y;// ⽤⼾输⼊ " -13.45e12# 0"scanf("%d", &x);scanf("%f", &y);printf("%d\n", x);printf("%d\n", y);return 0;}
  1. int x;float y:第一整型变量x和浮点数y
  2. scanf(“%d”, &x);scanf(“%f”, &y):scanf接受用户输入整型并存到x,scanf接受用户输入浮点数并存放到y
  3. printf(“%d\n”, x);printf(“%d\n”, y):以相应的形式对应x和y
  1. 此时我们运行程序并且输入:-13.45e12# 0,然后是scanf是这样运行的,将-13存放在x中,因为整型没有小数,所以第一个scanf就结束运行,并且将-13存入x;
  2. 此时第二个scanf开始接着小数点开始运行,因为scanf会从上一个遗留的第一个字符开始,并且以此为起点开始找小数,也就是 . 开始,那么就找到了.45e12(这个是科学计数法,是0.45*10^12,可能有误差)然后遇到#结束,因为小数里没有#,将结果存放y

Scanf的返回值

Scanf的返回值:scanf的返回值是一个整型,表示成功读取的变量个数,如果没有读取任何项,或则匹配失败,则返回0,如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量EOF

案例:

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. int r = scanf(“%d %d %f”, &a, &b, &f):scanf接受用户输入的值,并且存放到相应位置,然后定义一个整型变量r来存放scanf的返回值,此时r=3,因为scanf里放了3个变量
  2. printf(“a=%d b=%d f=%f\n”, a, b, f); printf(“r = %d\n”, r):以指定形式打印相应内容

注意:如果此时想让r=2,那么就可以在运行时只输入两组数据,然后安ctrl+z,但由于vsbugvs环境下需要按3ctrl+z

EOF:end of file 文件的结束,EOF的值为-1,在上面的例子中,如果什么都不输入按ctrl+z后回车 那么r此时就等于-1

占位符

占位符:scanf的占位符和printf的占位符相似

%[]

在方括号中指定一组匹配的字符(比如%[0-9]),遇到不在集合之中的字符,匹配将会停止

上⾯所有占位符之中,除了 %c 以外,都会⾃动忽略起⾸的空⽩字符。 %c 不忽略空⽩字符,总是返 回当前第⼀个字符,⽆论该字符是否为空格

案例:

int main(){char x = 0;scanf("%c", &x);printf("%c", x);printf("xxxx");return 0;}
  1. 此时我们输入空格a,那么scanf中的%c会把空格给读取走,不会读取a了
  2. 所以此时打印出来的就是 xxxx
  3. 如果要强制跳过%c读取空格,可在scanf中的%c前加空格

下⾯要特别说⼀下占位符 %s ,它其实不能简单地等同于字符串。它的规则是,从当前第⼀个⾮空⽩ 字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)为止

案例:

int main(){char x[20] = { 0 };scanf("%s", x);printf("%s", x);return 0;}
  1. char x[20] = { 0 }:定义字符型数组x,且数组有20个,初始化为0
  2. 此时我们输入ABC DEF,那么最终会打印出DEF,因为scanf %s 的形式遇到空格就不在继续读取了

因为 %s 不会包含空⽩字符,所以⽆法⽤来读取多个单词,除⾮多个 %s ⼀起使⽤。这也意味着, scanf() 不适合读取可能包含空格的字符串,⽐如书名或歌曲名。另外, scanf() 遇到 %s 占位 符,会在字符串变量末尾存储⼀个空字符 \0

scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度。所以,储存字符串时, 很可能会超过数组的边界,导致预想不到的结果(系统会提示崩溃)。为了防⽌这种情况,使⽤ %s 占位符时,应该指定 读⼊字符串的最⻓⻓度,即写成 %[n]s ,其中的 [n] 是⼀个整数,表⽰读取字符串的最⼤⻓度,后⾯的字符将被丢弃(这就是scanf不安全的原因)

案例:

int main(){char x[5] = { 0 };scanf("%4s", x);printf("%s\n", x);return 0;}
  1. char x[5] = { 0 }:定一个数组为5的整型变量x,初始化为0
  2. scanf(“%4s”, x):强制让字符串的长度为4位宽,多余的会被截掉
  3. 此时我们输入ABCDF,最终打印出ABCD

赋值忽律符

赋值忽律符:有时,⽤⼾的输⼊可能不符合预定的格式

案例:

int main(){int year = 0;int month = 0;int day = 0;scanf("%d-%d-%d", &year, &month, &day);scanf("%d%*c%d%*c%d", &year, &month, &day);return 0;}
  1. 定一个scanf在用户输入的时候也必须将—输入进去,不然就不对
  2. 而第二个scanf使用了赋值忽律符,此时用户只需要输入一组数值后按空格或制表符或回车就行了,不需要输入— 此时%*c就是赋值忽律符

好了,关于printf和scanf的讲解都结束了

如有错误请指出