目前是一名大二升大三的学生,早就有想法写博文了,但是因为自己的拖延一直到现在才开始着手。关于博文,我有以下打算:把C语言再重新过一遍,毕竟嵌入式开发C语言的重要性不言而喻;接下来我还会有一些关于单片机小项目的开源,打了两年电赛,可以和大家分享一下C51和STM32有趣的小项目;写博文的同时我也正在学linux操作系统,所以写以上博文的同时我也会写关于linux的博文,希望大家能够支持,互相学习,互相进步哈哈哈哈!
回归正题,本文是关于C语言中的数据形式及其输入输出,我总结的比较精炼,若有不足或错误的地方欢迎各位大佬批评指正。
什么是变量、常量
所谓变量,顾名思义变量表示其值在程序执行过程中是可以改变的,在C程序中,变量在使用之前必须先定义。一般形式:类型关键字 变量名;其中关键字就比如int、float,char等等,而变量名(也称标识符,这里注意一下,我初学C语言的时候这里卡壳了一会)就是由我们自己决定的,但是其也有其命名的规则,变量名由字母数字下划线组成,且只能以下划线或者字母开头,不能以数字开头,比如int a,int data,int _data等;而且要注意区分大小写,比如sum和SUM是两个变量;还有一个在嵌入式开发中比较重要的变量命名法——驼峰命名法,其讲究的就是顾名思义,就是我们看到这个变量名就能大概猜到其表示的意义,就如玩超声波的时候,我们会喜欢定义一个变量:(float distance;),一看就能知道这是超声波测出来的距离,方便我们阅读代码。
其实提到变量,我们肯定还会想到一个常量,但是常量没啥好说的,我就一笔带过吧。常量就在程序运行过程中其值不能改变的,对于一个我们在程序中经常会用的常量,我们通常会使用宏定义,比如#define PI 3.14,整个程序中就由PI代替3.14了,值得注意的是这个语句后面不需要分号。
什么是数据类型
引用数据类型主要目的是便于程序中对它们按不同方式和要求进行处理,不同的数据类型在内存中占不同大小的储存单元,比如int 一般占4个字节,32位,char一般占1个字节,8位等。C语言数据类型包括基本类型、构造类型、指针类型和无类型,本篇博文就先讨论基本类型:
数据类型分类 | 关键字 | 变量声明实例 | 占字节长度 | |
整形 | 基本整形 | int | int a; | 4 |
长整型 | long | long int a; / long a; | 4 | |
长长整形 | long long | long long int a; / long long a; | 8 | |
短整型 | short | short int a; / short a; | 2 | |
无符号整形 | unsigned | unsigned int a; unsigned long b; | 1/2/4/8 | |
实型(浮点型) | 单精度实型 | float | float a; | 4 |
双精度实型 | double | double a; | 8 | |
长双精度实型 | long double | long double a; | 16 | |
字符型 | char | char a; | 1 | |
枚举类型 | enum | enum color{red=1, oreange=2} | 较复杂,后面文章将详细讨论 |
此处涉及字节长度,就简单提一下sizeof这个运算符,要注意的是sizeof是C语言的关键字,不是函数名,专门用于计算指定数据类型字节数的运算符。使用形式:sizeof(变量名 / 关键字)
数据的输入输出
就数据的输出而言,分为两种,一种为原样输出,即printf("xxxxxx");第二种为含%占位符的输出。原样输出没啥好讲的,重点关注含%占位符的输出。其根据不同的数据类型选择不同的格式输出,比如输出整形:printf("%d",a),输出字符型:printf("%c",b)等。常见的数据类型对应的输出格式:%d—十进制整数,%c—单个字符,%s—多个字符,%f—小数,%x—十六进制,%p—一般打印内存地址,十六进制,%u—无符号十进制整形,%o—八进制等。
这里要注意一下浮点型的输出,其默认输出是保留6位小数,但我们也可以指定其输出格式:%m.nf,其中m表示总位宽,n表示保留几位小数。
如上图所示,7和14就是m,表示占多少位,m的值大于本身的位数时就在这个数前面补空格,记得小数点也占一位。大家肯定会想要是m的值小于本身的位数呢,我们在代码上实现一下:
大家可以看到当m的值小于本身的位数时输出就原来的位数,不过也和n有关,即保留几位小数有关。那我们再想一想,要是在m前面加一个-号呢,我们也在代码上实现一下:
大家肯定也发现了,好像没什么区别,确实在代码上体现的不是很明显,我就简单说一下吧,加了个-号我们就和没加-号对比一下嘛,没加-号会在前面补位,那加了-号就肯定是在后面补位的,大家记住就好啦。
接下来我们聊一聊输入,scanf和printf的用法差不多,其根据不同的数据类型选择不同的格式输输入,比如输入一个整形:scanf("%d",&a),字符型:scanf("%c",&b)等,有一个明显不同的地方就是多了个&符号,这个&符号代表取地址的意思,后续我们聊到指针的时候会详解。
针对scanf有几点需要大家注意的,我们来敲几行代码看看:
这种情况我们从键盘上依次输入10 12 14,以空格或回车隔开,输出的结果都是一样的,要是我们稍加修改一下呢:
我们在scanf中加逗号分开,显而易见不管我们是用空格隔开还是回车隔开,最终输出的都是错的,那我们应该怎样输入呢:
我们必须把逗号也加上,再举个例子:
对于上面这个程序我不做过多的解释了,总而言之:如果函数scanf()的格式控制字符串中存在除格式说明符以外的其他字符,那么这些字符必须在输入数据时由用户从键盘原样输入。
在这里我要补充一下用%c输入字符时存在的问题。
我们可以看到当scanf中有%c时,我们用之前空格或回车隔开都是不行的,因为在用%c格式读入字符时,空格字符和转义字符(包括回车)都会被当作有效字符读入。 那我们怎么解决呢:
这种方法就是输入数据时不加任何东西就连着输入,编译器会自己区分整形和字符的,当然还有其他方法:
这种方法就是在%c前面加一个空格,忽略前面数据输入时存入缓冲区中的空格或回车符,避免被后面的字符型变量作为有效字符读入。
我相信有的大佬肯定还想到了另一种方法—getchar,让我们来看看getchar是怎么实现的:
这是方法是用函数getchar()将数据输入时存入缓冲区的空格或回车符读入,避免被后面的字符型变量作为有效字符读入。
但是我认为第二种方法比第三种更简单,程序可读性也更好。
既然我们聊到了getchar()这个函数,我们也不妨来拓展一下getchar()、putchar()、puts()和gets(),其中gets()留到后面讲,我们先来简单聊一聊getchar()、putchar()和puts()。
函数getchar()没有参数,函数的返回值就是从终端键盘读入的字符,putchar()有参数,其参数就是要打印出来的字符,这两个函数针对的是一个字符。对于puts(),和printf()用法差不多,我们直接上代码:
简单总结一下puts()和printf()的区别:puts()自动加入了换行符;puts()只能是输入字符串。
好啦,本篇文章内容到这里差不多结束了,简单地讲了一下学习嵌入式开发需要掌握C语言的第一部分的内容,讲得比较浅显,有不足之处还是很期待各路大佬批评指正,欢迎大家在评论区交流,后续我还会不断更新的。最后本篇博文参考了C语言程序设计(第四版)这本书,还有上官可编程老陈老师的课。共勉。