c++基础知识
I/O流的常用控制符
控制符
功能
Dec
十进制输出
Hex
十进制输出
Oct
八进制输出
setfil(c )
在给定的输出域宽度内添充字符c
setprecision(n)
设显示小数精度为n位
setw(n)
设域宽为n个字符
setiosflags(ios::fixed)
固定的浮点显示
setiosflags(ios::scientific)
指数显示
setiosflags(ios::left)
左对齐
setiosflags(ios::right)
右对齐
setiosflags(ios::skipws)
忽略前导空白
setiosflags(ios::uppercase)
十六进制数大写输出
setiosflags(ios::lowercase)
十六进制数小写输出
setiosflags(iosa::showbase)
当十六进制数输出数据时,前面显示当前导符0x;
当八进制数输出数据时,前面显示当前导符0
c++的4种数据类型
数据类型
关键字
字节数
数值范围
字符型
char
1
-128~127
整型
int
4
-2147483648~2147483647
单精度浮点型
float
4
±(1.7E-308~1.7E308)
双精度浮点型
double
8
±(3.4E-38~3.4E38)
无值型
void
0
valueless
c++的基本数据类型
数据类型标识符
字节数
数值范围
char
1
-127-128
signed char
1
-127-128
unsigned char
1
0-255
short [int]
2
-32768-32767
signed short[int]
2
-32768-32767
unsigned short[int]
2
0-65535
int
4
-2147483648-2147483647
signed int
4
-2147483648-2147483647
unsigned int
4
0-4294967295
long [int]
4
-2147483648-2147483647
signed long [int]
4
-2147483648-2147483647
unsigned long [int]
4
0-4294967295
float
4
±(3.4E-38~3.4E38)
double
8
±(1.7E-308~1.7E308)
long double
10
±(1.2E-4932~1.2E4932)
c++中常用的转义字符
转义字符
含义
/a
响铃(BEL)
/b
退格(BS)
/n
换行(LF)
/r
回车(CR)
/t
水平制表(HT)
/v
垂直制表(VT)
//
反斜杠
/'
单引号
/"
双引号
/0
空子符(NULL)
/ddd
任意字符
/xhh
任意字符
c++中常用的转义字符
转义字符
含义
-
负号
+
加
-
减
*
乘
/
除
%
求余
++
自加
--
自加
=
x=x+y
+=
x=x+(x+y)
-=
x=x-(x+y)
*=
x=x*(x+y)
/=
x=x/(x+y)
%=
x=x%(x+y)
&=
x=x&(x+y)
|=
x=x|(x+y)
^=
x=x^(x+y)
<<=
x=x<<(x+y)
>>=
x=x>>(x+y)
<
小于
<=
小于等于
>
大于
>=
大于等于
==
等于
!=
不等于
!
逻辑非
&&
逻辑与
||
逻辑或
&
按位与
|
按位或
^
按位异或
~
按位取反
<<
按位左移
>>
按位右移
2007-6-7 17.07
今天学习调试了内联函数:其定义方法和格式为:
Inline 函数值的类型 函数名(形参及其类型列表)
{ 函数体}
下面的例子是调试过的可以输出:
inline double square(double x)
{
return x*x;
}
#include<iostream.h>
void main()
{
double x;
cout<<"input a data";
cin>>x;
cout<<"the square is "<<square(x);
}
输出结果为:input a data 8 the square is 64
2006.06.08.08:51
函数重载是指一个函数可以和同一作用域中的其它函数具有相同的名字,但这些同名函数的参数类型、参数个数、返回值以及函数功能可以完全不同。
#include<iostream.h>
void whatitis(int i)
{
cout<<"this is integer"<<i<<endl;
}
void whatitis(char c[])
{
cout<<"this is string"<<c<<endl;
}
main()
{
int i=1;
char c[]="abcdef";
whatitis(i);
whatitis(c);
}
输出结果是:this is integer1 this is string abcdef
※在本例中定义了两个名称叫whatitis的函数,但他们的形参累行不通。因此这两个函数就是重载函数。
在函数调用处由程序员对实参进行强制类型转换,以此作为查找相匹配的函数的依据。
例:
#include<iostream.h>
void print(double d)
{
cout<<"this is a double"<<d<<"/n";
}
void print(int i)
{cout<<"this is an integer"<<i<<"/n";}
void main()
{
int x=1,z=10;
float y=1.0;
char c='a';
print(x); //按规则(1)自动匹配函数void print(int i)
print(y); //按规则(2)通过内部转换匹配函数void print(double i)
//因为系统能自动将float型转换成double型
print(c); //按规则(2)通过内部转换匹配函数void print(int i)
//因为系统能自动将char型转换成int型
print(double(z));//按规则(3)匹配void print(double i)
//因为程序中将实参z强制转换为double 型
}
输出结果为:
this is integer1
this is double1
this is integer97
this is double10
print(int iprint(double d)是重载函数
c++允许在定义函数时给其中的某个后哦某些形参制定默认值,这样,当发生函数调用时,如果省略了对应位置上的实参的值,则在执行被调函数,以该形参的默认值进行运算。
如:
#include<iostream.h>
void sum(int num=10) //形参默认值
{
int i,s=0;
for(i=1;i<=num;i++)
s=s+i;
cout<<"sum is "<<s<<"/n";
}
void main()
{
sum(100); //提供了实参值,被调函数以100进行运算,输出值为5050
sum(); //省略实参值,使用形参默认值10,输出为55
}
输出为:
Sum is 5050
Sum is 55
※在这个函数中我们看到主函数调用子函数时,如果没有给出初始值,则系统默认为子函数定义的初始值,如果主函数定义了初始值则运用主函数定义的初始值来进行运算。
指针的应用:
1) 指针变量是一个变量。一个指针变量和普通变量一样,在内存中也占存储单元,因此,一个指针变量也相当于一个容器,所以,指针变量也有其指针,这就是指针变量的指针
2) 指针变量内只能存放其它变量的地址,而不能直接存放一个普通数据。
3) 一个指针变量只能指向同一个类型的变量。
4) 一个指针变量只有先指向某个变量后,才可利用该指针变量对它所指向的变量进行操作(间接访问)。
//指针变量及其使用方法
#include<iostream.h>
void main()
{
int a,b;
int *ip1,*ip2; //定义了两个指向整型的指针变量
a=100;b=200;
ip1=&a;ip2=&b; //将变量a,b的地址分别赋给两个指针变量
//这时指针变量ip1指向变量a而指针变量ip1指向b
cout<<a<<''<<b<<endl;
cout<<*ip1<<''<<*ip2<<endl; //与cout<<a<<’’<<b<<endl;等价
*ip1=200; //等价于a=200;
*ip2=300; //等价于b=300;
cout<<*ip1<<''<<*ip2<<endl; //与cout<<a<<’’<<b<<endl;等价
}
※&和*的运算的优先级相同,但结合特性是自右向左,所以,&*ip1等价于&(*ip1),并等价于&a。
2007.06.09.14:41
用指针来完成求两个数中的较大者。
#include<iostream.h>
int max(int x,int y)
{
int z;
if(x>y)
z=x;
else
z=y;
return(z);
}
void main()
{
int a,b,c;
cin>>a>>b;
c=max(a,b);
cout<<c;
}
/*如果改用指向函数的指针变量,则main函数为:
void main()
{
int(*p)(); //定义了一个指向反方向的返回值为int型的函数的指针变量p
int a,b,c;
p=max;
cin>>a>>b;
c=(*p)(a,b);
cout<<c;
}
※说明:1) int(*p)();说明了一个指向返回值为整型数据的函数的指针,不要写成int*p().
2) p=max;表示把函数的入口地址赋给指针变量p,那么,*p就是函数max,因此,c=(*p)(a,b);和c=max(a,b);是等价的。*/
定义findmax()函数,其功能是寻找数组中的最大元素,并将该元素的下标通过参数返回其地址值,编程实现findmax()函数。
#include<iostream.h>
int *findmax(int *array,int size,int *index);
void main()
{
int a[10]={33,91,54,67,33,26,58};
int *maxaddr;
int idx;
maxaddr=findmax(a,sizeof(a)/sizeof(*a),&idx);
cout<<idx<<endl;
cout<<maxaddr<<endl;
cout<<a[idx]<<endl;
}
int *findmax(int *array,int size,int *index)
{
int max,i;
max=*(array+0);
for (i=1;i<size;i++)
if(max<*(array+i))
{
max=*(array+i);
*index=i;
}
return(array+*index);
}
输出为:
1
0x0012ff5c
91
2007-6-11.09:00
P+i或a+i就是a[i]元素的存储地址,即它们都指向数组的第i号元素:
#include<iostream.h>
char main()
{
int a[10];
int *p,i;
for(i=0;i<10;i++)
cin>>a[i];
p=a;
for(i=0;i<10;i++)
cout<<*(p+i)<<endl; //等价于cout<<a[i];
}
输入为:1 22 33 55 66 44 55 56 6 12
输出为:1 22 33 55 66 44 55 56 6 12
输入时主意:各个数之间为空格或回车,输出才正确,若为逗号则输出错误
※利用数组名作为函数的参数可以用一下4种方法实现:
1) 形参和实参都是数组名。
2) 实参用数组名而形参用指针变量。
3) 实参和形参都用指针变量。
4) 实参用指针变量,而形参用数组名。
函数func是实现数组排序过程的函数。主函数将8个整数读入,调用func排序并输出结果:
#include<iostream.h>
void func(int *); //func的函数原型
void main()
{
int data[8];
int i;
cout<<"/n输入8个术:";
for(i=0;i<8;i++)
cin>>data[i];
func(data);
cout<<"/n排序输出:";
for(i=0;i<8;i++)
cout<<data[i]<<",";
cout<<endl<<endl;
}
void func(int *s)
{
int i,j;
int work;
for(i=0;i<8;i++)
for(j=i;j<=8;j++)
if((+i)<*(s+j))
{
work=*(s+i);
*(s+i)=*(s+j);
*(s+j)=work;
}
}
输入为:1 2 3 4 5 6 7 8
输出为:8 7 6 5 4 3 2 1
※输入时各个数据间为空格或回车都可以,为空格时超过8个数据也不出结果只有加一个回车才出数据输出,但少于8个数据回车则还要输入数据,什么时候>=8个数据后回车才有输出。
将字符串a复制到字符串b
#include<iostream.h>
void copy_string(char *from,char *to)
{
for(;*from!='/0';from++,to++)
*to=*from;
to='/0';
}
void main()
{
char a[20]="c language";
char b[20]="very good!";
copy_string(a,b);
cout<<a<<endl;
cout<<b<<endl;
}
输出结果为:c language
c language
※如果b字符串比较长,则输出时,b字符串的前i个为a[i]内容,而其它仍为b原来的字符串。
引用及声明方法
类型标识符 &引用名=目标变量名
例: int a;
int &ra=a; //定义引用ra,它是变量a的引用,即别名。
※ 说明:
1)&在此不是求地址运算,而是标识作用,标识在此声明的是一个引用名称。
2)类型标识符是指目标变量的类型。
3)声明引用时,必须同时对其进行初始化。
4)引用声明完毕后,相当于目标变量有两个名称,即该目标原名称和引用名。
5)声明一个不是新定义一个变量,它只是表示该引用名是目标变量名的一个别名,所以,系统并不给引用分配存储单元。
应用的定义及输出
#include<iostream.h>
void main()
{
int a,b=10;
int &ra=a; //定义引用ra,初始化成变量a,所以ra是变量a的引用(别名)
a=20;
cout<<a<<endl;
cout<<ra<<endl; //等价于cout<<a<<endl;
cout<<&a<<endl; //输出变量a所占存储单元的地址
cout<<&ra<<endl; //等价于cout<<&a<<endl;
ra=b; //等价于a=b;
cout<<a<<endl;
cout<<ra<<endl;
cout<<b<<endl;
cout<<&a<<endl;
cout<<&ra<<endl;
cout<<&b<<endl;
}
指针变量的引用:类型标识符 *&引用名=指针变量名
#include<iostream.h>
void main()
{
int *a; //定义指针变量a
int*&p=a; //定义引用p,初始化为指针变量a,所以p是a的引用(别名)
int b=10;
p=&b; //等价于a=&b,即将变量b的地址赋给指针变量a
cout<<*a<<endl; //输出变量b的值
cout<<*p<<endl; //等价于cout<<*a;
}
※ 不能建立数组的引用,因为数组是一个由若干个元素组成的集合,所以就无法建立一个数组的别名。
不能声明引用的引用,不能定义引用的指针。
不能建立空指针的引用
不能建立空类型void的引用。
引用作为函数的参数
#include<iostream.h>
void main()
{
int *a; //定义指针变量a
int *&p=a; //定义引用p,初始化为指针变量a,所以p是a的引用(别名)
int b=10;
p=&b; //等价于a=&b,即将变量b的地址赋给指针变量a
cout<<*a<<endl; //输出变量b的值
cout<<*p<<endl; //等价于cout<<*a;
}
输入为:10 20
输出为:20 10
※引用的主要目的是:当参数的数据较大时,用引用比用一般变量传递参数的效率和空间占有率都好。
使用引用使函数返回多个值。
#include<iostream.h>
void max_min(int *p,int n,int &max,int *&min); //声明函数max_min
void main()
{
int a[10];
int ma,mi;
int i;
for(i=0;i<10;i++)
cin>>a[i];
max_min(a,10,ma,mi); //调用函数max_min
cout<<"最大值:"<<ma<<",最小值:"<<mi<<endl;
}
void max_min(int *p,int n,int &max,int &min) //形参max和min定义成引用
{
int i=0;
max=*(p+i);
min=*(p+i);
for(i=1;i<n;i++)
{
if(max<*(p+i)) //实质上就是对实参变量max赋值
max=*(p+i);
if(min>*(p+i)) //实质上就是对实参变量min赋值
min=*(p+i);
}
}
◎此函数无法编译,因为调用max_min时无法调用,定义的数据类型不对。
这个程序总定义一个普通的函数fn1,而另外一个函数fn2,它以引用的方法返回函数值。
#include<iostream.h>
float temp; //定义全局变量temp
float fn1(float r); //声明函数fn1
float &fn2(float r); //声明函数fn2
float fn1(float r) //定义函数fn1,它以返回值的方法返回函数值
{
temp=(float)(r*r*3.14);
return temp;
}
float &fn2(float r) //定义函数fn2,它以引用方式返回函数值
{
temp=(float)(r*r*3.14);
return temp;
}
void main()
{
float a=fn1(10.0); //第1种情况,系统生成要返回值的副本
float &b=fn2(10.0); //第2种情况,可能会出错(不同c++系统有不同规定)
//不能从被调函数中返回一个临时变量或局部变量的引用
float c=fn2(10.0); //第3种情况,系统不生成返回值的副本
//可以从被调函数中返回一个全局变量的引用
float &d=fn2(10.0); //第4种情况,系统不生成返回值的副本
//可以从被调函数中返回一个全局变量的引用
cout<<a<<","<<c<<","<<d<<endl;
}
输出为:314,314,314
用const限定引用
#include "iostream.h"
double &fn(const double &pd)
{
static double ad=32;
ad+=pd;
cout<<pd<<”/t”;
return ad;
}
void main()
{
double a=100.0;
double &pa=fn(a);
cout<<pa<<”/t”;
a=200.0;
pa=fn(a);
cout<<pa<<endl;
}
输出为:100 132 200 332
※ 引用总结
1) 在引用的使用中,单纯给某个变量取个别名是毫无意义的。引用的目的主要是在函数参数传递中解决大对象的传递效率和空间不如意的问题。
2) 用引用传递函数的参数能保证参数传递中不产生副本,提高传递效率,且通过const的使用,保证了引用传递的安全性。
3) 引用与指针的区别在于:指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作,程序中使用指针使程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
2007-06-12-12:05
结构体、共同体和枚举
定义结构体的一般结构为:
struct 结构体名
{
成员列表
}变量名列表;
※引用结构体变量时应主意:
1) 不能将结构体作为一个整体来引用,只能引用结构体变量中的成员
2) 若结构体成员本身优势一个结构体变量,则要使用多个成员运输符一级一级地找到最低一级的成员进行引用。
3) 对结构体的成员变量的使用可以象对普通变量那样进行,入进行赋值、参加运算等。
4) 可以将一个已有的结构体变量的值直接赋给另外一个相同类型的结构体变量。
5) 可以引用成员的地址,也可以引用结构体变量的地址。
指向结构体变量的指针: (可以定义指针变量指向结构体变量)
#include "iostream.h"
#include "string.h"
void main()
{
struct student //定义结构体类型student
{
long int num;
char name[20];
char sex;
float score;
};
student stu1; //定义结构体类型student的变量stu1
student *p; //定义student类型的指针变量p
p=&stu1; //将结构体变量stu1的地址赋给指针变量p
stu1.num=1; //分别给结构体变量stu1的num、name、sex、score成员赋值
strcpy(stu1.name,"li lin");
stu1.sex='M';
stu1.score=89;
//输出stu1个成员的值
cout<<stu1.num<<"/t"<<stu1.name<<"/t"<<stu1.sex<<"/t"<<stu1.score<<endl;
//借助指针变量p输出它所指向的结构体变量成员的值
cout<<(*p).num<<"/t"<<(*p).name<<"/t"<<(*p).sex<<"/t"<<(*p).score<<endl;
cout<<p->num<<"/t"<<p->name<<"/t"<<p->sex<<"/t"<<p->score<<endl;
}
结果为:
1 li lin M 89
1 li lin M 89
1 li lin M 89
指向结构体数组的指针:
#include "iostream.h"
struct student
{
int num;
char name[20];
char sex;
int age;
};
student stu[3]={{1,"li lin",'M',18},{2,"sun",'M',19},{3,"zhao",'M',20}};
void main()
{
student *p;
for(p=stu;p<stu+3;p++)
cout<<p->num<<"/t"<<p->name<<"/t"<<p->sex<<"/t"<<p->age<<endl;
}
输出为:
1 li lin M 18
1 sun M 19
1 zhao M 20
返回结构类型值的恒心的定义:
这种函数的定义方法与返回普通数据类型的函数的定义方法是一样的,只不过这种函数的返回值是结构体数据类型的。其定义如下:
结构体名称 函数名(形参及类型说明)
{函数体}
定义一个返回结构体类型的函数,求所有同学中年龄最大的同学
#include "iostream.h"
struct student
{
int num;
char name[20];
char sex;
int age;
};
student max(student *,int);
student stu[3]={{1,"li lin",'M',18},{2,"sun",'M',19},{3,"zhao",'M',20}};
void main()
{
student maxold;
maxold=max(stu,3);
cout<<maxold.num<<"/t"<<maxold.name<<"/t"<<maxold.sex<<"/t"<<maxold.age<<endl;
}
student max(student *s,int n)
{
int i,age1,index;
age1=s->age;
index=0;
for(i=0;i<n;i++)
if(age1<(s+i)->age)
{
index=i;
age1=(s+i)->age;
}
return(*(s+index));
}
输出为:3 zhao M 20
2007-06-13-08:57
堆内存的分配和释放
利用malloc函数。格式是:void *malloc(字节数)
该函数如2分配内存成功:则返回其起始地址;否则返回NULL。当程序中使用malloc函数动态分配内存时,应该在程序的头部嵌入相应的头文件:#include<stdlib.h>
利用new运算符。格式:
格式1 指针变量名=new 类型标识符;
格式2 指针变量名=new 类型标识符(初始值);
格式3 指针变量名=new 类型标识符[内存单元个数];
※两种方法的区别是:使用malloc函数分配内存时,其返回值要经过类型转换后才能赋给一个指针变量,而利用new分配内存则不需要类型转换。
利用free函数。格式是:free(起始内存地址);
当程序中使用free函数释放内存时,应该在程序的头部嵌入相应的头文件:#include<stdlib.h>
利用delete运算符。
格式1 delete 指针变量名;
格式2 delete[] 指针变量名;
格式1可以释放一个内存单元;而格式2可以释放若干个内存单元空间。
例:
#include<iostream.h>
#include<stdlib.h>
void main()
{
int *number,*p,*q;
number=new int[100]; //申请分配100个int类型所占内存空间(200字节)
p=new int; //申请分配一个int类型所占内存空间(2个字节)
q=(int *)malloc(10*sizeof(int)); //申请分配10个int类型所占内存空间
if(number==NULL||p==NULL||q==NULL)
cout<<"内存分配失败"<<endl;
else
cout<<"内存分配成功"<<endl;
delete []number; //释放number所指向的所有内存空间
delete p; //释放p所指向的所有内存空间
free(q); //释放q所指向的所有内存空间
}
输出为:内存分配成功
共同体
使几个不同的变量共占一段内存的结构称为共用体类型,也叫联合体类型
格式:
union 共同体名
{成员表}变量表;
枚举就是之将某一变量所有可能的取值一一列举出来。定义格式是:
enum 枚举类型名{枚举元素表}枚举变量名;
类型定义typedef的使用:在c++中,出了直接使用c++提供的变准类型名:int、char、floot、double、long等去定义类型外,还可以用typedef定义新的类型名代替已有的类型名。
宏定义命令:一般形式为:#define 宏名 字符串
文件包含命令:是指将另一个源文件的内容合并到当前的程序中。一般形式为:
#include<文件名> 或 #include”文件名”
条件编译命令:它使得同一源文件在不同的条件下编译得到不同的目标代码。
形式有3种
1)#ifdef 标识符
程序段1
#else
程序段2
#endif
2)#ifndef 标识符
程序段1
else
程序段2
#endif
3)#if 常量表达式1
程序段1
#elif 常量表达式2
程序段2
……
#elif 常量表达式n
程序段n
#else
程序段n+1
#endif
面向对象的程序设计
类的定义
C++的类在结构体的基础上扩充而来的。结构体将具有某种的不同数据的不同类型的成员组织在一起,而类是把各种不同类型的数据和对数据的操作组织在一起而形成的用户自定义的数据类型。
※ 说明:
Class是定义类的关键字,类名由用户自定义,但必须是c++的有效标识符,且一般首字母大写。
用类的数据成员表示对象的属性,用成员函数表示对象的服务,即对象的行为和功能。这些成员分3部分,私有部分(private)、公有部分(public)、保护部分(protected)。
“::”符合叫做用域运算符,它是用来指明哪个函数属于哪个类或哪个数据属于哪个类,所以,使用类中成员的全名是:类名::成员名。
类名是成员名的一部分
class Record
{
private:
char bookname[20];
int number;
public:
void regist(char *a,int b); //成员函数regist的原型
void show(); //成员函数show的原型
}; //定义图书类Record
void Record::regist(char *a,int b) //regist()是类Record的成员函数
{
strcpy(bookname,a);
number=b;
}
void Record::show() //show()是类Record的成员函数
{
cout<<"名称:"<<bookname<<endl;
cout<<"号码:"<<number<<endl;
}