C++语言特性 基于《C++ Prime Plus》

C++语言特性 基于《C++ Prime Plus》,第1张

C++语言特性 基于《C++ Prime Plus》 开始学习C++ 进入C++
    使用cin和cout进行输入和输出的程序必须包含头文件iostream名称空间using namespace std,旨在编写大型程序以及将多个厂商现有代码组合起来的程序时更容易。类、函数和变量都被放置在名称空间std中。若省略名称空间,只能这样编码:std::cout << "come" << std::endl用双引号括起的一系列字符叫作字符串。输出引号括起的字符串时,通常使用换行符n,其他情况下使用控制符endl。一个差别是endl确保程序继续运行前刷新输出(将其立即显示在屏幕上)。
C++语句
    cout <<输出函数cin >>输入函数对于声明变量,C++的做法是尽可能在首次使用使用变量前声明它。如果不希望程序框闪退应在return语句前添加两条cin.get()<<运算符将字符串插入到输出流中>>运算符从输入流中抽取字符cout与cin都是智能对象cout拼接,如cout << "come" << " up! "将输出come up!
函数
    C++不允许将函数定义嵌套在另一个函数定义中。每个函数都是独立的让程序能访问名称空间std的四种方法:
    ①将using namespace std;放在函数定义之前,让文件中所有函数都能使用名称空间std中的所有元素 。
    ②将using namespace std;放在特定的函数定义中,让该函数能够使用名称空间std中的所有原数。
    ③使用using std::cout编译命令,让该函数能使用指定的元素std。
    ④在需要使用名称空间std中的元素时,使用前缀std::如:std::cout。
处理数据 简单变量
    内置C++类型分两组:基本类型和复合类型成员函数cout.put()用来输出字符成员函数归类所有,描述了 *** 纵类数据的方法。句点称为成员运算符。cout.put()的意思是,通过类对象cout来使用函数put()有些字符不能直接通过键盘输入到程序中。例如回车并不能使字符串包含一个换行符,所以使用转义字符n任何数字值或指针值都可以被隐式转换为bool值。任何非零值都被转换为true,而零被转换为false。
const限定符
    尽量使用const关键字来修改变量声明和初始化。必须在声明常量时提供值,否则常量的值将是不确定的,且无法修改。
浮点数
    E表示法最适合于非常大和非常小的数通常cout会删除结尾的零。调用cout.setf()将覆盖这种行为。调用示例:cout.setf(ios_base::fixed, ios_base::floatfield)浮点运算的速度通常比整数运算慢,且精度将降低。强制类型转换,示例:double(temp)C++格式的想法是让强制类型转换像函数调用。static_cast<>用于将值从一种数值类型转换为另一种数值类型,例如static_cast (temp),将变量temp转换为double类型。
复合类型 数组
    编译器不会检查使用的下标是否有效,比如num[-1]编译也会通过。如果将sizeof运算符用于数组名,得到的将是整个数组中的字节数。但如果将sizeof用于数组元素,得到的将是元素的长度(字节)。如int num[2]中num是一个数组,而num[1]只是一个int变量。只有在定义数组时才能使用初始化,此后不能使用,也不能将一个数组赋给另一个数组。如果只对数组的一部分进行初始化,这编译器把其他元素设置为0。如果初始化数组时方括号内为空,如num[],编译器将计算元素个数。让编译器计算元素个数是很糟的做法,其计数可能与您想象的不一样。这种方法对于将字符数组初始化为一个字符串来说比较安全,但不建议在其他情况使用。
字符串
    字符串是存储在内存的连续字节中的一系列字符用双引号括起的字符串隐式地包括结尾的空字符‘’,因此不用显式地包括它。在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内。使用cout进行字符串拼接时(cout << "come" << "up!")第一个字符串中的'将被第二个字符串的第一个字符取代使用strlen()确定字符串长度需要头文件cstring。strlen()只计算可见的字符,而不把空字符计算在内。getline()和get()函数都读取一行输入,直到到达换行符。getline()丢弃换行符,而get()将换行符保留在输入序列中。面向行的输入:getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。调用方法cin.getline()。函数有两个参数。第一个参数是用来存储输入行的数组的名称,第二个参数是要读取的字符数。如果这个参数为20,则函数最多读取19个字符,余下的空间用于存储自动在结尾处添加的空字符。
#include 
int main(){
    using namespace std;
    char ch[20];
    cin.getline(ch,20);
}
    面向行的输入:get()。cin.get()参数与cin.getline()一样。使用不带任何参数的cin.get()调用可读取下一个字符(即使是换行符),因此可以用它来处理换行符,为读取下一行输入做好准备。
#include 
int main(){
    using namespace std;
    char ch[20],ah[20];
    cin.get(ch,20);//也可以使用cin.get(ch,20).get();
    cin.get();//省略掉这一句
    cin.get(ah,20);
}
string类介绍
    要使用string类,必须在程序中包含头文件string类设计让程序能自动处理string的大小。例如,string str声明创建一个长度为0的string对象,但程序将输入读取到str中时,将自动调整str的长度。不能将一个数组赋给另一个数组,但可以将一个string对象赋给另一个string对象。可以使用运算符+将两个string对象合并起来。
#include 
#include 
int main(){
    using namespace std;
    string str_1 = "app";
    string str_2 = "le";
    string str_3 = str_1 + str_2;
}
    string使用getline(),示例:string str;声明,getline(cin,str);
结构简介
    C++不提倡使用外部变量,但提倡使用外部结构声明。结构的初始化:
#include 
struct inflatable{
    char name[20];
    float  volume;
    double price;
};
int main(){
    using namespace std;
    inflatable guest = {
            "Glorious Gloria",
            1.99,
            29.99
    };
}
指针和自由存储空间
    一定要在对指针应用解除引用运算符*之前,将指针初始化为一个确定的,适当的地址。使用new分配内存,格式为int * pt = new int需要在两个地方指定数据类型:用来指定需要什么样的内存和用来声明合适的指针。当使用new分配内存后,要使用delete释放内存,否则将发生内存泄露。如释放上面分配的内存delete pt。要创建一个包含10个int元素的数组时,int *ps = new int [10],使用delete释放内存delete [] ps。如果使用new时,不带方括号,则使用delete时也不应该带方括号。如果使用new时带方括号,则使用delete时也应该带方括号对指针解除引用意味着获得指针指向的值。使用方括号数组表示法等同于对指针解除引用。决不要对未被初始化为适当地址的指针解除引用。将一个指针减去另一个指针,获得两个指针的差。后一种运算将得到一个整数,仅当两个指针指向同一个数组时,运算才具有意义。使用new创建动态结构,此时只能使用箭头成员运算符(->)指向成员,如ps->price:
#include 
#include 
struct inflatable{
    char name[20];
    float  volume;
    double price;
};
int main(){
    using namespace std;
    inflatable * ps = new inflatable;
}
数组的替代品
    模板类vector,如vector vi与vector vd[n],其中vi是一个vector对象,vd是一个vector对象,n可以是整型常量,也可以是整型变量。模板类array,示例:array ad = {1.2, 2.1, 3.43, 4.3}。类型后面的大小只能是常量,不能是变量。可以将一个array对象赋给另一个array对象;对于数组必须逐元素复制数据。
循环和关系表达式 for循环
    cout.setf(iso_base::boolalpha)将输出变更为false或true而不是1和0。像x < y这样的关系表达式将被判定为bool值true或falsecout << (x < 3) << end因为<<运算符的优先级比表达式中使用的运算符高,所以使用括号获得正确的运算顺序。任何表达式加上分号都可以成为语句,但反过来就不一样了。通常定义一个const值来表示数组中的元素个数是个好办法。对于for循环,检测不等通常比检测相等好。string类的size()获得字符串中的字符数。string word定义big = word.size()计算字符数。a++意味着使用a的当前值计算表达式,然后将a的值加1;而++b的意思是先将b的值加1,然后使用新的值来计算表达式。对于类而言,前缀版本的效率比后缀版本高。前缀运算符的从右到左结合规则意味着*++pt的含义如下:先将++应用于pt,然后将* 应用于被递增后的pt。另一方面++*pt意味着先取得pt指向的值,然后将这个值加1。对于*pt++,后缀运算符++的优先级更高,意味着将运算符用于pt,而不是*pt逗号运算符优先级是最低的。要比较字符串不能使用==运算符,这样比较的是它们是否存储在相同的地址上。而应该使用strcmp()函数。如果两个字符串相同,该函数返回0。
while循环
    string对象不使用空字符标记字符串末尾,但仍然可以这样使用while(str[i])。
基于范围的for循环
    对数组(或容器类,如vector和array)的每个元素执行相同的 *** 作。如:
#include 
#include 
#include 
int main() {
    using namespace std;
    double num[5] = {0,1,2,3,4};
    for (double x : num) {
        cout << x << endl;
    }
}
    要修改数组的原数,需要使用不同的循环变量语法:for(double &x : num)cin在读取时将忽略空格、制表符和换行符。读取字符串使用getline()函数会丢弃末尾的换行符(n),但读取数值时不会,所以要这样做(cin >> num).get()因为get()函数会读取单个任意字符,将换行符(n)剔除输入空间。函数重载性质,如果在C++中使用cin.get(name, ArSize),则编译器将找到使用char*和int作为参数的cin.get()版本;如果使用cin.get(ch),则编译器将使用接受一个char参数的版本;检测到EOF后,cin将两位(eofbit和failbit)都设置为1;则cin.eof()将返回bool值true,否则返回false。同样cin.fail()将返回bool值true,否则返回false。eof()和fail()测试都应该放在读取后。可以这样这样检查文件末尾while ((ch = cin.get()) != EOF)使用cin.get(ch)进行输入时,将不会导致任何类型方面的问题。使用字符参数的版本(cin.get(ch)) 更符合对象方式,因为其返回值是istream对象。这意味着可以将它们拼接起来。cin.get(ch1).get(ch2)将输入中的下一个字符读入ch1中,并将接下来的一个字符读入到ch2
分支语句和逻辑运算符 字符函数库cctype
    如果ch是一个字母,则isalpha(ch)函数将返回一个非零值,否则返回0。如果有定义int n;cin >> n;,用户输入一个单词,而不是数字,发生类型不匹配的情况,将发生一下4种情况:
    ①n的值保持不变;
    ②不匹配的输入将被留在输入队列中;
    ③cin对象中的一个错误标记被设置;
    ④对cin方法的调用将返回false;非数字输入设置错误标记意味着必须重置该标记,程序才能继续读取输入。clear()方法重置错误输入标记,同时也重置文件尾。输入错误和EOF都将导致cin返回false可以在while循环中这样使用while(cin >> fish[i])当类型不匹配时,括号中为false当cin没有输入成功时,cin!为true,cin.clean()清除异常结束状态,cin.get()再读取一个字符,将退出字符(如q,s或任意字符)剔除出输入空间。
if(!cin){
	cin.clear();
	cin.get();
}
cin.get()//使命令行窗口停留
cin.get()//使命令行窗口停留
    程序发现用户输入了错误内容时应采取3个步骤。
    ①重置cin以接受新的输入。
    ②删除错误输入
    ③提示用户再输入
    请注意程序必须先重置cin,然后才能删除错误输入。
while(!(cin >> golf[i])){
	cin.clear();//重置cin
	while(cin.get() != 'n){
		continue;
	}
	cout << "请再次输入数值:"
}
    一维数组指针表示法int a[3]等于a+2(地址)*(a+0)(解引用值),二维数组int a[2][3]等于*(a+2)+3(地址)*(*(a+2)+3)。
函数——C++的编程模块 复习函数基本知识
    要使用函数,必须完成:提供函数定义;提供函数原型;调用函数。如果声明的返回类型为double,而函数返回一个int表达式,则该int值将被强制转换为double类型。C++对于返回值的类型有一定限制:不能是数组。函数原型描述了函数导编译器的接口。函数原型在C++中是必不可少的。原型确保以下几点:
    ①编译器正确处理函数返回值;
    ②编译器检查使用的参数数目是否正确;
    ③编译器检查使用的参数类型是否正确;如果不正确,则转换为正确的类型;C++中原型自动将被传递的参数强制转换为期望的类型,条件是两者都是算术类型(如int转double)。
函数参数和按值传递
    C++通常按值传递参数,这意味着将数组参数传递给函数,而后者将其赋给一个新变量。使用while循环提供重复输入,使用cin>>ch而不是cin.get(ch)或ch = cin.get()来读取一个字符。原因是两个cin.get()函数读取所有的输入字符,包括空格和换行符,而cin>>跳过空格和换行符。当用户对程序提示做出响应时,必须在每行的最后按Enter键,以生成换行符。cin>>ch方法可以轻松地跳过这些换行符,但当输入的下一个字符为数字时,cin.get()将读取后面的换行符。
函数和数组
    型参为数组:int sum_arr(int arr[],int n)。方括号指出arr是一个数组,而方括号为空则表明,可以将任何长度的数组传递给该函数。也可以这样声明:int sum_arr(int *arr,int n)数组声明使用数组名来标记存储位置;对数组名使用sizeof将得到整个数组的长度。传递常规变量时,函数将使用该变量的拷贝;但传递数组时,函数将使用原来的数组。const int * pt= &age该声明指出,pt指向一个const int,因此不能使用pt来修改这个值。换句话说,*pt的值为coust,不能被修改。但可通过age变量来修改age的值。将const变量的地址赋给指向const的指针是可行的,但禁止将const的地址赋给常规指针。如果数据类型本身并不是指针,则可以将const数据或非const数据的地址赋给指向const的指针,但只能将非const数据的地址赋给非const指针。const int * pt = &age能防止修改pt指向的值,但不能防止修改pt的值,也就是说可以将一个新地址赋给pt。int data[3][4],data是一个数组名,该数组有3个元素。第一个元素本身是一个数组,由4个int值组成。因此data的类型是指向由4个int组成的数组的指针。作为函数声明应该这样写int sum(int (*ar2)[][4], int size),括号必不可少,size为行数。int *ar2[][4]声明一个由4个指向int的指针组成的数组,而不是一个指向由4个int组成的数组的指针。
函数和结构
    若按值传递结构,函数将使用原始结构的副本。结构名只是结构的名称,要获得结构的地址,必须使用地址运算符&假如要传递结构的地址需要使用指向结构的指针void show (polar * pda)其中polar为结构名。
函数和string对象
    示例声明void display(string sa[], int n)
函数与arrar对象
    按值传递示例:void show (array da)按地址传递示例:void show (array *pa)模板array并非只能存储基本数据类型,还可以存储类对象,比如array sname = {"sp", "su", "fa", "wi"}
函数指针
    要传递函数的指针需要:获取函数的地址,声明一个函数指针;使用函数指针来调用函数。要声明指向特定类型的函数的指针,可以首先编写这种函数的原型,然后用(*pf)替换函数名。这样pf就是这类函数的指针。在函数中通过指针调用函数示例:
#include 
using namespace std;
double calculate(double m,double n,double(*pt)(double x,double y));
double add(double x,double y);
int main()
{
    double q = calculate(2.5,10.4,add);
    cout << q << endl;
}
double add(double x,double y){
    return x + y;
}
double calculate(double m,double n,double(*pt)(double x,double y)){
    double temp;
    temp = (*pt)(m,n);
    return temp;
函数探幽 C++内联函数
    内联函数的编译代码与其他程序代码“内联”起来了。内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存。在函数声明前加上关键字inline;在函数定义前加上关键字inline。inline sum (int x, int y)。内联函数不能递归!如果函数定义占用多行,将其作为内联函数就不太合适。
引用变量
    引用是已定义的变量的别名,通过将引用变量用作参数,函数将使用原始数据,而不是其副本。声明引用,例如,要将rodents作为rats变量的别名:int rats; int & rodents = rats;其中&不是地址运算符,而是类型识别符的一部分。上述引用声明允许将rats和rodents互换——它们指向相同的值和内存单元。简单来说将ridents加1将影响两个变量必须在声明引用时将其初始化,而不能想指针那样,先声明,再赋值。引用更接近const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它。引用用作函数参数,使得函数中的变量名称为调用程序中的变量的别名。按引用传递允许被调用的函数能够访问调用函数中的变量。示例交换函数:
#include 
void swapr(int & a, int & b);
int main()
{
    int x = 300;
    int y = 500;
    swapr(x,y);
}
void swapr(int & a, int & b){
    int temp;
    temp = a;
    a = b;
    b = temp;
}
    在swapr()中,变量a和b是x和y的别名,所以交换a和b的值相当于交换x和y的值。如果想让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用则应使用常量引用(加const)。当数据比较大时,引用参数将很有用。如果实参与引用参数不匹配,C++将生成临时变量。仅当参数为const引用时,C++才允许这样做,编译器两种情况下生成临时变量:实参类型正确,但不是左值;实参的类型不正确,但可以转换为正确的类型。左值参数是可被引用的数据对象。如果接受引用参数的函数的意图是修改作为参数传递的变量,则创建临时变量将阻止这种意图的实现。使用结构引用参数的方式与使用基本变量引用相同,只需在声明结构参数时使用引用运算符&即可。示例:结构定义struct free{},函数参数引用:void set (free & ft)依然使用成员运算符(.)访问元素。free & accumulate(free & target, const free & source)。如果返回类型被声明为free而不是free&,返回语句将返回target的拷贝。但返回类型为引用,这意味着返回的是最初传递给accumulate()的team对象。传统返回机制与按值传递函数参数类似,计算关键字return后面的表达式,并将结果返回给调用函数。但在返回值为引用时,将直接复制,效率更高。返回引用的函数实际上是被引用的变量的别名。应避免返回函数终止时不再存在的内存单元引用,也应避免返回指向临时变量的指针。为避免这种问题,作为参数的引用将指向调用函数使用的数据,因此返回的引用也将指向这些数据。使用引用参数的主要原因:
    ①能修改调用函数中的数据对象
    ②通过传递引用而不是整个数据对象,可以提高程序的运行速度。指导原则:
    ①如果数据对象很小,如内置数据类型或小型结构,则按值传递。
    ②如果数据对象是数组,则使用指针,这是唯一的选择,并注意使用const关键字。
    ③如果数据对象是较大的结构,使用指针或引用以提高效率
    ④如果数据对象是类对象,则使用引用。对修改调用函数中数据的函数:
    ①如果数据对象是内置数据类型,使用指针。
    ②如果数据对象是数组,使用指针
    ③如果数据对象是结构,使用指针或引用
    ④如果数据对象是类端详,则使用应用

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5714483.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-17
下一篇2022-12-18

发表评论

登录后才能评论

评论列表(0条)

    保存