[C语言]——scanf和printf介绍

目录

一.printf

1.基本用法

2.占位符

3.占位符列举

4.输出格式

4.1限定宽度

4.2总是显示正负号

4.3限定小数位数

4.4输出部分字符串

二.scanf

1.基本用法

2.scanf的返回值

3.占位符

4.赋值忽略符


一.printf

1.基本用法

printf() 的作⽤是将参数⽂本输出到屏幕。它名字⾥⾯的 f 代表 format (格式化),表示可以
定制输出文本的格式

cpp 复制代码
#include <stdio.h>
int main(void) 
{
 printf("Hello World");
 return 0;
}

上⾯命令会在屏幕上输出⼀⾏⽂字"Hello World"。 printf() 不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地⽅,不会自动换⾏ 。为了让光标移到下⼀⾏的开头,可以在输出⽂本的结尾,添加⼀个换⾏符**\n**。

cpp 复制代码
#include <stdio.h>
int main(void) 
{
 printf("Hello World\n");
 return 0;
}

如果⽂本内部有换⾏,也是通过插⼊换⾏符来实现,如下⽅代码:

cpp 复制代码
#include <stdio.h>
int main(void) 
{
 printf("Hello\nWorld\n");
 
 printf("Hello\n");
 printf("World\n");
 return 0;
}

printf() 是在标准库的头⽂件 stdio.h 定义的。使⽤这个函数之前,必须在源码⽂件头部引⼊这
个头⽂件。

2.占位符

printf() 可以在输出⽂本中指定占位符。 所谓 "占位符",就是这个位置可以⽤其他值代⼊。

cpp 复制代码
// 输出 There are 3 apples
#include <stdio.h>
int main()
{
 printf("There are %d apples\n", 3);
 return 0;
}
  • 上⾯⽰例中, There are %d apples\n 是输出⽂本,⾥⾯的 %d 就是占位符,表⽰这个位置要 ⽤其他值来替换。占位符的第⼀个字符⼀律为百分号**%** ,第⼆个字符表⽰占位符的类型, %d 表⽰这⾥代⼊的值必须是⼀个整数。
  • printf() 的第⼆个参数就是替换占位符的值,上⾯的例⼦是整数 3 替换 %d 。执⾏后的输出结果就是 There are 3 apples 。
  • 常⽤的占位符除了 %d ,还有 %s 表⽰代⼊的是字符串。
cpp 复制代码
#include <stdio.h>
int main()
{
 printf("%s will come tonight\n", "zhangsan");
 return 0;
}

上⾯⽰例中, %s 表⽰代⼊的是⼀个字符串,所以 printf() 的第⼆个参数就必须是字符串,这个例 ⼦是 zhangsan 。执⾏后的输出就是 zhangsan will come tonight 。
输出⽂本⾥⾯可以使⽤多个占位符。

cpp 复制代码
#include <stdio.h>
int main()
{
 printf("%s says it is %d o'clock\n", "lisi", 21);
 return 0;
}

上⾯⽰例中,输出⽂本 %s says it is %d o'clock 有两个占位符,第⼀个是字符串占位符 %s ,第⼆个是整数占位符 %d ,分别对应 printf() 的第⼆个参数( lisi )和第三个参数( 21 )。执⾏后的输出就是 lisi says it is 21 o'clock 。
printf() 参数与占位符是⼀⼀对应关系,如果有 n 个占位符, printf() 的参数就应该有 n + 1 个。如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。
这是因为在C语言中,printf()函数的第一个参数是格式化字符串,后面的参数是要替换占位符的实际值。所以如果有n个占位符,就需要n个实际值来替换这些占位符,再加上格式化字符串本身,所以参数个数应该是n+1个。

3.占位符列举

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

  • %% :输出⼀个百分号。

4.输出格式

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

4.1限定宽度

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

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

上⾯⽰例中, %5d 表⽰这个占位符的宽度至少为5位(输入123456打印为123456) 。(小数点也要占一位 )如果不满5位,对应的值的前⾯会添加空格。 输出的值默认是右对齐,即输出内容前⾯会有空格;如果希望改成左对⻬,在输出内容后⾯添加空格,可以在占位符的 % 的后⾯插⼊⼀个 - 号。

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

上⾯⽰例中,输出内容 123 的后⾯添加了空格。 对于⼩数,这个限定符会限制所有数字的最⼩显⽰宽度。

cpp 复制代码
// 输出 " 123.450000"
#include <stdio.h>
int main()
{
 printf("%12f\n", 123.45);
 return 0;
}

上⾯⽰例中, %12f 表⽰输出的浮点数最少要占据12位。由于**⼩数的默认显⽰精度是⼩数点后6位**, 所以 123.45 输出结果的头部会添加2个空格。

4.2总是显示正负号

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

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

上⾯⽰例中, %+d 可以确保输出的数值,总是带有正负号

4.3限定小数位数

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

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

上⾯⽰例中,如果希望⼩数点后⾯输出3位( 0.500 ),占位符就要写成 %.3f 。这种写法可以与限定宽度占位符,结合使⽤。

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

上⾯⽰例中, %6.2f 表⽰输出字符串最⼩宽度为6,⼩数位数为2。所以,输出字符串的头部有两个空格。
最⼩宽度和⼩数位数这两个限定值,都可以⽤ * 代替,通过 printf() 的参数传⼊。

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

上⾯⽰例中, %*.*f 的两个星号通过 printf() 的两个参数 6 和 2 传⼊。

4.4输出部分字符串

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

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

上⾯⽰例中,占位符 %.5s 表⽰只输出字符串"hello world"的前5个字符,即"hello"。

二.scanf

当我们有了变量,我们需要给变量输⼊值就可以使⽤ scanf 函数,如果需要将变量的值输出在屏幕上的时候可以使⽤ prinf 函数,下⾯看⼀个例⼦:

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

运行截图:

注:标准输⼊⼀般指的就是键盘,标准输出⼀般指的就是屏幕

1.基本用法

scanf() 函数⽤于读取⽤⼾的键盘输⼊。 程序运⾏到这个语句时,会停下来,等待⽤⼾从键盘输⼊。 ⽤⼾输⼊数据、按下回⻋键后, scanf() 就会处理⽤⼾的输⼊,将其存⼊变量。它的原型定义在头文件 stdio.h。scanf() 的语法跟 printf() 类似。

cpp 复制代码
 scanf("%d", &i);
  • 它的第⼀个参数是⼀个格式字符串,⾥⾯会放置占位符(与 printf() 的占位符基本⼀致),告诉编译器如何解读⽤⼾的输⼊,需要提取的数据是什么类型。
  • 这是因为 C 语⾔的数据都是有类型的, scanf() 必须提前知道⽤⼾输⼊的数据类型,才能处理数据。
  • 它的其余参数就是存放⽤⼾输⼊的变量,格式字符串里面有多少个占位符,就有多少个变量。 上⾯⽰例中, scanf() 的第⼀个参数 %d ,表⽰⽤⼾输⼊的应该是⼀个整数。 %d 就是⼀个占位符, % 是占位符的标志, d 表⽰整数。第⼆个参数 &i 表⽰,将⽤⼾从键盘输⼊的整数存⼊变量 i 。

**注意:变量前⾯必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,⽽是地址,****即将变量 i 的地址指向⽤⼾输⼊的值。**如果这⾥的变量是指针变量(⽐如字符串变量),那就不⽤加 & 运算符。

下⾯是⼀次将键盘输⼊读⼊多个变量的例⼦。

cpp 复制代码
scanf("%d%d%f%f", &i, &j, &x, &y);
  • 上⾯⽰例中,格式字符串 %d%d%f%f ,表⽰⽤⼾输⼊的前两个是整数,后两个是浮点数,⽐如 1 -20 3.4 -4.0e3 。这四个值依次放⼊ i 、 j 、 x 、 y 四个变量。
  • scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等
  • 所以,⽤⼾输⼊的数据之间,有⼀个或多个空格不影响 scanf() 解读数据。另外,⽤⼾使⽤回⻋ 键,将输⼊分成⼏⾏,也不影响解读。
cpp 复制代码
1
-20
3.4
-4.0e3
  • 上⾯⽰例中,⽤⼾分成四⾏输⼊,得到的结果与⼀⾏输⼊是完全⼀样的。每次按下回⻋键以后, scanf() 就会开始解读,如果第⼀⾏匹配第⼀个占位符,那么下次按下回⻋键时,就会从第⼆个占位符开始解读。
  • scanf() 处理⽤⼾输⼊的原理是,⽤⼾的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存 进⾏解读。
  • 解读⽤⼾输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。
cpp 复制代码
#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 ,这是采⽤科学计数法的浮点数格式。后⾯的# 不属于浮点数的有效字符,所以会停在这⾥。 由于 scanf() 可以连续处理多个占位符,所以上⾯的例⼦也可以写成下⾯这样。
cpp 复制代码
#include <stdio.h>
int main()
{
 int x;
 float y;
 
 // ⽤⼾输⼊ " -13.45e12# 0"
 scanf("%d%f", &x, &y);
 return 0;
}

2.scanf的返回值

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

cpp 复制代码
#include <stdio.h>
int main()
{
 int a = 0;
 int b = 0;
 float f = 0.0f;
 int r = scanf("%d %d %f", &a, &b, &f);
//输入时保持一致 "%d,%d,%f"  1,2,3(中英文符号要对应)
//              "%d %d %f"  1 2 3(中间有空格,不然表示123)
 printf("a=%d b=%d f=%f\n", a, b, f);
 printf("r = %d\n", r);
 return 0;
}

输⼊输出测试:

如果输⼊2个数后,按 ctrl+z ,提前结束输⼊:

在VS环境中按3次 ctrl+z ,才结束了输入,我们可以看到r是2,表示正确读取了2个数值。如果⼀个数字都不输入,直接 按3次ctrl+z ,输出的r是-1,也就是EOF

3.占位符

scanf() 常用的占位符如下,与 printf() 的占位符基本⼀致。

  • %c :字符。

  • %d :整数。

  • %f : float 类型浮点数。

  • %lf : double 类型浮点数。

  • %Lf : long double 类型浮点数。

  • %s :字符串。

  • %\[\] :在⽅括号中指定⼀组匹配的字符(⽐如 %0-9 ),遇到不在集合之中的字符,匹配将会停⽌。

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

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

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

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

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

cpp 复制代码
#include <stdio.h>
int main()
{
 char name[11];
 scanf("%10s", name);
 
 return 0;
}

上⾯⽰例中, name 是⼀个⻓度为11的字符数组, scanf() 的占位符 %10s 表⽰最多读取⽤⼾输⼊
的10个字符,后⾯的字符将被丢弃,这样就不会有数组溢出的⻛险了。

4.赋值忽略符

有时,⽤⼾的输⼊可能不符合预定的格式。

cpp 复制代码
#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;
}

上⾯⽰例中,如果⽤⼾输⼊ 2020-01-01 ,就会正确解读出年、⽉、⽇。问题是⽤⼾可能输⼊其他
格式,⽐如 2020/01/01 ,这种情况下, scanf() 解析数据就会失败。
为了避免这种情况, scanf() 提供了⼀个赋值忽略符(assignment suppression character) * 。 只要把 * 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。

相关推荐
Scott9999HH41 分钟前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海2 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨3 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区5 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大6 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai6 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜6 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa6 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio