C++学习(八)入门篇——复合类型

来源:互联网 发布:do as infinity 知乎 编辑:程序博客网 时间:2024/06/05 03:02

数组(需要声明以下三点):

(1)存储在每个元素中值的类型

(2)数组名

(3)数组中的元素数

声明数组的通用格式如下:

typeName arrayName[arraySize];arraySize不能是变量;

float loans[20]表示loans数组是使用float类型创建的,C++数组从0开始编号。

编译器不会检查使用的下标是否有效,如果将一个值赋给不存在的元素months[101]编译器不会指出错误,但会引发问题,破坏数据或代码或使程序异常终止。

程序清单4.1 arrayone.cpp//arrayone.cpp - - small arrays of integers#include<iostream>int main(){    using namespace std;    int yams[3];    yams[0] = 7;    yams[1] = 8;    yams[2] = 6;    int yamcosts[3] = { 20, 30, 5 };             //只要提供一个用逗号分隔的值列表,并用花括号括起来即可    cout << "Total yams = ";    cout << yams[0] + yams[1] + yams[2] << endl;     cout << "The package with " << yams[1] << " yams costs ";    cout<<yamcosts[1]<<    " cents per yam.\n";    int total = yams[0] * yamcosts[0] + yams[1] * yamcosts[1] + yams[2] * yamcosts[2];    total = total + yams[2] * yamcosts[2];    cout << "The total yam expense is " << total << " cents.\n";    cout << "\nSize of yams array = " << sizeof yams;      //整个数组字节数    cout << " bytes.\n";    cout << "Size of one elements = " << sizeof yams[0];   //一个元素字节数    cout << "bytes.\n";    cin.get();}

得到:

 

1.数组的初始化规则

只有在定义数组时才能初始化

int cards[4] = {3,6,8,10};

int hand [4];

hand [4] = {5,6,7,9};    不允许

hand =cards;               不允许

初始化数组时,提供的值可以少于数组的元素数目,其他元素将被设置为0,将数组所以元素都初始化为0,只要让第一个元素为0即可

long totals[500] = {0};

如果初始化数组时方括号为空,C++编译器将计算元素个数

short things[] ={1,5,3,8}

编译器将使things数组包含4个元素

如果主要关心的是程序,而不是自己知道数组的大小,可以这样做

short things [ ] ={1,5,3,8};

int num_elements = sizeof things / sizeof (short);

 

C++初始化新增了一些新功能

比如省略=

double earning[4] {1.2e4, 1.6e4, 1.1e4,1.7e4};

其次可不在大括号里包含任何东西,这将把所有元素都设置为零

unsigned int counts [10] = { };

float balances [100] { };

第三,列表初始化禁止缩窄转换

long plifs [ ] ={25,92,3.0};     不行,因为浮点数转化为整型是缩窄

char slifs [4] {'h','i',1122011, '\0'};    不行,因为1122011超过了char的取值范围

char tlifs  [4] {'h','i',112,'\0'};     可以

 

2.字符串

C++处理字符串的方式有两种,C风格字符串和基于string类库的方法。

C字符串具有一种特殊的性质,以空字符结尾,空字符被写作\0,ASCII码为0,用来标记字符串的结尾。

看以下两个声明:

char dog[8] = {‘b’,‘e’,‘a’,‘u’,‘x’,‘ ’,‘I’,‘I’};   是字符串

char cat[8] ={'f ', 'a', 't', 'e', 's' , 's', 'a', '\0'};                 不是字符串

空字符对C风格字符串至关重要,用cout显示cat字符串,将显示前7个字符,遇到空格后停止,而dog将打印8个,并接着将内存中随后各个字节解释为要打印的字符,知道遇到空字符为止。

也可以使用以下方法:

char bird[11] ="Mr.Cheeps";

char fish[ ] ="Bubbles";

用引号括起的字符串隐式的包括结尾的空字符

在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内。

 

注意:字符串常量(使用双引号)不能与字符常量(使用单引号)互换

'S'只是字符串编码的简写方式,在ASCII只是83的另一种写法

char shirt_size =‘S’;

将83赋给了shirt_size

 

“S”不是字符常量,而是S和\0组成的字符串,“S”实际表示字符串所在的内存地址

char shirt_size = "S";

将一个内存地址赋给shirt_size。

由于地址在C++中属于一个独立的类型,C++编译器不允许这种不合理的做法

 

C++允许拼接字符串字面值,即将两个用引号括起的字符串合并为一个。

任何两个由空白(空格、制表符、换行符)分隔的字符串常量都将拼接成一个(不考虑\0)

 

3.在数组中使用字符串

最常用的两个方法——将数组初始化为字符串常量,将键盘或文件输入读入到数组中。

标准头文件cstring提供了该函数以及很多与字符串相关的其他函数的声明

程序清单4.2  string.cpp//strings.cpp - - storing strings in an array#include<iostream>#include<cstring>int main(){    using namespace std;    const int Size = 15;    char name1[Size];    char name2[Size] = "C++owboy";    cout << "Howdy!I'm " << name2;    cout << "! What's your name?\n";    cin >> name1;    cin.get();    cout << "Well, " << name1 << ",your name has ";    cout << strlen(name1) << " lettrs and is stored\n";    cout << "in an array of " << sizeof(name1) << " bytes.\n";    cout << "Your initial is " << name1[0] << ".\n";    name2[3] = '\0';    cout << "Here are the first 3 characters of my name:";    cout << name2 << endl;    cin.get();}

输出:

sizeof运算符指的是整个数组的长度,而strlen函数返回的是存储在数组中的字符串的长度,而且是突然类只计算可见的字符,不把空字符计算在内

 

程序清单4.3  instr1.cpp//instr1.cpp - - reading more than one string#include<iostream>int main(){    using namespace std;    const int ArSize = 20;    char name[ArSize];    char dessert[ArSize];    cout << "Enter your name:\n";    cin >> name;    cout << "Enter your favorite dessert:\n";    cin >> dessert;    cin.get();    cout << "I have some delicious " << dessert;    cout << " for you, " << name <<".\n";    cin.get();}

得到输出:

可以看到,这个程序有个小缺陷,cin使用空白(空格、制表符和换行符)来确定字符串的结束位置。意味着cin在获取字符数组输入时只读取一个单词,并在结尾自动添加空字符。

采用每次读取一行字符串输入来解决(需要面向行而不是面向单词)

面向行的类成员函数:get()和getline()

这两个函数都读取一行输入,直到到达换行符,getline()将丢弃换行符,get()将换行符保留在输入序列中

这里先讨论getline()

通过回车键输入的换行符来确定结尾,cin.getline(name,20)第一个存储输入行的数组名称,第二个是要读取的字符数

如果参数为20,则函数最多读取19个字符,余下空间用来存储自动在结尾处添加的空字符

程序清单4.4  instr2.cpp//instr2.cpp - - reading more than one word with getline#include<iostream>int main(){    using namespace std;    const int ArSize=20;    char name[ArSize];    char dessert[ArSize];    cout<<"Enter your name:\n";    cin.getline(name, ArSize);    cout << "Enter your favorite dessert:\n";    cin.getline(dessert, ArSize);    cout << "I have some delicious " << dessert;    cout << " for you, " << name << " .\n";    cin.get();}

输出结果:

cin.getline()读取字符串并将换行符替换成空字符,不保存换行符

 

如果使用get()输入

连续两次调用get()时,第一次调用后,换行符将留在输入队列中,第二次调用时遇到第一个字符就是换行符,那么get()认为已到达行尾,无法读取任何内容。

因此采用以下的方式:

cin.get(name,ArSize);  //要将一个字符串放入数组中

cin.get();                         //处理换行符,读取一个字符

cin.get(dessert,ArSize);

 

另一种使用get()方式将两个类成员函数拼接起来

cin.get(name,ArSize).get();返回一个cin对象,随后被用来调用get()函数,处理掉换行符

cin.getline(name1,ArSize).getline(name2,ArSize);调用效果与两次调用cin.getline()相同

程序清单4.5  instr3.cpp//instr3.cpp - - reading more than one word with get()&get()#include<iostream>int main(){    using namespace std;    const int ArSize = 20;    char name[ArSize];    char dessert[ArSize];    cout << "Enter your name:\n";    cin.get(name, ArSize).get();    cout << "Enter your favorite dessert:\n";    cin.get(dessert, ArSize).get();    cout << "I have some delicious " << dessert;    cout << " for you, " << name << ".\n";    cin.get();}

得到输出:

 

get()和getline()相比,输入更仔细,它可以根据查看下一个字符是换行符或者不是来判断,停止读取的原因是已经读取了整行而不是数组已填满。

当get()读取空行侯江设置失效位,意味着接下来的输入将被阻断,可用以下命令恢复:

cin.clear();

当输入字符串比分配空间长,则getline()和get()将余下的字留在输入队列中,而getline还会设置失效位,并关闭后面的输入。

 

当混合输入数字和面向行的字符串会导致问题

程序清单4.6  numstr.cpp//numstr.cpp - - following number input with line input#include<iostream>int main(){    using namespace std;    cout << "What year was your house built?\n";    int year;    cin >> year;    cout << "What is its street address?\n";    char address[80];    cin.getline(address, 80);    cout << "Year built: " << year << endl;    cout << "Address: " << address << endl;    cout << "Done!\n";    cin.get();}

得到结果为:

当cin读取年份,将回车键生成的换行符留在了输入队列中,后面的cin.getline()看到换行符后认为是一个空行

所以在读取地址之前应该先丢弃换行符

可以在

cin >> year;后加
cin.get();

或者(cin.year).get();

则可以正常工作

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信给空号充话费了怎么办 微信充话费充错号码是空号怎么办 淘宝充流量不到账怎么办 微信退货不退款怎么办 京东话费交错号怎么办? 微信缴费错了怎么办 给手机充话费被退款怎么办 买到假货淘宝商家已关店怎么办 手机刷错系统了怎么办 苹果手机成砖了怎么办 苹果6p变砖头怎么办 苹果刷成石头了怎么办 苹果手机更新成了砖头怎么办 京东售后好慢怎么办 京东商品超过售后期怎么办 京东过了售后期怎么办 京东售后不处理怎么办 京东售后不让退货怎么办 天猫盒子遥控器丢了怎么办 淘宝店铺的客服不理人怎么办 淘宝假货下架了怎么办 淘宝不让发布本地生活服务了怎么办 淘宝删除差评后店家不返现怎么办 天猫店家迟迟不发货怎么办 淘宝下单后店家说缺货怎么办 用淘宝把话费冲到空号上怎么办 d速快递没有网点怎么办 京东买的货没收到怎么办 淘宝物流显示已揽件就是不动怎么办 淘宝查不到物流信息怎么办 快递物流信息更新错怎么办 淘宝上查不到物流怎么办 微信买的东西不给退怎么办 微信购物已收货怎么办 微信买东西不退怎么办 银行经营贷款资金回流怎么办 淘宝有运费险换货怎么办 淘宝有运费险的换货怎么办 淘宝换货一直不发货怎么办 淘宝申请换货卖家不发货怎么办 淘宝买家泄露卖家信息怎么办