-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
c++ 特性用法:
(二)开始学习c++
1.头文件的变化
#include< iostream > <=> #include<stdio.h>
#include< cmath > <=> #include<math.h> 、
#include<cstring>
2.变量初始化的变化(c+ + 仅需要满足在使用变量前定义即可,不一定是在开头定义)
int a = b = c = 9 ;// 即可以对变量赋初值的时候 采用连等操作。
int a( 45 ) ; //对变量a赋初值。
3.使用名称空间
using namespace std ;// 使用名称声明
std :: cout << " string " << std::endl ; // 逐个对名称进行声明
4.endl的用法(endl表示换行)
std::endl( std ::cout<<" string " ) ; // endl()输出的用法,完成括号内的操作后换行
cout 函数解析 :先把变量名 =》数值=》转换为字符串=》输出
5.获取一个字符
cin.get() <=> getchar() //既可以读取一个字符 又可以 读取一个字符串 。getline()只能处理字符串,原因在于两者对于换行符的处理方式不同。
(三)处理数据
1.输出格式控制
例如:(默认已十进制形式输出,如需要转化输出形式,需要事先声明)
int a = 123 ;
cout << " a = " << a << endl ;//默认情况下cout以十进制行输出
cout << hex ;//改变下一个数据的输出形式,以八进制形式输出
cout << " a10 = "<< a << endl;
cout << oct ;//改变下一个数据的输出形式,以十六进制形式输出
cout << " a10 = "<< a << endl;
2.如何确定整型的存储形式
首先,看后缀。L为long型,U为unsigned int 常量,UL 为unsigned long 常量 (不区分大小写)
其实,考察长度。无后缀的十进制,以 int ,long ,unsigned long 中的最小存储类型。无后缀的八进制和十六进制,int ,unsigned int ,long ,unsigned long 最小类型。
(例如 : 十六进制0x9c40(4000)表示为unsigned int 。 因为十六进制一般用来表示内存地址,因而unsigned int 比 long 合适)
3.c 语言的转义字符同样适用于 c++ 语言
例如:
cout << "\a operation \"hyperhtape\" is now active ! \n ";
cout << "enter the code ------\b\b\b\b\b\b";
long code ;
cin>>code ;cout << "you enter "<<code <<"......\n";
cout.setf(ios_base ::fixed ,ios_base::floatfield);//此函数功能是 迫使输出使用定点小数点形式输出表示法 更好了解精度,避免切换到指数形式
4.关于宽字节的输入输出方式
wchar_t ch = 'u';
wcout << " ch = " << ch << endl ; // 输出为 ‘u’ 。即宽字符必须用 wcout/wci 输入输出,每次读取两个字节
cout << " ch = " << ch << endl ; //输出为 117 ,把两个字节截断,保留低位字节,整型输出(简而言之cout 读取一个字节,wcout读取两个字节)
5.c++中 const 与 #defiine 的比较
const int MONTHS = 12 ; // 对于const 声明的常变量 一般需要大写 与其他变量加以区别
const 比 #define 的优点 :
首先,它能够明确的指定类型 。保证变量类型的正确性。
其次,可以使用c++的作用域限定在特定的函数或者文件中。
最后,可以将const 用于更加复杂的结构中,例如:数组的长度 或者 指针中。
6.整型分类:
算术类型分为整型和浮点型。
整型包括:bool,char,wchar_t ,符号整型(signed char ,short ,int ,long ),无符号整型。
浮点型包括:float ,double ,long double 。
7.潜在的数值转化问题
较大浮点转化为较小浮点(double 转化为 float):精度降低,可能超出目标类型范围,结果不确定
浮点转化为整型:小数部分丢失,可能超出目标范围,结果不确定。
较大整型转化较小整型:可能超出目标范围,通常只复制右边的低位字节。
8.表达式中的转换
自动转换:通常将int类型选择为计算机最自然的类型,这意味着计算机使用这样类型时,运算速度可能最快。叫做整体提升。详见c++ 第60页。
强制转换:(三种表示形式)
( typename) value ;
typename ( value );
static_cast< typename > ( value );
例如:
double mint = 10.0 / 3.0 ;
cout << " mint2 = " <<static_cast<int>(mint) / int(mint) / (int)mint << endl ;
(四)复合类型
1.拼接字符串常量:
endl(cout << "i would gave my right ar""m to be a great biolinist . \n"); //可以将两个引号扣起来的字符串合并为一个,直接把第二个字符串首字节替代第一个字符串的\0
2.cin 字符串的输入
例如:
const int Arrsize =100 ;
char ss[Arrsize] ;
char ss1[Arrsize] ;
cin >> ss;
cout <<" ss = " << ss<< endl ;
cin>>ss1;
cout <<" ss1 = "<< ss1<< endl;
输入 :shijiazhuang(空格)baoding ( enter ) //一次性读取两个字符串
//当ss读取第一个字符串后自动末尾添加‘\0’,第二个字符串在队列中等待,当再次遇到cin时,输出第二个字符串,添加‘\0’.
shijiazhuang(enter)baoding ( enter ) // 分别作为两次进行分别读取两个字符串。
cin.getline( name , Arsize ) ;
首先,第一个参数为数组名,第二个参数为读取的字符数大小。它在读取指定数目的字符或者换行符时停止读取。
其次,getline()函数每次读取一行,它通过换行符来确定行尾,但不保存换行符。相反,在储存字符串时,他用空字符来代替换行符。
最后,如果输入的第一个字符串超过getline()的大小,超出被截断,相邻的getlien()直接读入空,报错。
(重点) cin.getline(name,Arsize) 与 cin.get(name,Arsize) 的几点区别:
相同点:(都是面向行的,也就是说只要在其数组大小范围内,在换行符之前所有字符都会被写进数组,包括空格)
不同点:cin.getline() 函数,回车符确定结尾,不保存换行符,但把换行符转化为空字符,表示结尾。
cin.get() 函数,不读取换行符,并丢弃,因而换行符会在输入列表中等待。
例题1:cin.get(name,Arsize) ;//读取完整行字符串,换行符不要
cin.get(name, Arsize); // 读取换行符报错,
修改方案:1.在两个cin.get()函数中间插入一个函数读取换行符 如:cin.get() .
2.采用函数拼接合并,即:cin.get(name , Arsize).get(); //第一个get()读取行字符串,第二个get()函数,接受换行符。
(注意:采用这两种方案处理cin.get()函数后,其使用方法完全雷同cin,getline()函数)
get() 与 getline() 函数更加仔细在于:
(1):get() 停止读取的原因在于已读取整行,而不是数组长度,如果超出范围保存在等待队列中,被阻断,如不需要,可以使用cin,clear() 清理。 如果是换行符,说明已经读取完毕。
(2):getline() 只是读取整行,把换行转化为空格,按照数组大小存储,而不会管超出数组大小字符的处理,关闭后面的输入。
(3)在数组的存储大小范围之内,对于两个连续输入的处理:
两个数组:分别输入,空格隔开。
两个cin.get() :使用函数拼接。cin.get().get();
两个cin.getline() : 分别输入,enter 隔开;
3.c++ 的新类型 string (#include<string> 或者 std::string)
(1) string 赋值,拼接,附加
std::string;
string ss= "shijiazhuang";
string ss1 = "hebeisheng";
string ss2 = ss + ss1 ; // 两个string类变量的拼接,(第二个string 首字符取代第一个string末尾的空字符,相当于c语言strcat()函数)
ss += s1 ; // ss = ss +s1;
ss +="a nice day"// ss = ss + "a nice day"; ss = "shijiazhuang nice a day";
string ss3 = ss ; //可以将一个string类变量赋值给另一个string类变量
cout << " ss2 = " << ss2<<endl;
cout << " ss3 = "<<ss3<<endl;
int len1 = ss1.size(); //c++ 风格
int len2 = strlen(ss1); // c语言求字符串字节函数
(2)c++结构体赋值书写形式:
struct inflatable
{
char name[20];
float volume;
double price ;
};
inflatable guests[2] = //书写形式
{
{ "bambi",0.5,21,99},
{ " godzilla",2000,565,99}
}
(3)共用体引用方式
共用体:共用体的句法和结构体相似,但只能同时存储其中的一种类。共用体的长度为最大成员长度。
用途:当数据项使用两种或者更多种格式(但不会同时使用)时,可以节省空间。
struct widget
{
char brand[20];
int type ;
union color//有名共用体
{
char c_1;
char c_2;
}color_id;
union //无名共同体
{
long id_num;
char id_char[20];
};
};
widget prize;
if (prize.type == 1)
{
cin >> prize.id_num ;
{
char brand[20];
int type ;
union color
{
char c_1;
char c_2;
}color_id;
union
{
long id_num;
char id_char[20];
};
};
widget prize;
if (prize.type == 1)
{
cin >> prize.id_num ;//有名共用体引用
}
else
{
cin >> prize.id_char ;
}
if ( prize.type == 1)
{
prize.color_id.c_1 == 1
}
else
{
prize.color_id.c_2;//无名共用体引用
}
}
else
{
cin >> prize.id_char ;
}
if ( prize.type == 1)
{
prize.color_id.c_1 == 1
}
else
{
prize.color_id.c_2;
}
(4)枚举类型
例:enum spectum{red,orange,yellow=78,green,blue,violet,indigo,ultravolet};
sptctrum band ;//定义枚举变量band
1.默认情况下,枚举量的数值是从0开始的整数值。但一旦有一个枚举量别赋初始化,后面的枚举量的值比前面的枚举量的值大1.枚举量的值可以相同。
(可以将 int 或 long 类型的枚举量)
2.再不进行强制转换的情况下,只能将定义枚举时使用的枚举量赋给变量。
如:band = blue ;合法 band = 1001 ;不合法
3.枚举变量只能是枚举量的赋值运算,或者是通过强制转换为枚举量类型后赋值,本身没有算术运算
如:band=red ;合法 band = red + yellow ; 不合法 //int值不能赋值给枚举变量 band =spectum(red + yellow );合法//强制转化为枚举类型
4.枚举的范围:
a.每个枚举斗殴取值范围,通过强制转换,可以将取值范围中的任何整数值赋值给枚举变量,即使这个值不是枚举值
b.枚举范围上下限:
上限:为先找到枚举量的最大值,再找到大于这个最大值的,最小的2的幂,减去1。如:最大枚举值 = 101 ;最大幂 = 128;上限 = 128-1=127;
下限:枚举量的最小值,如果它不小于0 ,下限 = 0;否则,采用上限方法,加上负号。如:最小枚举量 = -6 ;最大幂 = -8 ;下限 = -8 +1=-7;
4.指针和自由存储空间
(1)常规变量 int ,char 等,值是定指的量,而地址为派生量。而指针恰好相反,地址是指定的量,值是派生的量。
(2)指针或者说是地址的长度既不能指示关于变量的长度或类型的任何信息,也不能指示该地址上有什么建筑物。一般来说,地址需要2个或4(32位操作系统) 个字节,取决于计算机系统。
(3)在创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针指向的数据的内存。因而在对指针解除引用操作符(*)之前,将指针初始化
一个确定的合适的地址。
(4)指针地址:
int *pt;
pt = ( int * )0xB8000000 // 把八进制的地址值强制转换为 整型指针,与指针类型相匹配。c语言可以不用转换,但c++需要转化,否则报错。
(5)指针的意义:在运行阶段分配未命名的内存以存储,在这种情况下,只能用指针来访问内存。(new 动态链接)
typeName pointer name = new typeName 说明两点:用来指定需要什么样的内存,和用来声明合适的指针。 如:int *p = new int ;// allocate space for an int
(6)内存耗尽
当计算机没有足够的内存而无法满足new的请求。new返回0 即空指针,如果成功,返回有用的指针。
(7)使用delete来释放内存
int *ps = new int ;
delete ps ; // 完成指针操作后及时释放ps所指向的内存,但不会删除指针ps本身。可以将ps指向另一个新的内存空间。new 和 delete要配对使用。否则泄露。
(8)使用new 和 delete 的规则
a. 不要尝试释放已经释放的内存块,不要使用delete来释放声明变量所获得的内存,只能释放new分配的内存,不过对null 是安全的。
如:int guys = 5 ;int *p =&guys ;delete p ;错误,声明变量不得释放。
b.静态联编:在编译时给数组分配的内存,意味着数组是在编译时加入程序中的.
动态联编:在运行过程中选着数组的长度。
c.如果使用 new [] 为数组分配内存,则应使用 delete[] 来释放。
d.如果使用 new [] 为一个实体分配内存,则应使用 delete (没有括号)来释放。
e.数组分配内存的通用格式: type_name pointer_name = new type_name [ num_elements ]
(9) 指针,数组,和指针算术
arrayname[ i ] = *(arrayname + i ) ;
A. 指针名 和数组名 的异同点:
相同点:可以使用数组方括号的方式表示法。也可以使用解除引用操作符(*)
不同点:可以修改指针的值,而数组名是常量。
对数组sizeof 是数组的长度。(数组元素的个数)而指针是指针的长度,及时指针指向的是一个数组。(32位中4个字节)
B.在cout和多数c++中,char 数组名, 指向char 的指针,以及用双引号括起来的字符串常量都被解释字符串第一个字符的地址。
C . const char * bard = "wren"; 字符串字面值是常量,即使用const 的原因。可以使用const意味着可以用bard 来访问字符串,但是不鞥修改它。
D.字符串复制函数原型 : strncpy (array_name1 , array_name2, cpy_num );
F .创建动态结构时,不能将成员操作符句点用于结构名,因为这种结构没有名称,指示知道他的地址。应该是另一种操作符:箭头成员操作符(->)
a.简而言之:如果结构标示符是结构名,则使用句点操作符;如果标示符是指向结构的指针,则使用箭头操作符。
b.另一种访问结构成员的方法,如果ps是指向结构的指针,则*ps 就是被指向的值 即结构本身 int *ps = struct_name; ( * ps ).stuct_member ;
(10 )使用new创建动态内存结构
int main()
{
char* name ;
name = getname();
cout << name << "at"<<(int *)name<<endl;
delete [] name ;
name = getname();//name指针指向返回值的首地址,即pn指针释放,name指针重新指向该内存
cout << name << "at"<<(int *)name<<endl;//cout函数在对于地址输出是按照字符串形式输出。
//把name指向(char *)的地址值强制转化为(int *)输出,说明此时地址也是按照字符串形式储存。
delete [] name ;//当指针指向一个地址,释放时无需加[],否则指向多个地址时需加[]
system("pause");
return 0 ;
}
char * getname()
{
char temp[80]; //找出姓名最大长度,作为数组长度。
cout << "enter your last name !"<<endl;
cin>>temp;
char *pn = new char[strlen(temp)+1];//在运行阶段,分配最佳适合内存,+1 为空字符结束标志
//为什么两次调用函数时pn的地址值都是一样的啊?应当每次都是随机从新分配内存啊?
strcpy(pn,temp);//字符串复制
return pn;//返回pn的首地址,结束调用。此时分配的内存并未被释放掉,因而依然存在,且有值。
//只是由于调用结束,pn指针被释放,显示未定义的变量。
}
(11)自动存储,静态存储,动态存储
自动存储:自由变量,函数被调用时自动产生,在该函数结束时消亡。如上例中 temp[80],调用结束消亡,这就是要用new的原因。(局部变量,代码块)
静态存储:整个程序执行过程期间都存在的存储方式。(函数外面定义它 , 或者 声明变量时使用关键字static )
动态存储:自由存储空间。可以再一个函数中分配内存,在一个函数中释放,程序员有更大的控制权。
(12)堆,栈,内存泄露
泄露:如果没有delete,则即使包含指针的内存由于作用域规则和对象生命周期的原因而被释放,在自由存储空间上动态分配的变量或结构也将继续存在,
实际上,将无法访问自由存储空间的内存,因为指向这些内存的指针无效,导致内存泄露。
影响:a.内存在程序的整个生命周期不能使用,即被分配出去,但是无法收回。
b.极端情况将导致内存被耗尽,导致程序错误。
c.给一些操作系统或者相同内存空间中运行的一些应用程序带来负面影响,导致相应崩溃。