创作不易,友友们给个三连吧
一、C语⾔的基本概念与发展历史
1.1 人和计算机进行交流的语言
通常,我们使用英语、中文等语言来进行两个人之间的交流。这意味着当我们想要和他人进行交流时,我们需要一种语言来表达自己的感受。同样的,当我们想要和计算机进行交流时,我们也需要一种语言,可以通过该语言向计算机提供信息,传达指令,我们称该语言为计算机语言。
然而C语言只不过是众多语言中的一种,像C++/Java/Go/Python都是计算机语⾔。
1.2 C语言的辉煌和历史
C 语⾔最初是作为 Unix 系统的开发⼯具⽽发明的。
类似的操作系统还有:windows、linux、macos(苹果)……
1.3“C生万物,编程之本”
C语言的四大领域:
游戏:目前很多游戏客户端都是基于C++开发的,除了一些网页游戏可能不是,所以如果想从事游戏开发行业学好C++是没错的。
服务器端开发:很多互联网公司的后台服务器程序都是基于C++开发的,而且大部分是linux,unix等类似操作系统。如果你想从事这样的工作,需要熟悉linux操作系统及其在上面的开发,熟悉数据库开发,精通网络编程。
数字图像处理:现在市面上有很多VC++图像处理的书籍,可见在这个领域的应用软件开发也是占了很大比重,需要深入学习数字图像处理和模式识别等课程。
虚拟现实仿真:这个也是发展很快的计算机领域,目前各种数字地球,数字城市,虚拟地理环境什么的,出现了这方面的大量应用
C语言出现时间较早,其他语言基本都是在C语言之后出现,或者在C语言的基础上进行创造,比如Java,C++是两门很有代表性的语言。
并且 学习了之后,语言的通用性还是存在的,所以在学习其他的语言的时候,学习起来就相对会简单一点。
TIOBE网站上可以查到每年编程语言的使用排名,其中c语言常见保持前3,
网址:https://www.tiobe.com/tiobe-index/
二、编译器的选择和使用方法
2.1 编译和链接
C语⾔是⼀⻔编译型计算机语⾔,C语言源代码都是文本文件,文本文件本身无法执行,必须通过编译器翻译和链接器的链接,生成二进制的可执行文件,可执行文件才能执行。(计算机识别的是二进制指令) C语⾔代码是放在 .c 为后缀的⽂件中的,要得到最终运⾏的可执⾏程序,中间要经过编译和链接2个过程。
⼀个工程⼀般都会有多个源文件组成,如下图所示,演示了源程序经过编译器和链接器处理的过程。
.c→.obj→.exe
⼀个工程⼀般都会有多个源文件组成,如下图所示,演示了源程序经过编译器和链接器处理的过程。
1. 每个源文件(.c)单独经过编译器处理⽣成对应的目标⽂件(.obj为后缀的⽂件)
2. 多个⽬标⽂件和库文件经过链接器处理⽣成对应的可执行程序(.exe⽂件)
2.2 编译器对比和选择
C语⾔是⼀⻔编译型的计算机语⾔,需要依赖编译器将计算机语⾔转换成机器能够执⾏的机器指令。
那我们常⻅的C语⾔编译器都有哪些呢? ⽐如:msvc、clang、gcc 就是⼀些常⻅的编译器,当然也有⼀些集成开发环境如:VS2022、 XCode、CodeBlocks、DevC++、Clion等。
集成开发环境(IDE):⽤于提供程序开发环境的应⽤程序,⼀般包括代码编辑器、 编译器 、 调试器 和 图形⽤⼾界⾯ 等⼯具。 集成了代码编写功能、分析功能、编译功能、调试功能等⼀体化的开发软件服务套。
• VS2022 集成了MSVC(安装报包较⼤⼀些,安装简单,⽆需多余配置,使⽤起来⾮常⽅便)
• XCode 集成了clang(苹果电脑上的开发⼯具)
• CodeBlocks 集成了gcc(这个⼯具⽐较⼩众,需要配置环境,不太推荐)
• DevC++ 集成了gcc(⼩巧,但是⼯具过于简单,对于代码⻛格的养成不好,⼀些竞赛使⽤)
• Clion 是默认使⽤CMake,编译器是可以配置的(⼯具是收费,所以暂时推荐⼤家使⽤)
• VSCode 具有强大的插件系统,可安装各种插件,来搭建c/c++的开发环境(不推荐新手使用)
新手推荐使用VS2022社区版本,免费并且使用方便。
2.3 VS的优缺点和下载方法
优点:
• VS2022 是⼀个主流的集成开发环境,企业中使⽤较为普遍
• VS2022 包含了:编辑器+编译器+调试器,功能强⼤
• 直接安装即可使⽤,基本不⽤额外配置环境,上⼿容易
• 默认界⾯是中⽂的,初学者友好
缺点:
• 功能丰富,安装包⼤,占⽤空间多。
下载方法:https://visualstudio.microsoft.com/zh-hans/downloads/
安装教程:https://www.bilibili.com/video/BV11R4y1s7jz/
2.4 VS项目和源文件、头文件介绍
在项⽬中就可以添加源⽂件和头⽂件。
C语⾔把 .c 为后缀的⽂件称为源⽂件,把 .h 为后缀的⽂件称为头⽂件。
2.5 在VS上创建新项目
2.5.1 写代码的前的步骤
1、创建项目(代码是在项目中管理的)
2、创建.c文件
3、写C语言代码,邀严格按照C语言的语法来写!!
2.5.2 项目名称
1、项目名称最好有自己的实际意义
2、项目名称最好不要使用后中文
3、不要使用特殊字符
2.5.3 项目存储路径
1、代码的位置邀自己找一个熟悉的路径维护起来
2、这个代码的路径不要包括空格、特殊字符、中文字符
三、main函数
每个 C 语⾔程序不管有多少⾏代码,都是从 main 函数开始执⾏的, main 函数是程序的⼊⼝, main 函数也被叫做:主函数。 main 前⾯的 int 表⽰ main 函数执⾏结束的时候返回⼀个整型类 型的值。所以在 main 函数的最后写 return 0; 正好前后呼应。
• main函数是程序的入口
• main函数有且仅有⼀个
• 即使⼀个项⽬中有多个.c⽂件,但是只能有⼀个main函数(因为程序的入口只能有⼀个)
• main函数可以出现在任意位置,若在主函数中调用的哪些函数,则必须在main函数之前对所调用的函数进行声明,或者包含其被调用函数的头文件
• 一般约定返回0,在c语言中正常在返回0,异常会返回非0
int main()
{
printf("hello C\n");
return 0;
}
在VS2022上运⾏代码的快捷键: Ctrl+f5
四、关键字介绍
C语⾔中有⼀批保留的名字的符号,⽐如: int 、 if 、 return ,这些符号被称为保留字或者关键 字。
• 关键字都有特殊的意义,是保留给C语言使用的
• 程序员自己在创建标识符的时候是不能和关键字重复的
• 关键字也是不能自己创建的。 C语言的32个关键字如下:
注:在C99标准中加⼊了 inline 、 restrict 、 _Bool 、 _Comploex 、 _Imaginary 等关键字。 ⼀些关键字⼤家可以去了解⼀下,不过使⽤最多的还是上⾯的32个关键字。
注:https://zh.cppreference.com/w/c/keyword(C语⾔关键字的全部介绍)
注: difine不是关键字,他是编译器实现的用来定义宏的预处理指令,不是c语言中的内容。
五、字符和ASCII编码
在键盘上可以敲出各种字符,如:a,q,@,#等,这些符号都被称为字符,C语⾔中字符是⽤单引号 括起来的,如:'a','b','@'。单个字符的打印可以使用%c来指定格式。
我们知道在计算机中所有的数据都是以二进制的形式存储的,那这些字符在内存中分别以什么样的⼆进制存储的呢?如果我们每个⼈⾃⼰给这些字符中的每个字符编⼀个⼆进制序列,这就叫做编码,为了⽅便⼤家相互通信,不造成混乱,后来美国国家标准学会(ANSI)出台了⼀个标准 ASCII 编码,C语言中的字符就遵循了ASCII 编码的⽅式。
参考:https://zh.cppreference.com/w/cpp/language/ascii
我们不需要记住所有的ASCII码表中的数字,使⽤时查看就可以,不过我们最好能掌握⼏组特殊的数据:
• 字符A~Z的ASCII码值从65~90
• 字符a~z的ASCII码值从97~122
• 对应的大小写字符(a和A)的ASCII码值的差值是32
• 数字字符0~9的ASCII码值从48~57 • 换⾏ \n 的ASCII值是:10
• 在这些字符中ASCII码值从0~31 这32个字符是不可打印字符,无法打印在屏幕上观察
• 字符其实也属于整型家族
比如:可打印字符展示(32-127)
#include <stdio.h>
int main()
{int i = 0;for (i = 32; i <= 127; i++){printf("%c ", i);if (i % 16 == 15)printf("\n");}return 0;
}
! " # $ % & ' ( ) * + , - . /
0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N O
P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o
p q r s t u v w x y z { | } ~
六、字符串和\0
使用双引号括起来的一串字符就被称为字符串,如:“abcdef”,就是一个字符串。
字符串的打印格式可以使用 %s 来指定,也可以直接打印如下:
#include <stdio.h>
int main()
{printf("%s\n", "hello C");printf("hello c");return 0;
}
C语⾔字符串中⼀个特殊的知识,就是在字符串的末尾隐藏放着⼀个 \0 字符,这个 \0 字符是字符串 的结束标志。
为了观察这一现象,我们要在调试中找到监视功能,它在VS2022里面的路径是:【调试】->【窗口】->【监视】,但当我们打开此路径,我们并没有找到监视的功能。
原因是:监视必须是代码在调试的条件下进行,所以按下ctrl+F10,开始调试程序,此时再来到刚才的路径,就能找到监视的窗口了。
左边出现箭头即为进入调试阶段
在进入调试状态后,比如想要监视某一个变量,添加本代码变量于监视窗口中添加完待监视项后,按f10 代码会一步一步运行,待监视项便也随着代码运行进行改变。
我们可以发现对于字符串"abcdef",我们实际上看到了6个字符:a,b,c,d,e,f,但是实际上在末尾还隐藏⼀个 \0 的 转义字符, \0 是字符串的结束标志。所以我们在使⽤库函数 printf() 打印字符串或者 strlen() 计算字符串⻓度的时候,遇到 \0 的时候就⾃动停⽌了。
监视窗口的优点:
1.便于理解代码,对代码工作原理运行顺序的理解都很有帮助
2.可以方便地在大型工作表中检查、审核或确认公式计算及其结果。. 使用“监视窗口”,无需反复滚动或定位到工作表的不同部分。
注:C语⾔中也可以把⼀个字符串放在⼀个字符数组中,我们在这里利用下⾯的代码验证⼀下 \0 的功能。
#include<stdio.h>
int main()
{char arr1[] = { 'a', 'b', 'c' };//arr1数组中存放3个字符char arr2[] = "abc"; //arr2数组中存放字符串printf("%s\n", arr1);//不含有/0,所以没有停止的标志,会一直输出下去,会出现一些随机值printf("%s\n", arr2);//含有/0,所以会输出到停止return 0;
}
abc烫烫烫烫烫烫烫烫烫烫烫烫烫烫蘟bc
abc
我们可以看到, arr1 字符数组在打印的时候,打印了 a 、 b 、 c 后还打印了⼀些随机值,这就是 因为 arr1 在末尾的地⽅没有 \0 字符作为结束标志,在打印的时候没有停⽌。
但是 arr2 的打印就是完全正常的,就是因为 arr2 数组是使⽤字符串常量初始化的,数组中有 \0 作为技术标志,打印可以正常停⽌。
如果我们在arr1数组中单独放⼀个 '\0' 字符呢?
#include<stdio.h>
int main()
{char arr1[] = { 'a', 'b', 'c' ,'\0'};//arr1数组中存放3个字符char arr2[] = "abc"; //arr2数组中存放字符串printf("%s\n", arr1);printf("%s\n", arr2);return 0;
}
abc
abc
则我们可以发现打印的结果是⼀样的了,都是打印到 \0 的时候就停⽌了,由此可以说明\0的作用以及重要性。
七、转义字符
也许在前⾯的代码中你看到 \n , \0 很纳闷时啥。其实在字符中有⼀组特殊的字符是转义字符,转义 字符顾名思义:转变原来的意思的字符。
C语⾔中像这样的转义字符,具体如下:
• \? :在书写连续多个问号时使⽤,防⽌他们被解析成三字⺟词,在新的编译器上没法验证了。
• \' :⽤于表⽰字符常量'(想打印单引号时用\将'转换成字符)
• \" :⽤于表⽰⼀个字符串内部的双引号(想打印双引号时用\将'转换成字符)
• \\ :⽤于表⽰⼀个反斜杠,防⽌它被解释为⼀个转义序列符。(相当于\\=1个\)
• \a :警报,这会使得终端发出警报声或出现闪烁,或者两者同时发⽣。
• \b :退格键,光标回退⼀个字符,但不删除字符。(覆盖前面那个字符)
• \f :换⻚符,光标移到下⼀⻚。在现代系统上,这已经反映不出来了,⾏为改成类似于 \v 。
• \n :换⾏符。
• \r :回⻋符,光标移到同⼀⾏的开头。
• \t :制表符,光标移到下⼀个⽔平制表位,通常是下⼀个8的倍数。(让输出的内容更美观和可读)
• \v :垂直分隔符,光标移到下⼀个垂直制表位,通常是下⼀⾏的同⼀列。
下⾯2种转义字符可以理解为:字符的8进制或者16进制表⽰形式
• \ddd :d d d表⽰1~3个⼋进制的数字。 如: \130 表示字符X(字符八进制的表示形式)
• \xdd :d d表⽰2个⼗六进制数字。 如: \x30 表示字符0(字符十六进制的表示形式)
• \0 :null 字符,代表没有内容, \0 就是 \ddd 这类转义字符的⼀种,⽤于字符串的结束标志,其 ASCII码值是0.
注: 关于转义字符我们首先要了解,然后要能在字符串中识别出来。(求字符串长度时,转义字符只占一个字节)
题型:求复杂字符串的长度
int main()
{printf("%zd\n", strlen("c:\test\130\test.c"));
}
13 因为\t和\130都只算1个字符
转义字符参考:https://zh.cppreference.com/w/c/language/escape
八、语句和语句分类
8.1空语句
空语句是最简单的,⼀个分号就是⼀条语句,是空语句。
#include <stdio.h>
int main()
{;//空语句return 0;
}
空语句⼀般出现的地⽅是:这⾥需要⼀条语句,但是这个语句不需要做任何事,就可以写⼀个空语句。
8.2表达式语句
表达式语句就是在表达式的后边加上分号。如下所⽰:
#include <stdio.h>
int main()
{int a = 20;int b = 0;b = a + 5; //表达式语句return 0;
}
8.3函数调用语句
函数调⽤的时候,也会加上分号,就是函数调⽤语句。
#include <stdio.h>
int Add(int x, int y)
{return x+y;
}int main()
{printf("hehe\n");//函数调⽤语句int ret = Add(2, 3);//函数调⽤语句 return 0;
}
8.4复合语句
复合语句其实就是前⾯讲过的代码块,成对括号中的代码就构成⼀个代码块,也被称为复合语句。
#include <stdio.h>
void print(int arr[], int sz) //函数的⼤括号中的代码也构成复合语句
{int i = 0;for(i=0; i<sz; i++){printf("%d ", arr[i]);}
}
int main()
{int i = 0;int arr[10] = {0};for(i=0; i<10; i++) //for循环的循环体的⼤括号中的就是复合语句{arr[i] = 10-i;printf("%d\n", arr[i]);}return 0;
}
8.5控制语句
控制语句⽤于控制程序的执⾏流程,以实现程序的各种结构⽅式(C语⾔⽀持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,C语⾔有九种控制语句。
可分成以下三类:
1. 条件判断语句也叫分⽀语句:if语句、switch语句;
2. 循环执⾏语句:do while语句、while语句、for语句;
3. 转向语句:break语句、goto语句、continue语句、return语句。
九、注释
注释是对代码的说明,编译器会忽略注释,也就是说,注释对实际代码没有影响。
注释是给程序员⾃⼰,或者其他程序员看的。
好的注释可以帮我们更好的理解代码,但是也不要过度注释,不要写没必要的注释。
当然不写注释可能会让后期阅读代码的⼈抓狂。 写注释⼀定程度上反应了程序作者的素质,建议⼤家写必要的注释,在未来找⼯作的时候,写代码时 留下必要的注释也会给⾯试官留下更好的印象。
第⼀种⽅法是将注释放在 /*...*/ 之间,内部可以分⾏。
注:这种注释⼀定不能忘记写结束符号 */ ,否则很容易导致错误。
注:/* */ 的这个注释不⽀持嵌套注释, /* 开始注释后,遇到第⼀个 */ 就认为注释结束了。
第⼆种方法是将注释放在双斜杠 // 后⾯,从双斜杠到⾏尾都属于注释。这种注释只能是单⾏,可以 放在⾏⾸,也可以放在⼀⾏语句的结尾。这是 C99 标准新增的语法。
注:不管是哪⼀种注释,都不能放在双引号⾥⾯。 双引号⾥⾯的注释符号,会成为字符串的⼀部分,解释为普通符号,失去注释作⽤。
注:编译时,注释会被替换成⼀个空格,所以(min/* 这⾥是注释 */Value) 会变成 min Value ,而不是 minValue 。
十、数据类型
C语⾔提供了丰富的数据类型来描述⽣活中的各种数据。
使⽤整型类型来描述整数,使⽤字符类型来描述字符,使⽤浮点型类型来描述⼩数。
所谓“类型”,就是相似的数据所拥有的共同特征,编译器只有知道了数据的类型,才知道怎么操作 数据。
10.1 字符型
char
[signed] char
unsigned char
10.2 整型
//短整型
short [int]
[signed] short [int]
unsigned short [int]
//整型
int
[signed] int
unsigned int
//⻓整型
long [int]
[signed] long [int]
unsigned long [int]
//更⻓的整型
//C99中引⼊
long long [int]
[signed] long long [int]
unsigned long long [int]
10.3 浮点型
float
double
long double
10.4 布尔类型
C 语⾔原来并没有为布尔值单独设置⼀个类型,⽽是使⽤整数 0 表⽰假,⾮零值表⽰真。
在 C99 中也引⼊了 布尔类型 ,是专门表示真假的。
_Bool
布尔类型的使⽤需要包含头⽂件<stdbool.h>
布尔类型变量的取值是:true或者false
10.5 自定义类型
C语言:自定义类型——结构体-CSDN博客
C语言:自定义类型——联合和枚举-CSDN博客
10.6 数据类型的长度
10.7 signed 和 unsigned
C 语⾔使⽤ signed 和 unsigned 关键字修饰字符型和整型类型的。
signed 关键字,表⽰⼀个类型带有正负号,包含负值;
unsigned 关键字,表⽰该类型不带有正负号,只能表⽰零和正整数。
整数变量声明为 unsigned 的好处是,同样⻓度的内存能够表⽰的最⼤整数值,增⼤了⼀倍。
C 语言规定 char 类型默认是否带有正负号,由当前系统决定。
所以 char 不等同于 signed char ,它有可能是 signed char ,也有可能是 unsigned char
这⼀点与 int 不同, int 就是等同于 signed int 。
十一、变量
类型是⽤来创建变量的。C语⾔中把经常变化的值称为变量,不变的值称为常量。
data_type name;| || |
数据类型 变量名
11.1 变量初始化
变量在创建的时候就给⼀个初始值,就叫初始化。
int age = 18;
char ch = 'w';
double weight = 48.0;
unsigned int height = 100;
11.2 变量的分类
• 全局变量:在⼤括号外部定义的变量就是全局变量
全局变量的使⽤范围更⼴,整个⼯程中想使⽤,都是有办法使⽤的。
• 局部变量:在⼤括号内部定义的变量就是局部变量
局部变量的使⽤范围是⽐较局限,只能在⾃⼰所在的局部范围内使⽤的。
int global = 2023;//全局变量
int main()
{int local = 2018;//局部变量printf("%d\n", local);printf("%d\n", global);return 0;
}
注意:局部变量和全局变量同名的时候,局部变量优先使⽤。
11.3 变量的命名规则和规范
1.一个变量名称可以由数字、字母、下划线、美元符号($) 组成
2.严格区分大小写
3.不能由数字开头,不要使用中文汉字命名
4.不能是保留字或者关键字
5.不要出现空格
十二、printf详细介绍
12.1 基本用法
printf() 的作⽤是将参数⽂本输出到屏幕。它名字⾥⾯的 f 代表 format (格式化),表⽰可以 定制输出⽂本的格式。头文件<stdio.h>
int main(void)
{printf("Hello World");return 0;
}
Hello World
printf() 不会在自动在行尾添加换行符,运⾏结束后,光标就停留在输出结束的地⽅,不会⾃动换行。 为了让光标移到下⼀行的开头,可以在输出文本的结尾,添加⼀个换行符 \n 。
12.2 占位符列举
• %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 类型。
• %% :输出⼀个百分号。
12.3 占位符的使用
printf() 可以在输出⽂本中指定占位符。 所谓 “占位符”,就是这个位置可以⽤其他值代⼊。
常⽤的占位符除了 %d ,还有 %s 表⽰代⼊的是字符串。
输出文本里面可以使用多个占位符!!!
int main()
{printf("%s says it is %d o'clock\n", "lisi", 21);return 0;
}
lisi says it is 21 o'clock 。
printf() 参数与占位符是⼀⼀对应关系,如果有 n 个占位符, printf() 的参数就应该有 n + 1 个。如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。
12.4 输出格式
printf() 允许限定占位符的最⼩宽度。
12.4.1 限定宽度
int main()
{printf("%5d\n", 123); // 输出为 " 123"return 0;
}
输出结果:“ 123”
上⾯⽰例中, %5d 表⽰这个占位符的宽度⾄少为5位。如果不满5位,对应的值的前⾯会添加空格。 输出的值默认是右对⻬,即输出内容前⾯会有空格;如果希望改成左对⻬,在输出内容后⾯添加空格,可以在占位符的 % 的后⾯插⼊⼀个 - 号。
int main()
{printf("%-5d\n", 123); // 输出为 "123 "return 0;
}
输出结果:“123 ”
对于小数,这个限定符会限制所有数字的最小显示宽度。
int main()
{printf("%12f\n", 123.45);return 0;
}
" 123.450000"
上⾯⽰例中, %12f 表⽰输出的浮点数最少要占据12位。由于小数的默认显示精度是⼩数点后6位, 所以 123.45 输出结果的头部会添加2个空格。
12.4.2 总是显示正负号
默认情况下, printf() 不对正数显⽰ + 号,只对负数显⽰ - 号。如果想让正数也输出 + 号,可 以在占位符的 % 后⾯加⼀个 + 。
int main()
{printf("%+d\n", 12); // 输出 +12printf("%+d\n", -12); // 输出 -12return 0;
}
+12
-12
上⾯⽰例中, %+d 可以确保输出的数值,总是带有正负号。
12.4.3 限定小数位数
输出小数时,有时希望限定⼩数的位数。举例来说,希望⼩数点后⾯只保留两位,占位符可以写 成 %.2f 。
int main()
{printf("Number is %.2f\n", 0.5);return 0;
}
Number is 0.50
这种写法可以与限定宽度占位符,结合使⽤。
int main()
{printf("%6.2f\n", 0.5);return 0;
}
" 0.50"
最⼩宽度和⼩数位数这两个限定值,都可以⽤ * 代替,通过 printf() 的参数传⼊。
int main()
{printf("%*.*f\n", 6, 2, 0.5);return 0;
}
// 等同于printf("%6.2f\n", 0.5);
" 0.50" 上述代码等同于printf("%6.2f\n", 0.5);
12.4.4 输出部分字符串
%s 占位符⽤来输出字符串,默认是全部输出。如果只想输出开头的部分,可以⽤ %.[m]s 指定输出 的⻓度,其中 [m] 代表⼀个数字,表⽰所要输出的⻓度。
int main()
{printf("%.5s\n", "hello world");return 0;
}
hello 占位符 %.5s 表⽰只输出字符串“hello world”的前5个字符,即“hello”。
12.5 printf的返回值
printf的返回值返回的是字符串中字符的数量(和strlen的返回值差不多,但是strlen的返回值是size_t,而printf的返回值是int)
int main()
{int a=printf("hello world\n");printf("%d\n", a);return 0;
}
hello world
12
十三、scanf详细介绍
13.1 基本用法
scanf() 函数⽤于读取用户的键盘输⼊。
程序运⾏到这个语句时,会停下来,等待⽤⼾从键盘输⼊。
⽤⼾输⼊数据、按下回⻋键后, scanf() 就会处理⽤⼾的输⼊,将其存⼊变量。
它的原型定义也在头⽂件 stdio.h , scanf() 的语法跟 printf() 类似。
scanf("%d", &i);
它的其余参数就是存放⽤⼾输⼊的变量,格式字符串⾥⾯有多少个占位符,就有多少个变量。 上⾯⽰例中, scanf() 的第⼀个参数 %d ,表⽰⽤⼾输⼊的应该是⼀个整数。 %d 就是⼀个占位 符, % 是占位符的标志, d 表⽰整数。第⼆个参数 &i 表⽰,将⽤⼾从键盘输⼊的整数存⼊变量 i 。
变量前⾯必须加上 & 运算符(指针变量除外),因为 scanf() 传递的不是值,⽽是地址, 即将变量 i 的地址指向⽤⼾输⼊的值。 如果这⾥的变量是指针变量(⽐如字符串变量),那就不⽤加 & 运算符。
scanf() 处理数值占位符时,会⾃动过滤空⽩字符,包括空格、制表符、换⾏符等。
所以,⽤⼾输⼊的数据之间,有⼀个或多个空格不影响 scanf() 解读数据。另外,⽤⼾使⽤回⻋ 键,将输⼊分成⼏⾏,也不影响解读。
scanf() 处理⽤⼾输⼊的原理是,⽤⼾的输⼊先放⼊缓存,等到按下回⻋键后,按照占位符对缓存 进⾏解读。 解读用户输⼊时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为⽌。
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;
}
输入: -13.45e12# 0
输出:-13
449999994880.000000
在上⾯⽰例中, scanf() 读取⽤⼾输⼊时, %d 占位符会忽略起⾸的空格,从 - 处开始获取数据,读 取到 -13 停下来,因为后⾯的 . 不属于整数的有效字符。这就是说,占位符 %d 会读到 -13 。 第⼆次调⽤ scanf() 时,就会从上⼀次停⽌解读的地⽅,继续往下读取。这⼀次读取的⾸字符 是 . ,由于对应的占位符是 %f ,会读取到 .45e12 (表示0.45*10^12),这是采⽤科学计数法的浮点数格式。后⾯的 # 不属于浮点数的有效字符,所以会停在这⾥。
13.2 scanf的返回值
scanf() 的返回值是⼀个整数,表⽰成功读取的变量个数。 如果没有读取任何项,或者匹配失败,则返回 0 。如果在成功读取任何数据之前,发⽣了读取错误或 者遇到读取到⽂件结尾,则返回常量 EOF。
13.3 占位符的使用
scanf() 常⽤的占位符如下,与 printf() 的占位符基本⼀致。
• %c :字符。
• %d :整数。
• %f : float 类型浮点数。
• %lf : double 类型浮点数。
• %Lf : long double 类型浮点数。 • %s :字符串。
• %[] :在⽅括号中指定⼀组匹配的字符(⽐如 %[0-9] ),遇到不在集合之中的字符,匹配将会停⽌。
13.3.1 %c
1、上⾯所有占位符之中,除了 %c 以外,都会⾃动忽略起首的空白字符。 %c 不忽略空⽩字符,总是返回当前第⼀个字符,无论该字符是否为空格。
2、如果要强制跳过字符前的空⽩字符,可以写成 scanf(" %c", &ch) ,即 %c 前加上⼀个空格,表⽰跳过零个或多个空⽩字符。
13.3.2 %s
1、占位符 %s ,它其实不能简单地等同于字符串。它的规则是,从当前第⼀个⾮空⽩ 字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)为⽌。
2、 因为 %s 不会包含空⽩字符,所以⽆法⽤来读取多个单词,除⾮多个 %s ⼀起使⽤。这也意味着, scanf( ) 不适合读取可能包含空格的字符串,⽐如书名或歌曲名。另外, scanf( ) 遇到 %s 占位符,会在字符串变量末尾存储⼀个空字符 \0 。
3、 scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度。所以,储存字符串时, 很可能会超过数组的边界,导致预想不到的结果。为了防⽌这种情况,使⽤ %s 占位符时,应该指定读⼊字符串的最⻓⻓度,即写成 %[m]s ,其中的 [m] 是⼀个整数,表⽰读取字符串的最大场度,后⾯的字符将被丢弃。
int main()
{char name[11];scanf("%10s", name);return 0;
}
上面实例中, name 是⼀个⻓度为11的字符数组, scanf() 的占位符 %10s 表⽰最多读取⽤⼾输⼊ 的10个字符,后⾯的字符将被丢弃,这样就不会有数组溢出的⻛险了。