文章目录
输入
当一次键盘输入结束时(按下回车)会将输入的数据(包括空白字符,换行符)存入输入缓冲区,当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。
cin
忽略开头的所有空白字符 (空格,换行符,制表符等)
读取直至再次遇到空白字符 (空白字符不会读取)
测试:
char a[10],b[10];
char c,d;
cin>>a>>b>>c>>d;
cout<<a<<"///"<<b<<"///"<<c<<"///"<<d<<endl;
输入:空格空格空格45
空格空格空格换行空格空格空格98
换行空格空格15
输出:45///98///1///5
cin.get();
可接收单个字符,包括换行 空格等。
对字符数组:
char c[10],d;
cin.get(c,n);
当输入的字符足够长时,
只会读取n-1个字符,放到 c 里。当n=10时,c[10]里是'\0',c是字符串。 当n=11时,读取10个字符放到 c 里,此时c[10]不再是'\0'
当n>11,仍然是读取 n-1 个字符,但只会将前10个字符放到 c里,余下的虽被读取,但不赋给任何变量
当输入的字符长度小于n-1时,将其全部读取。回车符不会读取 之后如果再有一条cin.get(d); 会将回车符读到
C++中cin、cin.get()、cin.getline()、getline()、gets()
cin.sync();
清空输入缓冲区
再次使用 cin 去读取 数据时,它就只能等待从键盘输入了,因为此时 输入缓冲区为 空。
简单的格式控制
先包含#include<iomanip>
int main(){
cout<<setfill('*')<<setw(5)<<setprecision(3)<<3.1415;
} // setw(n)设置字段的宽度 只对紧接着的输出产生作用。 当 n>要输出的字段长度时,才会起作用,默认以空格填充,可以用setfill来设置其他填充符号
//setprecision()是设置有效数字位数,舍去的时候是四舍五入
// ends 是空格
int main( void ){
const double value = 12.3456789;
cout<<"第一:"<<ends<<12.3456789<<endl; // 默认是最多6位有效数字,有效位不足6位的不受影响,12.30会输出12.3
cout<<"第二:"<<ends<<setprecision(4)<<value<<endl; // 4位有效数字
cout<<"第三:"<<ends<<setprecision(8)<<value<<endl; // 8位有效数字
cout<<"第四:"<<fixed<<setprecision(4)<<value<<endl; // 加上了fixed,意思是小数点后保留4位
cout<<"第五:"<<value<<endl; // fixed和setprecision的作用还在,依然显示12.3457
cout.unsetf( ios::fixed ); // 去掉了fixed,变成4位有效数字
cout<<"第六:"<<value<<endl;
cout.precision( 6 ); // 恢复成原来的样子,输出为 12.3457
cout<<"第七:"<<value<< endl;
cout<<"第八:"<<fixed<<value<<endl; // 小数点后六位
}
动态内存分配
二者等价
int *p=new int; // new int 返回 int *类型,动态分配出 sizeof(int)字节的空间,将起始地址 赋给 p。
int *p=(int*)malloc(sizeof(int)); // int *p=new int(10); *p 的值初始化为 10
进行释放
delete p;
二者等价
int *p=new int[20]; // new int[20] 也是返回 int *类型
int *p=(int*)malloc(sizeof(int)*20);
进行释放
delete []p;
内联函数
在函数定义前面 加 inline
关键字
调用函数的语句是有时间开销的,为了减少函数调用的开销,引入内联函数。
在对内联函数进行调用时,是将整个函数的代码插入到调用语句处,而不会产生调用函数的语句,提高运行效率。
inline int max(int a,int b){
return a>b? a:b;
}
定义在class 内的函数,自动成为 inline候选人,由编译器决定是否最终为 inline
函数重载
几个函数名字一样 , 参数个数/参数类型 不同
函数的缺省参数
定义函数的时候可以让 最右边的连续若干个参数有缺省值。
void func(int x,int y=2;int z=3){
...
}
类和对象起步
一个类:成员变量 成员函数。
一个类的成员函数在内存里只有一份,被所有对象所共用。对象只包含成员变量,不包含成员函数。
对象所占用的内存空间等于所有成员变量的大小之和。
使用类的成员变量和成员函数
访问范围关键字:
private:私有成员,只可以被 成员函数 友元函数 访问
public:公有成员,可在任何地方访问
protected:保护成员,成员函数 友元函数 子类的成员函数可以访问当前对象的
没加的话,默认是 private
class Employee{
private:
char szName[30];
public:
int salary;
void setName(char *name);
void getName(char *name);
void averageSalary(Employee e1,Employee e2);
};
void Employee::setName(char *name){
strcpy(szName,name);
}
void Employee::getName(char *name){
strcpy(name,szName);
}
void Employee::averageSalary(Employee e1,Employee e2){
cout<<e1.szName; // OK 访问 同类 其他对象的私有成员,因为这是在成员函数里
salary=(e1.salary+e2.salary)/2;
}
int main(){
Employee e;
// strcpy(e.szName,"Tom 1234567"); Error,私有成员只可在成员函数里访问
// main 并不是 Employee 类的成员函数
e.setName("Tom");
e.salary=5000;
return 0;
}
构造函数:Complex(double r,double i)
名字与类名相同,没有返回值
作用:对象生成,自动调用构造函数
类里没写构造函数,编译器会生成一个默认的无参数的构造函数(不做任何操作)
类里已经写了构造函数,编译器就不再生成无参的默认构造函数了
一个类可以有多个构造函数。
class Complex{
Complex(double r,double i=0){
}
};
//Complex *c1=new Complex; //Error ,没有提供构造函数的参数
Complex *c1=new Complex(3); // OK
//Complex c2; // Error, 没有提供构造函数的参数
Complex c2(2); // OK
构造函数在对象数组里如何起作用:
class Test{
public:
Test(int n){
cout<<"采用了第一种构造函数"<<endl;
}
Test(int n,int m){
cout<<"采用了第二种构造函数"<<endl;
}
Test(){
cout<<"采用了第三种构造函数"<<endl;
}
};
int main(){
Test array1[3]={1,Test(1,2)};
// array1[0]的参数是:1, array1[1]的参数是 1和2, array1[2]没有参数
// 数组里是三个对象
cout<<"-------------"<<endl;
Test *pArray[3]={new Test(4),new Test(1,2)};
// pArray[0] 的参数是 4, pArray[1]的 参数是 1和2
// 生成了两个对象, pArray[2] 只是一个未经初始化的指针。
}
运行输出:
采用了第一种构造函数
采用了第二种构造函数
采用了第三种构造函数
-------------
采用了第一种构造函数
采用了第二种构造函数
复制构造函数:Complex(const Complex & c)
用一个已经存在的对象去初始化新对象
class Complex{
Complex(const Complex &c){ // 只有一个参数, 参数是对同类对象的引用
}
};
如果没有定义复制构造函数,编译器生成默认的复制构造函数。
复制构造函数起作用的三种情况:
1.用一个对象 去初始化同类的另一个对象
Complex c2(c1);
Complex c2=c1; // 初始化语句
注意 如果是 Complex c1,c2; c1.n=5;
c2=c1; // 赋值语句 并不会调用复制构造函数
2.函数有一个参数是类A的对象时,该函数被调用时,类A的复制构造函数 将被调用
void Func(A a1){
}
int main(){
A a2;
Func(a2);
}
3.函数的返回值是类A的对象时,函数返回时,A的复制构造函数被调用
对于参数是对象的函数,调用时会引发调用复制构造函数,时间效率比较大
可以考虑采用常量引用参数,不会引发复制构造函数,如:
void func(Complex obj){
}
改成
void func(const Complex &obj){
// 函数中 任何 试图改变 obj的值的语句都将是非法的。
}
析构函数:~Complex()
名字与类名相同(前面多一个 ~
),无参数,无返回值,一个类只有一个析构函数
class Ctest{
public:
~Ctest(){
cout<<"析构函数被调用"<<endl;
}
};
Ctest array[2];
int main(){
}
运行输出:
析构函数被调用
析构函数被调用
// 在对象消亡时自动被调用