【C语言】2.C语言数据类型和变量(下)


8.scanf 和 printf 介绍

8.1printf

8.1.1基本用法

printf() 的作用是将参数文本输出到屏幕。

#include <stdio.h>
int main(){
	printf("Hello World");
 	return 0;
}

打印:

Hello World

printf() 不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行。

为了让光标移到下一行的开头,可以在输出文本的结尾,添加一个换行符 \n

#include <stdio.h>
int main(){
	printf("Hello World\n");
 	return 0;
}

8.1.2占位符

printf() 可以在输出文本中指定占位符。

所谓 “占位符”,就是这个位置可以用其他值代入。

#include <stdio.h>
int main()
{
 printf("There are %d apples\n", 3);//输出 There are 3 apples
 return 0;
}

上面示例中, There are %d apples\n 是输出文本,里面的 %d 就是占位符,表示这个位置要用其他值来替换。占位符的第一个字符一律为百分号 % ,第二个字符表示占位符的类型, %d 表示这里代入的值必须是一个整数。

printf() 的第二个参数就是替换占位符的值,上面的例子是整数 3 替换 %d 。执行后的输出结果就是 There are 3 apples

int main() {
    printf("%s will  come tonight", "list");
    return 0;
}

%s 表示代入的是字符串。

输出文本里面可以使用多个占位符。

8.1.3占位符列举

最常用的几个我用✨标出来了

  1. %a :十六进制浮点数,字母输出为小写。

  2. %A :十六进制浮点数,字母输出为大写。

  3. %c :字符。//✨

  4. %d :十进制整数。// int ✨

  5. %e :使用科学计数法的浮点数,指数部分的 e 为小写。

  6. %E :使用科学计数法的浮点数,指数部分的 E 为大写。

  7. %i :整数,基本等同于 %d 。

  8. %f :小数(包含 float 类型和 double 类型)。//float %f✨ double - %lf✨

  9. %g :6个有效数字的浮点数。整数部分一旦超过6位,就会自动转为科学计数法,指数部分的 e为小写。

  10. %G :等同于 %g ,唯一的区别是指数部分的 E 为大写。

  11. %hd :十进制 short int 类型。✨

  12. %ho :八进制 short int 类型。

  13. %hx :十六进制 short int 类型。

  14. %hu :unsigned short int 类型。✨

  15. %ld :十进制 long int 类型。✨

  16. %lo :八进制 long int 类型。

  17. %lx :十六进制 long int 类型。

  18. %lu :unsigned long int 类型。✨

  19. %lld :十进制 long long int 类型。

  20. %llo :八进制 long long int 类型。

  21. %llx :十六进制 long long int 类型。

  22. %llu :unsigned long long int 类型。

  23. %Le :科学计数法表示的 long double 类型浮点数。

  24. %Lf :long double 类型浮点数。✨

  25. %n :已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中。

  26. %o :八进制整数。

  27. %p :指针(用来打印地址)。✨

  28. %s :字符串。✨

  29. %u :无符号整数(unsigned int)。✨

  30. %x :十六进制整数。✨

  31. %zd : size_t 类型。✨

  32. %% :输出一个百分号。

举个例子:

int main() {
    printf("%hd\n",100);
    printf("%ho\n", 100);
    printf("%x\n", 15);
    return 0;
}

打印:

100//100用十进制表示是100
144//100用八进制表示是144;64+32+4
f//15用十六进制表示是f

👌


8.1.4输出格式

printf() 可以定制占位符的输出格式。

8.1.5限定宽度

printf() 允许限定占位符的最小宽度。

为了方便查看,我就把空格用⏹️来表示了。

#include <stdio.h>
int main()
{
 printf("%5d\n", 123); // 输出为 "⏹️⏹️123"
 return 0;
}

上面示例中, %5d 表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。

输出的值默认是右对齐,即输出内容前面会有空格;如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的 % 的后面插入一个 - 号。

#include <stdio.h>
int main()
{
 printf("%-5d\n", 123); // 输出为 "123⏹️⏹️"
 return 0;
}

对于小数,限定符会限制所有数字的最小显示宽度。

#include <stdio.h>
int main()
{
 printf("%12f\n", 123.45);//输出 "⏹️⏹️123.450000"
 printf("%4lf\n", 123.45);//输出 :"123.450000"
 printf("%12.1lf\n",123.45);//输出:"⏹️⏹️⏹️⏹️⏹️⏹️⏹️123.5"
 //在C语言中,当使用 %lf 格式化浮点数时,会根据指定的小数位数进行四舍五入。
printf("%*.*lf\n",12,1,123.45);//输出:"⏹️⏹️⏹️⏹️⏹️⏹️⏹️123.5"
//这里的*相当于起了个数值传递的功能//和上面那个%12.1lf一个作用
    
printf("%s\n","abcdef");//输出:"abcdef"
printf("%.3s\n","abcdef");//输出:"abc"
 return 0;
}

举个例子:

#include <stdio.h>
int main()
{
    printf("%5d\n", 123456);
    return 0;
}

打印:

123456

为啥不是12345呢?🤔莫非C语言不存在了?🤣

因为%5d表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。如果超过5位,正常输出就行,5是最少输出5位。


8.1.6总是显示正负号

默认情况下, printf() 不对正数显示 + 号,只对负数显示 - 号。如果想让正数也输出 + 号,可以在占位符的 % 后面加一个 + 。

#include <stdio.h>
int main()
{
 printf("%d\n", 12); // 输出 12
 printf("%d\n", -12); // 输出 -12   
 printf("%+d\n", 12); // 输出 +12
 printf("%+d\n", -12); // 输出 -12✨
 return 0;
}

8.1.7限定小数位数

输出小数时,有时希望限定小数的位数。举例来说,希望小数点后面只保留两位,占位符可以写成 %.2f

#include <stdio.h>
int main()
{
 printf("Number is %.2f\n", 0.5);//输出 Number is 0.50
 return 0;
}

这种写法可以与限定宽度占位符,结合使用。

#include <stdio.h>
int main()
{
 printf("%6.2f\n", 0.5);//输出为 "⏹️⏹️0.50"
 return 0;
}

最小宽度和小数位数这两个限定值,都可以用 * 代替,通过 printf() 的参数传入。

#include <stdio.h>
int main()
{
 printf("%*.*f\n", 6, 2, 0.5);
 return 0;
}
// 等同于printf("%6.2f\n", 0.5);

8.1.8输出部分字符串

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

#include <stdio.h>
int main()
{
 printf("%.5s\n", "hello world");//输出 hello
 return 0;
}

8.1.9输出多个占位字符

printf() 参数与占位符是一一对应关系,如果有 n 个占位符, printf() 的参数就应该有 n + 1 个。如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。

int main() {
    printf("%s says it is %d o'clock\n", "list", 10);
    printf("%s says it is %d o'clock\n", "avwfb", 20);
    return 0;
}

打印:

list says it is 10 o'clock
avwfb says it is 20 o'clock

上面的n+1是哪来的?🤨

在这里插入图片描述


8.2scanf

8.2.1scanf输入一个参数

需要给变量输入值就可以使用 scanf 函数.

#include <stdio.h>
int main()
{
 int score = 0;
 printf("请输入成绩:");
 scanf("%d", &score);
 printf("成绩是:%d\n", score);
 return 0;
}

运行截图:

在这里插入图片描述

输入90

在这里插入图片描述

点击回车

在这里插入图片描述

scanf() 的第一个参数 %d ,表示用户输入的应该是一个整数。

scanf("%d", &score);

%d 就是一个占位符, % 是占位符的标志, d 表示整数。第二个参数 &score 表示,将用户从键盘输入的整数存入变量score


8.2.2scanf输入多个参数

scanf("%d%d%f%f", &i, &j, &x, &y);

scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。所以,用户输入的数据之间,有一个或多个空格不影响 scanf() 解读数据。另外,用户使用回车键,将输入分成几行,也不影响解读。

可以这样

1 2 0.4 4.6

也可以这样

1 
2 
0.4 
4.6

来个例题做做:

int main() {
    int x;
    int y;
    scanf("%d=%d", &x, &y);
    printf("%d %d", x, y);
    return 0;
}

如果想输入i的值为2,想输入j的值为3

很多初学者直接会输入2 3

然后得到一个奇怪的结果:

在这里插入图片描述

🤨然后怀疑电脑坏了。

为啥y不显示 3却显示这么个怪东西呢?

注意:scanf函数里面的%d=%d,这里面有个等号啊!😡

应该输入2=3,对应scanf("%d=%d", &x, &y);里面的%d=%d

如果你输入 2 3 而不是 2=3 , scanf 将无法正确解析输入,因为它期望的是一个等号而不是一个空格。由于 scanf 无法匹配格式字符串中的等号,它不会为 y 读取任何值,因此 y 的值将是未定义的。也就是随便来个值咯。

既然这样,我把%d和%d写一起不就无法输出了吗?🤔

int main() {
    int x;
    int y;
    scanf("%d%d", &x, &y);
    printf("%d %d", x, y);
    return 0;
}

并不是这样的😡

我们先输入1空格 2,再回车一样能得到这个值。

scanf("%d=%d", &x, &y);

就像这个一样,只要在输入x和y的时候,中间有个=就行了,电脑可不管x和=,或者y和=之间有几个空格。

scanf("%d=%d\n", &x, &y);

如果里面写了 \n,那么输入的时候也要输入\n
建议写代码的时候%d之间不要有空格,不然检查不仔细可能会出现奇怪的错误。


再来题练练:

下面的程序里面,用户输入"⏹️⏹️⏹️-13.45e12#⏹️0"会发生什么?

int main() {
    int x;
    float y;
    scanf("%d", &x);
    printf("%d\n", x);
    scanf("%f", &y);
    printf("%f\n", y);
    return 0;
}

打印:

在这里插入图片描述

🤯🤯🤯

首先x跳过了开头的空格读取了-13。因为x是int类型的。

因为y是float类型的,所以从这里的小数点开始读。先读到0.45,然后遇到这个e12。这里面e12表示的是科学计数法。0.45e12表示的是 0.45乘上10的12次方。然后发现后面有个#,读不了,就结束了读取。

所以y就得到了这么怪东西。


8.2.3scanf的返回值

1.scanf() 返回值

scanf() 的返回值是一个整数,表示成功读取的变量个数。

如果没有读取任何项,或者匹配失败,则返回 0 。

如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF (-1)。

int main() {
    int a = 0;
    int b = 0;
    int c = 0;
    int d = 0;
    int ret = scanf("%d %d %d %d", &a, &b, &c, &d);
    printf("%d %d %d %d\n", a, b, c, d);
    printf("ret = %d\n", ret);
    
    return 0;
}

输入:

1 2 3 4

打印 :

1 2 3 4
ret = 4

然后我们改变一下输入的东西。

输入:

1 2 34

打印 :

1 2 3 0
ret = 3

这次ret=3了。

接着,我们再改变一下输入的东西。

在这里插入图片描述

这里面我输入的是CtrlZ ,也就是按住Ctrl的时候按住Z,然后回车继续按。

这里按了3次是因为VS这里需要3次。在VS环境中按3次 ctrl+z ,才结束了输入。其他软件里面可能按一次再回车就好了。

输出的ret = -1,刚好和上面说的如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF (-1)。吻合。


2.scanf() 输入%c

%c 不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。

int main() {
	char ch = 0;
	scanf("%c", &ch);
	printf("xxx%cyyy", ch);
	return 0;
}

输入:

⏹️⏹️ejs

打印:

xxx⏹️yyy

输入:

sdyuy

打印:

xxxsyyy

如果要强制跳过字符前的空白字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上一个空格,表示跳过零个或多个空白字符。

int main() {
	char ch = 0;
	scanf(" %c", &ch);//%c的前面有个空格
	printf("xxx%cyyy", ch);
	return 0;
}

输入:

⏹️⏹️ejs

打印:

xxxeyyy

欧了👌


3.scanf() 将字符串读入字符数组:

scanf() 将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时,很可能会超过数组的边界,导致预想不到的结果。

int main()
{
	char name[5];
	scanf("%s", name);
	printf("%s", name);
	return 0;
}

输入:

wtwrtrw

打印:

在这里插入图片描述

报错了。

因为name[5]数组里面最多放5个。这里面放太多了。它受不了了。

在这里插入图片描述


咋办呢?

为了防止这种情况,使用 %s 占位符时,应该指定读入字符串的最长长度,即写成 %🅰️s

其中的 🅰️ 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。

int main()
{
	char name[5];
	scanf("%5s", name);
	printf("%s", name);
	return 0;
}

输入:

sgdggfds

结果:

还是报错!

在这里插入图片描述

因为scanf() 遇到 %s 占位符,会在字符串变量末尾存储一个空字符 \0

也就是说上面的scanf("%5s", name);里面的5应该改成4。这样就不会溢出了。

在这里插入图片描述


int main()
{
	char name[11];
	scanf("%10s", name);
	printf("%s", name);
	return 0;
}

输入:

efgrgegttgteht

输出:

efgrgegttg
4.赋值忽略符

之前在 8.2.2scanf输入多个参数 这个地方讲过scanf输入与里面符号的关系。

我们也可以用赋值忽略符*来解决这个问题。

只要把 * 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。

例如:

int main()
{
 int year = 0;
 int month = 0;
 int day = 0;
 scanf("%d%*c%d%*c%d", &year, &month, &day);
 return 0;
}

输入:

2024 4 1

打印:

2024 4 1

可能有人会奇怪为什么说了赋值忽略符是* ,结果我放了个%*c?

%c是读取一个字符,%*c是读取这个字符,然后让他不会有返回值。


在这里插入图片描述
都看到这里了,点个赞呗~


  • 30
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值