printf和scanf操控术:让C语言输入输出再无神秘

目录

一. printf

1.1 printf基本用法

1.2 占位符

1.3 占位符列举

1.4 输出格式

1.4.1限定宽度

1.4.2 显示正负号

1.4.3 限定小数位数

1.4.4 输出部分字符串

二. scanf

2.1 基本用法

2.2 scanf的返回值

 2.3 占位符

2.4 赋值忽略符

一. printf

1.1 printf基本用法

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

#include <stdio.h>

int main() 
{
    printf("Hello World");
    return 0;
}

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

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

#include <stdio.h>

int main() 
{
    printf("Hello World\n");
    return 0;
}

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

1.2 占位符

printf() 可以在输出文本中指定占位符。所谓“占位符”,就是这个位置可以用其他值代入。​

#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 表示代入的是字符串。

#include <stdio.h>

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

上面示例中,%s 表示代入的是一个字符串,所以printf() 的第二个参数就必须是字符串,这个例 子是zhangsan 。执行后的输出就是zhangsan will come tonight 。

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

#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() 可能会输出内存中的任意值。

1.3 占位符列举

printf() 的占位符有许多种类,与 C 语言的数据类型相对应。下面按照字母顺序,列出常用的占位符。

• %a :⼗六进制浮点数,字⺟输出为⼩写。

• %A :⼗六进制浮点数,字⺟输出为⼤写。

• %c :字符。//char

• %d :⼗进制整数。//int

• %e :使⽤科学计数法的浮点数,指数部分的 e 为⼩写。

• %E :使⽤科学计数法的浮点数,指数部分的 E 为⼤写。

• %i :整数,基本等同于 %d

• %f:⼩数(包含float类型和double类型)。//float:%f, double:%lf

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

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

1.4 输出格式

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

1.4.1限定宽度

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;
}

上⾯⽰例中,输出内容 123 的后⾯添加了空格。

对于⼩数,这个限定符会限制所有数字的最⼩显⽰宽度。 

#include <stdio.h>

int main()
{
 printf("%12f\n", 123.45); // 输出 "  123.450000" 
 return 0;
}

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

1.4.2 显示正负号

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

#include <stdio.h>

int main()
{
    printf("%+d\n", 12); // 输出 +12 
    printf("%+d\n", -12); // 输出 -12 
    return 0;
}

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

1.4.3 限定小数位数

输出⼩数时,有时希望限定⼩数的位数。举例来说,希望⼩数点后⾯只保留两位,占位符可以写 成 %.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;
}

上⾯⽰例中, %6.2f 表⽰输出字符串最⼩宽度为6,⼩数位数为2。所以,输出字符串的头部有两个空格。

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

#include <stdio.h>

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

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

1.4.4 输出部分字符串

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

#include <stdio.h>

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

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

二. scanf

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

#include <stdio.h>

int main()
{
    int score = 0;
    printf("请输⼊成绩:");
    scanf("%d", &score);
    printf("成绩是:%d\n", score);
    return 0;
}

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

2.1 基本用法

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

scanf("%d", &i)

它的第⼀个参数是⼀个格式字符串,⾥⾯会放置占位符(与 printf() 的占位符基本⼀致),告诉编 译器如何解读用户的输⼊,需要提取的数据是什么类型。

这是因为C语⾔的数据都是有类型的, scanf() 必须提前知道用户输⼊的数据类型,才能处理数 据。

它的其余参数就是存放用户输⼊的变量,格式字符串⾥⾯有多少个占位符,就有多少个变量。

上⾯⽰例中,scanf() 的第⼀个参数 %d ,表⽰用户输⼊的应该是⼀个整数。%d 就是⼀个占位符,% 是占位符的标志,d 表⽰整数。第⼆个参数 &i 表⽰将用户从键盘输⼊的整数存⼊变量 i 。

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

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

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() 解读数据。另外,用户使⽤回车键,将输⼊分成⼏⾏,也不影响解读。

scanf() 处理用户输⼊的原理是,用户的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存 进⾏解读。 

解读用户输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。

#include <stdio.h>

int main()
{
    int x;
    float y;
 
    scanf("%d", &x); // 用户输⼊ "   -13.45e12# 0" 
    printf("%d\n", x); // 输出 "-13"
    scanf("%f", &y); 
    printf("%f\n", y); // 输出 ".45e12(科学计数法的浮点数格式)"

    return 0;
}

上⾯⽰例中, scanf() 读取用户输⼊时, %d 占位符会忽略起⾸的空格,从 - 处开始获取数据,读 取到 -13 停下来,因为后⾯的 . 不属于整数的有效字符。这就是说,占位符 %d 会读到 -13 。 第⼆次调⽤ scanf() 时,就会从上⼀次停⽌解读的地⽅,继续往下读取。这⼀次读取的⾸字符是 . ,由于对应的占位符是 %f ,会读取到 .45e12 ,这是采⽤科学计数法的浮点数格式。后⾯的 # 不属于浮点数的有效字符,所以会停在这⾥。

由于 scanf() 可以连续处理多个占位符,所以上⾯的例⼦也可以写成下⾯这样。

#include <stdio.h>
int main()
{
    int x;
    float y;

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

2.2 scanf的返回值

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

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

如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量EOF(-1)。 EOF - end of file⽂件结束标志。

#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;
}

输入输出测试:

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

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

 2.3 占位符

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

• %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] 是⼀个整数,表⽰读取字符串的最⼤⻓度,后 ⾯的字符将被丢弃。

#include <stdio.h>

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

    return 0;
}

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

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;
}

上⾯⽰例中,如果用户输⼊ 2020-01-01 ,就会正确解读出年、⽉、⽇。问题是用户可能输⼊其他 格式,⽐如 2020/01/01 ,这种情况下, scanf() 解析数据就会失败。

为了避免这种情况, scanf() 提供了⼀个赋值忽略符(assignment suppression character) * 。 只要把 * 加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃。 

#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;
}

上⾯⽰例中, %*c 就是在占位符的百分号后⾯,加⼊了赋值忽略符 * ,表⽰这个占位符没有对应的 变量,解读后不必返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值