zoukankan      html  css  js  c++  java
  • 第3讲——复合类型

    一、学习新知识

    这一讲我们来学些几种普通的复合类型,但是我们要知道,类也是复合类型。

     

    首先来看数组,C语言嚼烂的知识了,我们只看新特性。

    几种初始化方数组方法:

    int arr1[4] = {3,6,8,10};
    int arr2[] = {1,2,5,8};
    int arr3[4] {1,3,6,9};    //可省略等号 
    int arr4[4] {};            //将所有元素设置为零 
    4种初始化方法

    我们知道声明数组的一种方式是:

    typeName arrayName[arraySize];
    

    其中,表达式arraySize指定元素数目,它必须是整型常数或const值,也可以是常量表达式,即其中所有的值在编译时都是已知的。也就是说,arraySize不能是变量,因为变量的值是在程序运行时设置的。

    但使用new运算符将避开这种限制。

    假设要编写一个程序,它是否需要数组取决于运行时用户提供的信息。如果通过声明来创建数组,则在程序被编译时将为它分配内存空间,不管程序最终是否使用数组,数组都在那里,它占用了内存。

    静态联编:在编译时给数组分配内存,即意味着数组是在编译时加入到程序中的;

    动态联编:在运行阶段选择是否创建数组并且可以选择数组的长度。

    使用new来创建动态数组:

    //创建动态数组只需将数组的元素类型和元素数目告诉new即可
    //必须在类型名后加上方括号,其中包含元素数目 
    int *p = new int[10];	//创建一个包含10个int元素的数组 
    

    new运算符返回第一个元素的地址,在这个例子中,该地址被赋给指针p。

    p是指向一个int(数组第一个元素)的指针。我们需要跟踪内存块中的元素个数,也就是说,由于编译器不能对p是指向10个整数中的第一个这种情况进行跟踪,因此编写程序时,必须让程序跟踪元素的数目。

    使用动态数组:

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	double *p = new double [3];
    	p[0] = 0.2;
    	p[1] = 0.5;
    	p[2] = 0.8;
    	cout<<"p[1] is "<<p[1]<<".
    ";
    	p = p + 1;
    	cout<<"Now p[0] is "<<p[0]<<" and p[1] is "<<p[1]<<".
    ";
    	p = p - 1;
    	delete [] p;		//释放new分配的内存 
    	return 0;
    }
    

    运行结果为:

    看完数组,再来看看结构。

    结构是一种比数据更灵活的数据格式,因为同一个结构可以存储多种类型的数据,从而能够将数据的表示合并到一起。

    我们要知道,结构也是C++OOP堡垒(类)的基石,学习有关结构的知识将使我们离C++的核心OOP更近。

     

    结构是用户定义的类型,而结构声明定义了这种类型的数据属性。定义了类型后,便可以创建这种类型的变量。因此,创建结构包括两步:①定义结构描述;②按描述创建结构变量。

    来看一段创建结构的程序:

    #include <iostream>
    using namespace std;
    //结构声明 
    struct student{
    	char name[20];    //name成员是一个字符数组,可以初始化为一个字符串
    	int score;      //将结构成员score看作还是int类型的变量
    }; 
    
    int main()
    {
    	student stu1 = {"liuyu",98};		//创建结构类型student的变量stu1 
    	student stu2  {"zhouning",18};	
    	cout<<stu1.name<<"的得分是"<<stu1.score<<".
    "; 
    	cout<<stu2.name<<"的得分是"<<stu2.score<<".
    "; 
    }
    

    哈哈,上面这段程序只是结构的基本操作啊,我们来段猛的:

    #include <iostream>
    using namespace std;
    //结构声明 
    struct student{
    	char name[20];
    	int score;
    }stu2; 		//同时定义结构和创建结构变量 
    
    int main()
    {
    	student stu1 = {"liuyu",98};	 
    	stu2 = stu1;		//进行结构间的赋值	
    	cout<<stu1.name<<"的得分是"<<stu1.score<<".
    "; 
    	cout<<stu2.name<<"的得分是"<<stu2.score<<".
    "; 	//输出和上面一模一样 
    }
    

    这些特征和我们学C时的结构差不多,但C++结构拥有更多的特性。例如,C++结构除了成员变量之外,还可以有成员函数。但这类高级特性往往被用于类中,而不是结构中。

     

    【枚举】

     之前学java也看过枚举了,当时没看懂,今天一定要弄懂!!!

    C++的enum工具提供了另一种创建符号常量的方式,这种方式可以代替const。它还允许定义新类型,但必须按严格的限制进行。

    使用enum的句法与使用结构相似,请看下面的语句:

    enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet};
    

    这条语句完成两项工作:

    1. 让spectrum成为新类型的名称;spectrum被称为枚举(enumeration),就像struct变量被称为结构一样。
    2. 将red、orange、yellow等作为符号常量,它们将对应整数值0~7。这些常量叫作枚举量(enumerator)。

    我们要知道,在默认情况下,将整数值赋给枚举量,第一个枚举量的值为0,第二个枚举量的值为1,依次类推。可以通过显式地指定整数值来覆盖默认值。

    由上面的语句我们知道spectrum为枚举名,那么我们可以用枚举名来声明这种类型的变量:

    specrtum band;     //band是spectrum类型的变量
    

    下面来看枚举变量的特性:

    enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet};
    specrtum band; 
    //在不进行强制类型转换的情况下,只能讲定义枚举时使用的枚举量赋给这种枚举的变量
    //即band只有8个可能的值 
    band = blue;
    band = 2000;    //错误,2000不是一个枚举量
    //枚举只定义了赋值运算符
    band = orange;
    band = orange + red;    //错误
    //枚举量是整型,可被提升为int类型,但int类型不能自动转换为枚举类型    
    band = 3;            //错误,虽然3对应的枚举量为green 
    band = green;        //正确 
    int color = blue;    //spectrum type promoted to int 
    color = 3 + red;    //red被提升为int类型 
    //如果int值有效,则可以通过强制类型转换,将它赋给枚举变量
    band = spectrum(3);    //3在0-7之间
    View Code

    我们可以了解到枚举的规则相当严格,所以枚举更常被用来定义相关的符号常量,而不是新类型。

    比如,我们可以用枚举来定义switch语句中使用的符号常量。

    如果我们只使用常量,我们可以省略枚举类型的名称:

    enum {red,orange,yellow,green,blue,violet,indigo,ultraviolet};
    

    我们除了像上面那样由系统帮我们设置枚举量的值,我们也可以自己进行设置:

    enum bits{one = 1,two = 2,four = 4,eight =8};
    //只定义其中一些枚举量的值
    enum bigstep{first,second = 0,third};	//first在默认情况下为0,可以创建多个值相同的枚举量,没有初始化的枚举量值比前面的大1 
    

    二、温故而知新

    【编写一条语句,显示float数组ideas中的第二个元素的值。】

    cout <<(float)ideas[1]<<endl; 
    

    【声明一个char数组,将其初始化为字符串“cheeseburger”。】

    char a[20]="cheeseburger";
    

    【设计一个描述鱼的结构声明。结构中应当包括品种、重量(整数,单位为盎司)和长度(英寸、包括小数)。】

    struct fish{
      string pinzhong;     //品种名
      int angsi;	          //重量,盎司,整数
      double yingcun;	     //长度,英寸,浮点数
    };
    

    【声明一个问题3中定义的结构的变量,并对它进行初始化。】

    fish liyu={"鲤鱼",5,2.2}; 
    

    fish liyu;  
    liyu.pinzhong = "鲤鱼";  
    liyu.angsi = 5;  
    liyu.yingcun = 2.2; 
    

    【用enum定义一个名为Response的类型,他包括Yes,No和Maybe等枚举量,其中Yes的值为1,No为0,Maybe为2。】

    enmu Response{Yes=1,No=0,Maybe=2};
    

    【编写一段代码,要求用户输入一个正整数,然后创建一个动态的int数组,其中包含的元素数目等于用户输入的值。】

    unsigned int a;  
    cin >> a;  
    int *b=new int[a];
    

    【下面的代码是否有效?如果有效,他将打印出什么结果?】

    有效。他会打印储存这个字符串常量的内存地址。

     

    【编写一段代码,给问题3中描述的结构动态分配内存,再读取该结构的成员的值。】

    fish *a=new fish;  
    cout<<"依次输入鱼类的名字,重量(盎司,整数),长度(英寸,小数),以回车为结束。
    "  
    cin >> (*a).string;  
    cin >> a->angsi;  
    cin >> a->yingcun;  
    

    三、做做习题

    1.编写一个C++程序,如下述输出示例所示的那样请求并显示信息:

    What is your first name? Betty Sue

    What is your last name? Yewe

    What letter grade do you deserve? B

    What is your age? 22

    Name: Yewe, Betty Sue

    Grade: C

    Age: 22

    注:该程序应接受的名字包含多个单词。另外,程序将向下调整成绩,即向上调整一个字母。假设用户请求A、B或C,所以不必担心D和F之间的空档。

    答:代码:

    #include<iostream>
     
    int main()
    {
    using namespace std;
    char first[20], last[20];    //声明first name和last name
    char grade;    //声明成绩变量grade
    int age;    //声明年龄变量age
    cout << "What is your first name? ";
    cin.getline(first, 20);    //读取用户输入的一行字符给first
    cout << "What is your last name? ";
    cin.getline(last, 20);    //读取用户输入的一行字符给last
    cout << "What letter grade do you deserve? ";
    cin >> grade;    //读取用户输入的grade
    cout << "What is your age? ";
    cin >> age;    //读取用户输入的年龄
    cout << "Name: " << last << ", " << first << endl;    //显示名字
    cout << "Grade: " << char((int)grade + 1) << endl;    //将用户输入的grade转为int类,然后+1就是下调成绩,再转为char类显示
    cout << "Age: " << age << endl;    //显示用户输入的年龄
    cin.get();    //和下面起到暂停作用
    cin.get();
    return 0;
    }
    View Code

    2.编写一个程序,它要求用户首先输入其名,然后输入其姓;然后程序使用一个逗号和空格将姓和名组合起来,并存储和显示组合结果。请使用char数组和头文件cstring中的函数。下面是程序运行时的情形:

    Enter your first name: Flip

    Enter your last name: Fleming

    Here's the information in a single string: Fleming, Flip

    答:代码:

    #include<iostream>
    #include<cstring>
     
    int main()
    {
    using namespace std;
    char first[20], last[20];    //创建字符串first和last
    char middle[3] = ", ";    //创建用于连接名字的间隔符,和空格
    cout << "Enter your first name: ";
    cin.getline(first, 20);    //要求用户输入名
    cout << "Enter your last name: ";
    cin.getline(last, 20);    //要求用户输入姓
     
    const int a=strlen(first);    //让常量a等于first的长度
    const int b = strlen(last);    //让常量b等于last的长度
    char *name = new char[43];    //创建指针,用于将first和last还有中间的间隔符组合到一起
     
    strcpy_s(name, b + 1, last);    //将last的内容复制到指针name(所指向地址的字符串)中,注意,长度需要给空字符留一个位置
    name = name + b;    //指针偏移,偏移长度为last的长度,这样的话,就将空字符覆写掉了
    strcpy_s(name, 3, middle);    //将middle的内容复制到指针name中,同样留一个空字符位置
    name = name + 2;    //偏移指针,覆写空字符
    strcpy_s(name,a+1, first);    //将first内容复制到指针name中
    name = name - b - 2;    //将指针偏移回原来的位置
    cout << "Here's the information in a single string: " << name << endl;    //输出指针指向的地址
    system("pause");    //用2个cin.get()就不会显示最后的 请按任意键继续. . . 但问题是,好像也没法复制输出的内容了
    return 0;
    }
    View Code

    3.结构CandyBar包含3个成员。第一个成员存储了糖块的品牌;第二个成员存储糖块的重量(可以有小数);第三个成员存储了糖块的卡路里含量(整数)。请编写一个程序,声明这个结构,创建一个名为snack的CandyBar变量,并将其成员分别初始化为“Mocha Munch”、2.3和350。初始化应在声明snack时进行。最后,程序显示snack变量的内容。

    答:代码:

    #include<iostream>
    #include<string>
     
    struct CandyBar
    {
    std::string pinpai;    //品牌
    double weight;    //重量
    int kaluli;    //卡路里
    };
     
    int main()
    {
    using namespace std;
    CandyBar snack = { "Mocha Munch",2.3,350 };    //声明并初始化snack
    cout << snack.pinpai << "的重量为" << snack.weight << ",卡路里含量为:" << snack.kaluli << endl;
    system("Pause");
    return 0;
    }
    View Code

    4.结构CandyBar包含3个成员,如编程练习3所示。请编写一个程序,创建一个包含3个元素的CandyBar数组,并将它们初始化为所选择的值,然后显示每个结构的内容。

    答:代码:

    #include<iostream>
    #include<string>
     
    struct CandyBar
    {
    std::string pinpai;    //品牌
    double weight;    //重量
    int kaluli;    //卡路里
    };
     
    int main()
    {
    using namespace std;
    CandyBar tang[3];
    tang[0] = { "大白兔奶糖",3.3,200 };
    tang[1] = { "小白兔奶糖",2.2,150 };
    tang[2] = { "巧克力糖",4.2,300 };
    cout << tang[0].pinpai << "的重量为" << tang[0].weight << ",卡路里含量为:" << tang[0].kaluli << endl;
    cout << tang[1].pinpai << "的重量为" << tang[1].weight << ",卡路里含量为:" << tang[1].kaluli << endl;
    cout << tang[2].pinpai << "的重量为" << tang[2].weight << ",卡路里含量为:" << tang[2].kaluli << endl;
    system("Pause");
    return 0;
    }
    View Code

    5.William Wingate从事比萨饼分析服务。对于每个比萨饼,他都需要记录下列信息:

    ● 披萨饼公司的名称,可以由多个单词组成。

    ● 披萨饼的直径。

    ● 披萨饼的重量。

    请设计一个能够储存这些信息的结构,并编写一个使用这种结构变量的程序。程序将请求用户输入上述信息,然后显示这些信息。请使用cin(或它的方法)和cout。

    答:代码:

    #include<iostream>
    #include<string>
     
    struct pisa
    {
    std::string gs;    //公司
    double zj;    //直径
    int zl;    //重量
    };
     
    int main()
    {
    using namespace std;
    cout << "这里可以帮你储存披萨饼的相关信息。
    请输入披萨饼的公司名称: ";
    pisa a;
    getline(cin, a.gs);
    cout << "请输入披萨饼的直径(英寸): ";
    cin >> a.zj;
    cout << "请输入披萨饼的重量(克): ";
    cin >> a.zl;
    cout << a.gs << "的披萨饼,直径为" << a.zj << "英寸,重量为" << a.zl << "克。" << endl;
    system("Pause");
    return 0;
    }
    View Code

    6.完成编程练习5,但使用new来为结构分配内存,而不是声明一个结构变量。另外,让程序在请求输入比萨饼公司名称之前输入比萨饼的直径。

    答:代码:

    #include<iostream>
    #include<string>
     
    struct pisa
    {
    std::string gs;    //公司
    double zj;    //直径
    int zl;    //重量
    };
     
    int main()
    {
    using namespace std;
    pisa *a = new pisa;    //使用动态结构数组
    cout << "这里可以帮你储存披萨饼的相关信息。" << endl;
    cout << "请输入披萨饼的直径(英寸): ";
    cin >> (*a).zj;
    cout<<"请输入披萨饼的公司名称: ";
    cin.get();    //读取掉换行符
    getline(cin, a->gs);
    cout << "请输入披萨饼的重量(克): ";
    cin >> a->zl;
    cout << a->gs << "的披萨饼,直径为" << a->zj << "英寸,重量为" << a->zl << "克。" << endl;
    system("Pause");
    return 0;
    }
    View Code

    7.完成编程练习4,但使用new来动态分配数组,而不是声明一个包含3个元素的CandyBar数组。

    答:代码:

    #include<iostream>
    #include<string>
     
    struct CandyBar
    {
    std::string pinpai;    //品牌
    double weight;    //重量
    int kaluli;    //卡路里
    };
     
    int main()
    {
    using namespace std;
    CandyBar *tang=new CandyBar[3];
    tang[0] = { "大白兔奶糖",3.3,200 };
    tang[1] = { "小白兔奶糖",2.2,150 };
    tang[2] = { "巧克力糖",4.2,300 };
    cout << tang[0].pinpai << "的重量为" << tang[0].weight << ",卡路里含量为:" << tang[0].kaluli << endl;
    cout << tang[1].pinpai << "的重量为" << tang[1].weight << ",卡路里含量为:" << tang[1].kaluli << endl;
    cout << tang[2].pinpai << "的重量为" << tang[2].weight << ",卡路里含量为:" << tang[2].kaluli << endl;
    system("Pause");
    return 0;
    }
    View Code

    8.编写一个程序,让用户输入三次40码跑的成绩(如果您愿意,也可让用户输入40米跑的成绩),并显示次数和平均成绩。请使用一个array对象来存储数据(如果编译不支持array类,请使用数组)。

    答:代码:

    #include<iostream>
    #include<array>
     
    int main()
    {
    using namespace std;
    const int b = 3;
    array<double, b>a;
    cout << "请输入三次四十米跑的成绩。
    请输入第一次的成绩(秒): ";
    cin >> a[0];
    cout << "请输入第二次的成绩(秒): ";
    cin >> a[1];
    cout << "请输入第三次的成绩(秒): ";
    cin >> a[2];
    cout << "" << b << "次的成绩分别为:" << a[0] << "秒、" << a[1] << "秒、" << a[2] << "秒。
    平均成绩为:" << (a[0] + a[1] + a[2]) / 3 << "秒。" << endl;
    system("pause");
    return 0;
    }
    View Code
  • 相关阅读:
    计算机为什么要从 0 开始计数?
    MySQL索引结构为什么是B+树
    expdp导出报错ORA-39127
    expdp 跳过坏块
    (转)没有索引导致的DIRECT PATH READ
    Python的实用场景有哪些
    Oracle索引修复 ,ORA-00600: internal error code, arguments: [6200],
    CentOS7.6静默安装19C实例脚本 ORA-27125 [FATAL] [DBT-10322]
    ORA-00313: 无法打开日志组
    cursor: pin S wait on X等待事件的处理过程(转载)
  • 原文地址:https://www.cnblogs.com/xzxl/p/7364169.html
Copyright © 2011-2022 走看看