C语言学习笔记06-占位符格式、C基本类型及逃逸字符一些细节(附介绍BCD码)

主要整理有关占位符格式与逃逸字符的一些细节

朋友们,看栗子——“BCD解码”

(文末附BCD码介绍)
一个BCD数的十六进制是0x12(对应二进制表示:0001 0010),它表达的就是十进制的12,但如果我没学过BCD,我就会把这个数当作一般的二进制数处理,对应成十进制的18。如何将错误处理后的十进制数改成正确的?先转回十六进制数0x12再重新转换出12。【思考:超出十进制数范围[0, 153]如何解决呢?】
实现代码:
在这里插入图片描述
在这里插入图片描述

1. 占位符格式作用说明

编程常用到的是%d,%u,%f,%c,%s,%#X。一般用多了就能记住使用规则。

%d 		十进制有符号整数 长整型%ld 短整型%hd;  64位整型适用:%I64d(只能MinGW)与%lld(只能Linux)
%i		和%d都是用来表达整数,但可以区分8进制0ooo、16进制0xhhh
%u 		十进制无符号整数 %lu    size_t类型用%zu或%u
%f 		浮点数  scanf double型%lf    long double型%Lf
%c 		单个字符
%s 		字符串(但C语言不支持定义字符串,用char[]字符数组代替)
%p 		指针的值(内存地址16进制)
%x, %X 	无符号以十六进制表示的整数(负数就是首位是1) %#x, %#X把0x或0X也输出显示,主要用于代码调试(字符串形式)
%o 		无符号以八进制表示的整数(字符串形式)
%e, %E 	以指数形式**输出**实数/浮点数,科学计数法(1,10)*10^n;scanf不能用
%g, %G 	根据浮点数的大小自动选择f格式或e格式

(1)格式的扩展:
形如%km.nf,f是占位符格式,m表示占位最小总宽度(超过则按实际输出),n表示小数点后保留位数,k是占位方式:(i)空格(右对齐,正前加空格,负加负号) ;(ii)+(右对齐,正加正号,负加负号);(iii) -(左对齐,负加负号正不加) ;(iv)0(右对齐,负加负号正不加,空位用0填)。

形如: ddd、0bBBB、0ooo、0xhhh、dddu、dddl、dddul、dddedL、d.df 用于直接表明数据的进制及类型,但后缀不可重复且要符合类型规范。大小写基本都行:u,U;l,L……
1e-8、1e-10可用于科学计数法。
对于直接给float变量赋值3.2在程序中自动认为3.2是double型的,如果是需要定义float型,赋值必须3.2f或3.2F。
参考:https://www.runoob.com/cprogramming/c-constants.html
(格式的具体演示)
在这里插入图片描述
在这里插入图片描述

(2)常见进制:二进制Binary(B),八进制Octal(O/Q),十进制Decimal(D),十六进制Hexadecimal(H),十六进制也多以0x或0X开头。
时钟-12/24进制、60进制,周7进制,军队排-连-营-团(3进制),农历年360进制,节气5进制(5日一候,72候)、3进制(3候一气,3气一节,一年8节,共24节气一轮回)。
题外话,道家-阴阳(二进制)、八卦(八进制,爻仍是二进制)、六十四卦(八卦两两相重),其中变化无穷无尽( 6464 * 26 )。
(3)相关进制转换方法(懂的都懂):
二进制速转八进制与十六进制用3/4位对1位的对应表;
进制转换常规做法:(i)其它进制转十进制直接各位加权求和处理;(ii)十进制转其它进制,整数部分除以进制权重(到商为0止)自下而上取余数,小数部分乘权重(小数部分0止)自上而下取整数,两段拼起来后标注进制就是最后结果。

2. C语言数据类型

2.1. 基本类型 / 数值类型(整数类型及浮点数类型)
(1)

数据类型		类型名		所占Byte数(与OS及软件位数相关)
(-----整数类型-----)
字符型		char			1    (C语言字符==数字)
短整型		short			2
整型			int				2/4    unsigned
长整型		long			4/8
长长整型		long long		8
(-----浮点数类型-----)
单精度型		float			4
双精度型		double			8/6/12/16
长双精度型	long double		8/16
(--------指针--------)
各类型指针					4/8

【C99新增long long、long double、bool型(stdbool.h, true 1, false 0),bool或_Bool占1个字节。】
逻辑类型(整数型)bool在C语言中的定义方式:宏定义、枚举或使用stdbool头文件。

类型越界问题思考:将有符号数和无符号数分别看成两类闭环,如有符号数char逆时针走从0 - 127- -128 - -1 - 0;无符号数unsigned char的逆时针闭环 0 - 255 - 0。

  *各常用类型表示范围:
char: -27 ~ 27 - 1, short: -215 ~ 215 - 1(-32768~32767)
int: -231 ~ 231 - 1(约正负21亿) (int和long与寄存器位数有关,整型最本质的类型就是 int或long 和 long long 两种)
unsigned int: 0 ~ 232 - 1

float: 字长32(cpu rigesters 总线),范围:正负1.210-38 ~ 3.41038 、0、正负inf(无穷大)、nan(Not A Number)。精度:6 ~ 7位。
double: 字长64,范围:正负2.210-308 ~ 1.7910308 、0、正负inf、nan。精度:15 ~ 16位。
float、 double计算方式标准IEEE754(1+8+23、1+11+52)(注意:原码、反码、 补码 、移码,计算机内存计算采用补码形式表示: -a补码本质就是2n - a(0-a) ,n是该类型位数;然而实际上,unsigned类型的二进制是计算机内部实际存储的样子,使用不同的类型只有在针对底层编程时存在位数和效率的限制下才真正有实际意义。)
long double有18、9位。
(浮点数超过精度时 四舍六入五奇进偶不进,因此可以看出计算机的数都是离散的。计算机无法真正表达一个实数,只能取最接近的数代替,二者之间存在误差 fabs(f2 - f1) <= 1e-12 不能直接f1 == f2 ,且计算误差会叠加,因此能精确计算的整数型在计算机中是非常必要的。)

bit *8 -> Byte(B) -> KB -> MB -> GB -> TB -> PB -> EB(210 = 1024)

Win7_x64系统下使用Devcpp_x86输出C语言数据类型字节数
(使用sizeof,还可以用来巧算数组长度lenth,C语言不能直接得出;sizeof是静态运算符,在sizeof中的计算是无效的,如:sizeof(++a),++a没有做):

#include <stdio.h>
#include <stdlib.h>
#include <string.h> //strcpy copy    字符串长度strlen    memset
using namespace std;

typedef long long ll;
#define N 12
//结构体
typedef struct Occupied_Bytes
{
	char name[13]; //end'\0' >=13    EOF~-1
	int bytes;
}Occ_B; //重定义的结构名

int main()
{
	Occ_B Array1[N] = {
	{"char:", sizeof(char)},
	{"short:", sizeof(short)},
	{"unsigned:", sizeof(unsigned)},
	{"int:", sizeof(int)},
	{"long:", sizeof(long)},
	{"long long:", sizeof(long long)},
	{"float:", sizeof(float)},
	{"double:", sizeof(double)},
	{"long double:", sizeof(long double)},
	{"char*:", sizeof(char*)},
	{"int*:", sizeof(int*)},
	{"double*:", sizeof(double*)}
	};
	int oArray1_Lenth = sizeof(Array1) / sizeof(Array1[0]); //算数组长度
	printf("共%d种类型\n", oArray1_Lenth);
	//strcpy(Array1[0].name, "char:"); //给结构体内数组赋值及修改的标准方式
	//Array1[0].bytes = sizeof(char);
	Occ_B* p = Array1; //C99允许代码中间定义  &Array1[0]
	for (int i = 0; i < oArray1_Lenth; i++, p++) { //OOL C++支持直接在此处定义变量
		printf("%s\t%d\n", p->name, p->bytes); //*p.name, *p.bytes 结构体变量.成员 ->结构体指针
	}
	p = NULL; //用完指针习惯置空 if(p != NULL){}
	
//	printf("char\t%d\n", sizeof(char));
//	printf("short\t%d\n", sizeof(short));
//	printf("unsigned\t%d\n", sizeof(unsigned));
//	printf("int\t%d\n", sizeof(int));
//	printf("long\t%d\n", sizeof(long));
//	printf("long long\t%d\n", sizeof(long long)); //ll
//	printf("float\t%d\n", sizeof(float));
//	printf("double\t%d\n", sizeof(double));
//	printf("long double\t%d\n", sizeof(long double));
//	//pointer  x32--4    x64--8
//	printf("char*\t%d\n", sizeof(char*));
//	printf("int*\t%d\n", sizeof(int*));
//	printf("double*\t%d\n", sizeof(double*));
	system("pause");
	
	return 0;
}

在这里插入图片描述

C语言关键字 / 保留字查询链接(菜鸟):https://www.runoob.com/cprogramming/c-basic-syntax.html

(2)数据类型转换:计算时自动转向精度更高或占字节更大的,int还可转成float。另外就是,强制类型转换,语法如下:(强制要转成的类型)值 ,遵循就近原则,必要时整体加()。强制转换没有改变变量。【printf函数会把小于int型的自动转成int,%d,float会被自动转成double,%f,在printf中用其它格式反而会降低效率 ; scanf不行,因此scanf需要严格选用格式字符,%f,%lf,%hd等。】

2.2. 枚举类型
枚举类型(离散整数值的变量)enum x {a , b }; //默认首个从0开始。如果有赋值,则从赋值的变量往后顺次递增数值直到重新出现赋值。【详细说明见C语言学习笔记11常量定义】

2.3. void类型
void空类型
函数返回空、函数参数空、指针指向空

2.4. 派生类型
数组[]、函数{}、指针*、结构体 struct、共用体 typedef union
注意:不同类型的指针在32位系统中(OS或软件)都占4union个字节,与内存有4G个编号相关,16位系统就是占2个字节,64位应占8个字节。

3. 逃逸字符

逃逸字符,也叫转义字符(python中转义字符),以反斜杠\开头。

符号	含义
\'	 '
\"	 "
\r	回车
\n	换行
\b	退格
\t	水平制表符(TAB)
\v	垂直制表符
\f	翻页
\\	\
\a	响铃警告(BEL)
\0	空字符NULL
\?	?
\ooo	1~3位八进制数所代表的任意字符(0~127)
\xhh	十六进制所代表的任意字符
 
打印百分号
%%	 %

常用ASCII码(占一个字节,共8bit,首位是0,使用7位表示0~127),扩展ASCII码使用8位(新增希腊符号等)
常用ASCII码值记忆:

0   NULL
10  '\n'
27  esc
32	space
48~57	0~9
65~90	A~Z
97~122	a~z

具体详情可查表: https://www.asciim.cn/
注:EOF值为-1,不会出现在ASCII码中,故可以用来表示文本结束。while(scanf(“%d”,&x) != EOF) //EOF ctrl+Z结束 可能需要三次ctrl+Z。   如果是 while(x != EOF) //EOF -1 输入-1就结束。

附:BCD码介绍

最后,简要介绍一下BCD码。
我们最熟悉的8421码是BCD码的一种,BCD码全称是Binary Coded Decimal ,即意为二进制编码十进制。8421码就是用4个二进制位从高到低各位的1分别表示十进制的8、4、2、1四个值(8421码表示十进制0 ~ 9的值,本身不会用来表示十六进制的10 ~15。当然我们计算自然二进制数时也可以借助8、4、2、1快速求值)。与8421码类似的还有5211码、2421码,这些属于有权码或叫恒权码。
BCD码还有另外一种类型(无权码)如:余3码、格雷码(工程中常用):
(1)8421码的余3码就是在8421码的结果基础上加3,主要用以校验。如8421码的余3码是用0011(原8421码0000)表示0,0100(0001)表示十进制的值1。格雷码的余3码也是一样,它取格雷码的3 ~ 12来表示0 ~ 9。
(2)格雷码(循环码),我学习时的发现:在十进制0~15的变化过程中,它与自然二进制数的对应关系为:只有遇到自然二进制数位0变1的位时格雷码的对应位也由0变1或1变0,这样保证了格雷码任意两个相邻的代码只有1位二进制数不同。
那么,将自然二进制码转成二进制格雷码的具体法则是:(i)保留二进制码的最高位作为格雷码的最高位;(ii)将二进制位的最高位与次高位做异或运算得出格雷码的次高位;(iii)格雷码的其余位求法与(ii)中类似,由二进制位之后各位顺次异或得出。

十进制数二进制数格雷码
000000000
100010001
200100011
300110010
401000110
501010111
601100101
701110100
810001100
910011101
1010101111
1110111110
1211001010
1311011011
1411101001
1511111000
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值