第三章 处理数据 C++ Primer Plus 2018_3_6

本文深入浅出地介绍了C++的基本数据类型及其特点,包括整型、浮点型等,并探讨了面向对象编程的核心理念及其实现方式。同时,文章还详细解释了sizeof()与strlen()的区别和联系,以及C++中的变量初始化方法。
博主精要总结:


第三章


一 本章内容包括:

                                                                                                                             

  1.  面向对象的本质是什么?
  2.  C++基本数据类型
二 知识点:
                                                                                                                             


1 OPP编程本质是什么?

面向对象编程本质:设计扩展自己的数据类型

”C++ 面向对象 的编程,强调的是 数据 ,其理念是 设计 与问题本质特性相对应的 数据格式 ......“
详见链接---点击打开链接

2 C++基本数据类型

代码即是正义  奋斗奋斗
【整型】

    内置C++类型分两种:基本和复合类型

    基本类型包括整数、浮点数;复合类型包括数组、字符串、指针、结构等。

    整型(小->大):bool、 char、 signed char、 unsigned char、 short、 unsigned short、 int 、unsigned int、 long、unsigned long

    举例:假设char为1byte,则unsigned char 0~255,而signed char -128~0~127 。虽然对于一个字节都是2^8=256个数,但是就数值表示范围而言,无符号unsigned要比有符号signed类型大得多。

   

【补充1】sizeof() 与 strlen()
sizeof() 与 strlen()的联系与区别

  效率作用参数
sizeof(形参)运算符、关键字编译器在编译阶段执行,效率高

用于测量类型或对象所占的内存字节,可以和除法组合用来测出数组中成员的个数或者字符串个数等。

可以是 任何类型,且它本身也可以作为形参使用
unsigned int strlen(const char* string)函数编译器在运行阶段,该函数被调用到才执行,效率低返回字符串的个数,遇到第一个'\0'结束且字符'\0'不包含在内。必须是const char* 类型的形参,且它本身也可以作为形参使用

          

        运行:


        代码:VS13

#include <iostream>
#include <string>

using namespace std;

struct Stu
{
	int a;
	char b;
	long c;//long在WIN7 VS13中测试居然是4bytes!!!
};//我猜是20bytes---打脸,实际结果是12bytes

class Stu2
{
private:
	int m_a;
	char m_b;
	long m_c;
public:
	void set(int a,char b,long c);
};
void Stu2::set(int a, char b, long c){
	m_a = a;
	m_b = b;
	m_c = c;
}


int main()
{
	Stu test = {1,'2',3};
	Stu2 test2;
	test2.set(4,'5',6);
	
	string str = "haha";
	const char* cstr = "haha";
	const char* cstr2 = "hahaxixi";

	int array[] = { 1, 2, 3, 4, 5, 6 };

	/*【1】sizeof可对结构体变量、类示例化的对象的子字节大小测量*/
	cout << "结构体变量  sizeof(test) = " << sizeof(test) << endl;
	cout << "类实例化的对象 sizeof(test2) = " << sizeof(test2)<<endl;

	int a = 7; char b = '8'; long c = 9;
	cout << "int a =" << sizeof(a) <<" "; 
	cout << "char b =" << sizeof(b) << " ";
	cout << "long c =" << sizeof(c) << " "<<endl;

	cout << "sizeof ((int a = 7) + (char b = '8') + (long c = 9))为" << sizeof(a) + sizeof(b) + sizeof(c) << endl;


	/*【2】sizeof可对string类型的变量进行字节大小测量吗?测验知,可以。但string类的变量所占字节远大于const char*定义变量所占的4个字节*/
	cout << "/*******************************************************/"<<endl;
	//尝试看看string类型的变量是否可以具体计算出其字节大小或者字符个数
	cout << "string类型变量  sizeof(str) = " << sizeof(str)<<endl;
	//cout << "string类型变量  strlen(str) = " << strlen(str) << endl;//报错:string类型无法转换到const char*类型
	cout << "const char*类型变量 sizeof(cstr) = " << sizeof(cstr)<<endl;
	cout << "const char*类型变量 sizeof(cstr2) = " << sizeof(cstr2) << endl;

	/*【3】strlen只可以对const char* 类型变量进行测量,即strlen()只可以测量字符串中字符的个数*/
	cout << "/*******************************************************/" << endl;
	//cout << "string类型变量  strlen(str) = " << strlen(str) << endl;//参数str回报错,因为strlen()只接受const char*类型的参数
	cout << "const char*类型变量 strlen(cstr) = " << strlen(cstr) << endl;
	cout << "const char*类型变量 strlen(cstr2) = " << strlen(cstr2) << endl;


	/*【4】strlen本身可作参数使用*/
	cout << "/*******************************************************/" << endl;
	//strlen本身能否作为参数使用呢?试试看
	cout << "结构体变量  sizeof(strlen(cstr)) = " << sizeof(strlen(cstr)) << endl;//显然可以

	/*【5】数组成员的个数sizeof(array)/sizeof(int)*/
	cout << "/*******************************************************/" << endl;
	cout << "sizeof(array)/sizeof(int) 即数组成员的个数为:" << sizeof(array) / sizeof(int) << endl;;
	
	system("pause");
	return 0;
}

   

【补充2】将信息保存到计算机中的一般型策略
为将信息存储到计算机中,谨记两条准则:存什么?存哪里? 一般采用的策略是:使用变量

   

变量类型        变量值变量名
  代指内存单元
举例:int a = 10;  
int类型10a
这些语句告诉程序,去找一块存储整型变量的内存单元把5复制进去,并将该内存单元标识为a,以供访问
标识数据的其她方法:&指针
  注意:定义变量名时,只能是字母、下划线、数字,且不能用数字开头,不能用C++关键字作为名字等

        --- 变量三要素:类型、值、名

        ---常用命名风格:my_lucy or myLuck

        ---常用前缀:str(字符串)、p(指针)、c(单字符)、b(表示布尔)、m_happy(类成员变量)

【补充3】预处理

预处理指令:#include #define等

在C++编译过程中,先将源代码传递给预处理器进行预处理。再编译、连接、运行。

【补充4】变量、数组、结构体 在C++中的不同初始化方法
C++11 大括号{}初始器可用于任何数据类型(等号可用可不用),这是一种通用初始化语法。

    运行结果:


    

    代码:

#include <iostream>
#include <string>

using namespace std;

struct Stu
{
	int a;
	char b;
	long c;//long在WIN7 VS13中测试居然是4bytes!!!
};//我猜是20bytes---打脸,实际结果是12bytes

class Stu2
{
private:
	int m_a;
	char m_b;
	long m_c;
public:
	void set(int a,char b,long c);
};
void Stu2::set(int a, char b, long c){
	m_a = a;
	m_b = b;
	m_c = c;
}

//非正文
void sizeofStrlen()
{
	
	Stu test = {1,'2',3};
	Stu2 test2;
	test2.set(4,'5',6);
	
	string str = "haha";
	const char* cstr = "haha";
	const char* cstr2 = "hahaxixi";

	int array[] = { 1, 2, 3, 4, 5, 6 };

	/*【1】sizeof可对结构体变量、类示例化的对象的子字节大小测量*/
	cout << "结构体变量  sizeof(test) = " << sizeof(test) << endl;
	cout << "类实例化的对象 sizeof(test2) = " << sizeof(test2)<<endl;

	int a = 7; char b = '8'; long c = 9;
	cout << "int a =" << sizeof(a) <<" "; 
	cout << "char b =" << sizeof(b) << " ";
	cout << "long c =" << sizeof(c) << " "<<endl;

	cout << "sizeof ((int a = 7) + (char b = '8') + (long c = 9))为" << sizeof(a) + sizeof(b) + sizeof(c) << endl;


	/*【2】sizeof可对string类型的变量进行字节大小测量吗?测验知,可以。但string类的变量所占字节远大于const char*定义变量所占的4个字节*/
	cout << "/*******************************************************/"<<endl;
	//尝试看看string类型的变量是否可以具体计算出其字节大小或者字符个数
	cout << "string类型变量  sizeof(str) = " << sizeof(str)<<endl;
	//cout << "string类型变量  strlen(str) = " << strlen(str) << endl;//报错:string类型无法转换到const char*类型
	cout << "const char*类型变量 sizeof(cstr) = " << sizeof(cstr)<<endl;
	cout << "const char*类型变量 sizeof(cstr2) = " << sizeof(cstr2) << endl;

	/*【3】strlen只可以对const char* 类型变量进行测量,即strlen()只可以测量字符串中字符的个数*/
	cout << "/*******************************************************/" << endl;
	//cout << "string类型变量  strlen(str) = " << strlen(str) << endl;//参数str回报错,因为strlen()只接受const char*类型的参数
	cout << "const char*类型变量 strlen(cstr) = " << strlen(cstr) << endl;
	cout << "const char*类型变量 strlen(cstr2) = " << strlen(cstr2) << endl;


	/*【4】strlen本身可作参数使用*/
	cout << "/*******************************************************/" << endl;
	//strlen本身能否作为参数使用呢?试试看
	cout << "结构体变量  sizeof(strlen(cstr)) = " << sizeof(strlen(cstr)) << endl;//显然可以

	/*【5】数组成员的个数sizeof(array)/sizeof(int)*/
	cout << "/*******************************************************/" << endl;
	cout << "sizeof(array)/sizeof(int) 即数组成员的个数为:" << sizeof(array) / sizeof(int) << endl;;
	
}

int main()
{
	//非正文
	//sizeofStrlen();//正确
	//void sizeofStrlen();//错误//为什么加了void没有任何输出而不加则能正常使用呢?void到底什么作用?
	/*
		void的字面意思是空类型,void *的意思是空类型指针,void 不是一个真正的类型,我们在声明变量的时候从来不会像下面这样声明:
		void a;
		如果我们写了一行这样的代码,某些编译器会直接报错,有些则不会,但也没有任何意义。
		void真正的用途在下面两个方面:
		对函数返回值的限定
		对函数参数的限定
		比如,函数没有返回值,那么函数可能会声明成这样:void fun(int a);
		如果函数有返回值,但是函数没有参数,那么函数的可能会声明成这样:int fun(void)。
		以上的情况都是很好理解的。下面介绍void *的一些用法。
	*/

	//正文:

	/*【1】C++变量、数组、结构体赋值其他方法*/

	//变量
	int a{ 7 }; cout << " a = " << a << " ";
	int b = { 14 }; cout << " b = " << b << " ";
	//{}中什么也不写,表示初始化为0
	int c{}; cout << " c = " << c << " ";
	int d = {}; cout << " d = " << d << " "<<endl;
	
	//数组
	int array2[]{ 6, 5, 4, 3, 2, 1 };
	cout << " 数组array2 = ";
	for (int i = 0; i < sizeof(array2) / sizeof(int); i++)
		cout << array2[i];
	
	//结构体
	Stu e{ 1, '2', 3 }; cout << " 结构体 " << e.a << " " << e.b << " " << e.c << " " << endl;
	

	/*【2】补充:如何输出字符串、数组*/
	
	//方法1:
	char* cstr = "xox";
	cout << " 字符串 ";
	for (; *cstr != '\0'; cstr++)
		cout << *cstr;
	cout << endl;

	//方法2:
	int array[] = { 6, 5, 4, 3, 2, 1 };
	cout << " 数组array = ";
	for (int i = 0; i < sizeof(array) / sizeof(int); i++) 
		cout << array[i];
	
	//错误例子:
	//int array[]{1, 2, 3, 4, 5, 6}; int* p = array;
	//cout << " 数组array = "; 
	//while (*p++ != '\0') cout << *p;//报错//原因:array是数组并不是字符串,她的最后一个的后一个成员array[6]其值是一个未知数

	system("pause");
	return 0;
}


【补充5】溢出

无符号、有符号类型所表示的最大数值范围 以及 发生上溢或者下溢时的情况:

自加的话,

无符号类型变量取值范围:0 -> max - 1 -> 0 循环下去  

有符号类型变量取值范围:-|min| -> 0 -> max - 1 -> -|min| 循环下去

    运行结果:



    代码:

#include <iostream>
#include <string>

using namespace std;

void yiChu()
{
	/*【1】无符号、有符号类型所表示的最大数值范围 以及 发生上溢或者下溢时的情况*/
	//自加的话,无符号类型变量取值范围:0 -> max -> 0 循环下去   有符号类型变量取值范围:-|min| -> 0 -> max - 1 -> -|min|  循环下去

	//无符号 上溢
	unsigned short Num0, Num1 = 65535, Num2 = 65536, Num3 = 0;
	Num0 = Num1 + 1;
	cout << "无符号类型:" << endl;
	cout << "Num1 = " << Num1 << " " << "Num2 = " << Num2 << " " << "Num3 = " << Num3 << " " << endl;
	cout << "Num0 = Num1 + 1 则 Num0 = " << Num0 << endl;

	//有符号 上溢
	short Num4 = -32768, Num5 = 32767, Num6 = 32768;
	cout << "有符号类型:" << endl;
	cout << "Num4 = " << Num4 << " " << "Num5 = " << Num5 << " " << "Num6 = " << Num6 << " " << endl;
	cout << "Num5 + 1 = " << short(Num5 + 1) << endl;
	//cout << "Num5 + 1 = " << Num5 + 1 << endl;//没有报错 但是结果不是想要的//解决方法:方法1---定义一个short的临时变量temp,temp = Num5 + 1  方法2---强制类型转换 (short)Num5 + 1
	//原因:本来Num5是short类型的,结果写成这样Num5 + 1之后,因为没有明确给出Num5 + 1的类型,所以计算机会按自己最舒服的int来默认Num5 + 1的类型,所以本该输出为0的却正常+1输出

}
int main()
{
	//正文
	yiChu();

        system("pause");
	return 0;
}

【补充6】计算机最喜欢哪种类型的值?

显然int计算机认为最舒服的值

    “通常,int被设置为对目标计算机而言最为‘自然’的长度。自然长度指的是计算机处理起来效率最高的长度。如果没有非常有说服力的理由来选择其他类型,则应使用int。” ---C++ Primer Plus 第六版 3.1.5选择整形类型

【补充7】如何用十进制、八进制、十六进制输出一个数?

    运行结果:



    代码:

#include <iostream>
#include <string>

using namespace std;

void cou()
{

	/*【1】不论十进制也好,八进制、十六进制也罢,最终都是以二进制存放在计算机里*/

	int a = 15, *p = &a;

	cout << *p << "(十进制)" << endl;

	cout << oct << *p << "(八进制)" << endl;

	cout << hex << *p << "(十六进制)" << endl;

}

int main()
{
	//正文
	cou();

	system("pause");
	return 0;
}


【补充8】不同操作系统对基本类型宽度定义不同

不同OS对int等类型的宽度 表示不同,老式IBM PC机int宽度2bytes,现在的常见OS将int宽度表示为4bytes。


【char类型:字符和小整数】

char类型是整型的一种,专为存储字符(如字母和数字)而设计。注意在数值上,unsigned char 和 signed char的差异。(前者:0~256,后者:-128~127)

    ”char类型是整型的一种,专为存储字符(如字母和数字)而设计的。它足够长,能表示目标计算机系统中所有的基本符号---所有的字母、数字、标点符号等。实际上,很多系统支持的字符都不超过128个,所以一个字节足够用。因此,虽然char常被用来处理字符,但也可以用作比short更小的整型。"---C++ Primer Plus 第六版 3.1.8 char乐享:字符和小整数

 

    疑问:如何在C++中使用C代码的风格来解决判断字符是否相等的问题???

    ---已尝试用strcmp(),但是仍不奏效!

    运行结果:

   


    代码:

#include <iostream>
#include <string.h>
#include <string>

using namespace std;

void char_()
{
	/*【01】cin、cout都是智能对象 cout.put()只可以对单个字符进行输出,cout既可以输出单个字符也可以输出字符串。*/
	//并且单个字符经过cin输入之后可以参与算术运算,运算结束后,当被cout输出时,以字符形式输出到屏幕上
	//cin输入时字符会自动转换成相应的ASCII码值被处理,cout输出时又会根据ASCII表自动转成相应字符输出
	
	char ch, temp = '0';
	int num = -1;

	while (1)
	{
		cout << "请输入一个字符: ";//输入A  下面会用到
		cin >> ch;//cin之后的ch已经转换成整型数,可进行算术运算,单cout输出时会自动转换成字符,除非先进行算术运行然后再cout。

		cout << "输入的字符为:";
		cout<<ch;
		printf("---ASCII码值为:%d\n", ch); 
		
		//A 65  Z 90
		cout.put(ch);	
		//算术运算
		ch = ch + 25;
		cout << "后第25个字母为:";
		cout.put(ch);
		printf("---ASCII码值为:%d\n", ch);

		cout << "*********************" << endl;
		
		//算术运算
		ch = ch - 25;
		cout <<"ch - 25 = "<< ch << endl;

		//犯的这两个错误没有报错,但是运行结果都不是我想要的,第一个想了一会才想明白原因,第一个通过断点调试才解决。如下:
		//error1:char ch;if(ch == '0'){...} //原因:对于C语言风格的char而言,string类中的==运算符它是不能使用的,可以使用C语言风格的函数strcmp(&ch,&...)进行比较
		//error2:char ch;if (ch == 48){...} //原因:致命错误 逻辑上,我把判断语句放在了ch = ch + 25;语句后面 导致ch的值+25 !!!

	}
}

int main()
{
	char_();

	system("pause");
	return 0;
}

【浮点数】
  • 何为浮点数?

    通过缩放因子移动小数点的位置,进而改变原数值的数叫做浮点数

    例如:3.14 基准值是3 若缩放因子为10^3的话 则小数点右移3位 则结果为3140; 反之若缩放因子为10^-3的话,则左移。

    运行结果:

    代码:

#include <iostream>
#include <string.h>
#include <string>

using namespace std;

int main()
{
	//一些浮点数
	cout << "一些浮点数:" << endl;
	cout << "2.66e2=" << 2.66e2 << endl;
	cout << "6.99e+3=" << 6.99e+3 << endl;
	cout << "8.88E-4=" << 8.88E-4 << endl;
	cout << "9.11e-31=" << 9.11e-31 << endl;

	system("pause");
	return 0;
}

【浮点型】

若不强调类型,对于浮点数C++会默认为double类型。

在精度上,float类型要比double类型低。若在小数点后的某一位上(float已经精确不到但是double能够精确到的位置上),将浮点移到该位置上,float(double等等也类似)的精度只能表示到该位(其实通过下面的代码测试,在VS13 C++11版本中,无论float、double、long double,她们都只精确到有效位第六位)之前,若在该位之后对float类型的浮点数进行+ or - (要考虑到进位和四舍五入进位的情况)则该浮点数不变。

例子:

    运行结果:


    代码:

	int main{
        cout << "float所占字节数:" << sizeof(float) << endl;//4bytes  2^32 = 4294967296   有符号:-2147483648 ~ 2147483647

	float a = 2147483646,b = 0.0f;
	cout << "float a = 2147483646 则a = " << a << endl;//输出 2.14748e+009
	//显然,从上面的结果可见float类型的变量只精确到有效位的第6位
	//那么,我将对有效位第7位进行+法  看看结果是不是有什么变化(不产生进位,也不产生四舍五入的进位)
	b = a + 1000;
	cout << "float b = a + 1000; 则b = " << b << endl;//结果没有变化 输出 2.14748e+009
	
	system("pause");
	return 0;
        } 

【运算符】

+ - * /  %

/ 取整取余结合使用多位数的 各个位上的位数

% 两个操作数必须是整数    若 % 的两个操作数中有一个负数,取模结果仍为正

    运行结果:


    代码:

#include <iostream>
#include <string.h>
#include <string>

using namespace std;

int main()
{
        int a = 0;
	a = 20 % (-11);
	cout << a << endl;
	cout << (20 / 9) << endl;
	cout << (20.0 / 9) << endl;//精度被限制为6位有效数字

	float b = 3.0;
	b = 20 / b;
	cout << b << endl;//精度被限制为6位有效数字

	double c = 3.0;
	c = 20 / c;
	cout << c << endl;//精度被限制为6位有效数字

	float d = 3.0;
	d = 20 / d;
	cout << d << endl;//精度被限制为6位有效数字

        system("pause");
        return 0;
}

【强制类型转换】

没问题:精度小的类型 -> 精度大的类型

存在问题:精度大的类型 -> 精度小的类型

哪些问题: 精度降低(如double -> float)、丢失小数部分(如float -> int)、编译器不会报错但是错误很严重截断常量值(如int -> short)

    运行结果:



    代码:

#include <iostream>
#include <string.h>
#include <string>

using namespace std;

int main()
{
cout << "sizeof(short) = " << sizeof(short) << "   sizeof(int) = " << sizeof(int) << endl;
	//sizeof(short) = 2 ---  -32678 ~ 32677
	//sizeof(int) = 4 ---  -2147483648 ~ 2147483647

	//下面让int -> short 看看截断常量值是什么情况
	int a = 2000000000;
	short b = 20000;
	b = a;//结果:-27648 //常量值显然被截断

	cout << "b = " << b << endl;

        system("pause");
	return 0;
}

【const限定符】

使用关键字const比使用宏定义define能够更好地处理符号常量

const作用:定义常量、修饰函数参数、修饰函数返回值。被其修饰的东西可以受到强制保护,以预防意外改动,能提高代码健壮性。

与define相比const的优点

  • const能指明数据类型(包括复杂的数据类型),而define无法指明数据类型。
      这样就导致编译器可以对前者进行数据类型的安全检查,而对后者只进行宏替换没有类型安全检查,后者因此有可能会产生意料不到的错误。
  •  某些集成化的调试工具以对const常量进行调试,但不能对宏常量进行调试。

三 总结
                                                                                                                             






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值