printf()和scanf() (详解)

简介: printf()和scanf() (详解)

前言

在C语言中,printf和scanf函数是贯穿始终的,它们是输出和输入函数,简称I/O函数。它们的工作原理几乎相同,两个函数都使用格式字符串和参数列表。我们先介绍printf(),再介绍scanf()。

printf()

printf函数格式:

printf( 格式字符串, 待打印项1, 待打印项2,…)

格式字符串是用双引号括起来的语句,待打印项是要打印的项,它们可以是变量、常量,甚至是在打印之前先要计算的表达式。

转换说明符

我们在使用中,经常会用到%d和%c来打印想要的整数和字符,这些以%+字母称之为转换说明,下面给出给出一些转换说明和输出类型表

下面通过一些例子来演示这些转换说明的使用

#include<stdio.h>
int main()
{
    int number=9;
    int cost=500;
    float pi=15.67;
    printf("今天消费了%d,欠了别人%f钱\n",cost,pi);
    printf("这里有%d个篮球,总共花费了%c%d\n",number,'$',2*cost);
    return 0;
}


结果:

这里的

printf(“这里有%d个篮球,总共花费了%c%d\n”,number,‘$’,2*cost);

第二个打印项是字符常量,第三个是乘法表达式,表明printf()使用的是值


要清楚,格式字符串要和转换字符对应清楚,否则将会导致严重的后果。

如:


printf(“今天买了%d个篮球,花了%d元”,number);


结果:


今天买了9个篮球,花了1867835296元


这里的第二个%d没有对应的值,所以打印出来的是一个毫无意义的值,系统不同,结果也会不同。

由于%用来表示转换说明,所以当要打印%时,要用到%%进行打印


printf(“今天有%%95的概率会下雨\n”);

结果:今天有%95的概率会下雨

转换说明修饰符

在%和转换字符之间插入修饰符可修饰基本的转换说明。下面给出修饰符表格:

下面通过例子来说明使用含义。

字段宽度:

*号表示字段开始和结束

#include<stdio.h>
int main()
{
    int num=8848;
    printf("%d\n",num);
    printf("%2d\n",num);
    printf("%9d\n",num);
    printf("%-9d\n",num);
    return 0;
}

说明:第一项是默认的打印结果,输出结果默认是对应相应的字段宽度。

第二项由于字段宽度小于实际宽度,故字段宽度会默认扩大到相应的宽度。

第三项是默认是右对齐,第四项的-表示是左对齐。


浮点型格式:

#include <stdio.h>
int main()
{
const double op = 3456.78; // const变量
printf("*%f*\n", op);
printf("*%e*\n", op);
printf("*%4.2f*\n", op);
printf("*%3.1f*\n", op);
printf("*%10.3f*\n", op);
printf("*%10.3E*\n", op);
printf("*%+4.2f*\n", op);
printf("*%010.2f*\n", op);
return 0;
}


说明:第一项是默认的转换说明,f默认打印小数点后6位,超出则以四舍五入的方式计算打印。第二项是的e表示10的几次方再乘上前面的数字。第三项的.2表示打印小数点后两位,超出以四舍五入方式进行计算打印。第五项10为字段宽度。第6项E与e是相同作用的,.3为小数点后3位,10为字段宽度。第7项0是进行补充字段宽度空白处的。

格式标记:

#include <stdio.h>
int main()
{
printf("%x %X %#x\n", 78, 78, 78);
printf("**%d**% d**% d**\n", 42,42, - 42);
printf("**%5d**%5.3d**%05d**%05.3d**\n", 6, 6, 6, 6);
return 0;
}


9.png

说明:第一句0x通常表示这是一个地址,用#来进行修饰。第二句当空格遇到负号时,空格无效。第三句.3表示打印整型格式的精度,当0和.3一起使用时,0的修饰会被省略。

字符串:

#include<stdio.h>
int main()
{
    char arr[]="Today is a sun day";
    printf("[%s]\n",arr);
    printf("[%25s]\n",arr);
    printf("[%.5s]\n",arr);
    printf("[%25.5s]\n",arr);
    printf("[%-25.5s]\n",arr);
    return 0;
}

8.png

说明:.5表示打印字符串长度,25为字段宽度,默认右对齐,加上-表示左对齐


在我们使用转换说明时,用对字符是非常关键的。我们知道,电脑将会以二进制的格式进行存储,不同的转换说明是将二进制格式转换为不同形式进行改变再打印到屏幕上。

如将字符打印成整数


printf(“%d\n”,‘a’);

结果:97

它会通过ASCLL编码表进行转换从而打印


再如:

将整数用%f打印


printf(“%f\n”,16);

结果:0.000000

16对于%f来说相当于0,所以要正确打印的话,要用16.0表示你是一个有精度的数。


printf()的返回值

大部分C函数都有一个返回值,这是函数计算并返回给主程序的值。printf()函数也有一个返回值,它返回打印字符的个数。如果有输出错误,printf()则返回一个负值。

#include<stdio.h>
int main()
{
    int num1=printf("%d\n",3);
    int num2=printf("这个数是%d\n",3);
    printf("%d %d",num1,num2);
    return 0;
}

7.png

说明:中文表示两个字符,%d和\n分别各表示一个。所以长度取决于格式字符串的长度。

scanf()

接下来我们来看scanf函数。这是C语言中最通用的一个C函数,因为它可以读取不同格式的数据。我们键盘上只能输入字母,字符和数字,scanf函数能将输入的字符串转换成整数、浮点数、字符或字符串,这种方式恰好于printf()相反。格式形式和printf类似,也使用格式字符串和参数列表。scanf()中的格式字符串表明字符输入流的目标数据类型。两个函数主要的区别在参数列表中。printf()函数使用变量、常量和表达式,而scanf()函数使用指向变量的指针。一般来说,对基本变量的使用赋值,用在变量前加一个&(意思为取地址);字符串数组本质其实就是一个指针,所以不要使用&。

6.png

#include<stdio.h>
int main()
{
    int n;
    char arr[30];
    scanf("%d",&n);//n为基本变量,需要应用&
    scanf("%s",arr);//arr是一个数组,不需要用到&
    return 0;
}


对于转换说明,于printf类似。

5.png

对于scanf()函数也有修饰符,但对于使用场所来说,是比较少的,所以在此没有介绍。一般使用场景就如我上面的例图一般。

scanf的输入

我们以%d读取一个整数为例。我们输入一个数字(2048),会先放在一块输入空间里,对于scanf(),会去这块空间进行读取,读取到空白字符会跳过,直至读到数字或者符号(+或-),会将这个数字字符进行保存,接着读下一个字符,当下一个字符是非空白字符,继续读取保存,直至读到空白字符停止下来。

3.png

倘若在这块输入空间最前头有某一个非空白非数字字符,遇到时将会读取,由于不是数字,将会还给输入空间。scanf继续读下一个字符,又读到这个非数字字符,以此往复,无法给变量进行赋值。

4.png


当我们了解这些之后,当我们有多个变量需要赋值,通常会用换行符空格进行对下一个变量的赋值。

当然,如果设定了字段宽度,scanf()会在字段结尾或第1个空白字符处停止读取(满足两个条件之一便停止)。

#include<stdio.h>
int main()
{
    int n;
   scanf("%2d",&n);
   printf("%d",n);
    return 0;
}


结果:

输入:2018

输出:20

当我们以这种形式输入时:

scanf(“%d,%d”,&n);

要严格按照格式字符串的格式进行输入

3,3

3 , 3

3,

3

这三种格式都行,只要带有逗号输入即可,倘若没有逗号,那么就会输出没有意义的值。

#include<stdio.h>
int main()
{
    int n,m;
   scanf("%d,%d",&n,&m);
   printf("%d %d",n,m);
    return 0;
}

2.png

scanf()的返回值

scanf()函数返回成功读取的项数。如果没有读取任何项,且需要读取一

个数字而用户却输入一个非数值字符串,scanf()便返回0。当scanf()检测

到“文件结尾”时,会返回EOF(EOF是stdio.h中定义的特殊值,通常用

#define指令把EOF定义为-1)。

所以当我们想要多次进行赋值时,可以用while语句,然后以等于EOF作为结束条件。在VScode(gcc)编译环境下以CTRL+z作为EOF。


#include<stdio.h>
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        printf("%d\n",n);
    }
    return 0;
}

1.png

返回值:

#include<stdio.h>
int main()
{
    int n,m;
   int sum=scanf("%d,%d",&n,&m);
   printf("%d ",sum);
    return 0;
}

daa25208c5e140988729e075d1aa92cf.png


相关文章
|
存储 传感器 Linux
Linux应用开发基础知识——I2C应用编程(十二)
Linux应用开发基础知识——I2C应用编程(十二)
972 0
Linux应用开发基础知识——I2C应用编程(十二)
|
数据安全/隐私保护
全球免费编程教育网站:Code.org
你还在为小朋友的编程教育而发愁吗? 你还在为小朋友放假无聊而头疼吗? 他来了他来了,全球免费编程教育网站来了。 2013年成立的Code.org是一个非营利组织。 它致力于为年轻女子、学生从来自少数民族提供机会。 其愿景是:每所学校的每位学生都有机会学习计算机科学,就像学习生物、化学和代数。 提供了最广泛讲授的中小学计算机科学课程,也会每年组织编程一小时活动。 这已吸引了全世界约 10% 的学生来参与。 Code.org 得到了亚马逊、脸书、谷歌、印孚瑟斯基金会、微软等更多慷慨捐助者的支持。
3075 0
|
Java Android开发 iOS开发
深入探讨移动操作系统的性能优化:安卓与iOS的对比分析
在现代移动设备中,操作系统的性能优化至关重要。本文从系统架构、内存管理、电池续航和应用程序运行效率等多个维度,深入探讨了安卓(Android)和iOS两大主流移动操作系统的优化策略及其实际效果,旨在为开发者和用户提供更清晰的了解和选择依据。
1980 27
|
存储 JavaScript 前端开发
ts简介和基本类型
ts简介和基本类型
|
安全 算法 数据安全/隐私保护
加密与安全:公开密钥加密、加密过程、数字签名等
这篇文章详细解释了非对称加密算法,包括公开密钥加密的原理、加密过程、数字签名的功能,以及它与对称加密的比较和实际应用场景。
加密与安全:公开密钥加密、加密过程、数字签名等
|
Linux Windows 内存技术
PCIe初始化枚举和资源分配流程分析
本文主要是对PCIe的初始化枚举、资源分配流程进行分析,代码对应的是alikernel-4.19,平台是arm64 ## 1. PCIe architecture ### 1.1 pcie的拓扑结构 在分析PCIe初始化枚举流程之前,先描述下pcie的拓扑结构。 如下图所示: ![11.png](https://ata2-img.oss-cn-zhangjiakou.aliyuncs
9278 1
PCIe初始化枚举和资源分配流程分析
|
搜索推荐 前端开发 C#
推荐7款美观且功能强大的WPF UI库
推荐7款美观且功能强大的WPF UI库
1877 2
|
存储 前端开发 rax
x64汇编语言与逆向工程基础指南(三)
x64汇编语言与逆向工程基础指南(三)
|
SQL 资源调度 关系型数据库
实时计算 Flink版产品使用问题之在使用Flink on yarn模式进行内存资源调优时,如何进行优化
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
前端开发 C#
wpfui:一个开源免费具有现代化设计趋势的WPF控件库
wpfui:一个开源免费具有现代化设计趋势的WPF控件库
914 0