日常应用中,简单的C++的简单基本类型,无法满足其数据的要求。于是便诞生了——复合类型。这种类型是基于基本整形和浮点类型创建的。影响最为深远的复合类型是类,是OOP的一个难点。
1.1 数组
-
定义:数组(array)是一种数据格式,能够存储多个同类型的值。
例如,数组可以存储60个int类型的值(这些值表示游戏5年来的销售量)。 -
存储:每个值都存储在一个独立的数组元素中,计算机在内存中依次存储数组的各个元素。
-
创建:创建数组,可使用声明语句。数组声明应指出以下三点:
- 存储在每个元素中的值的类型;
- 数组名;
- 数组中的元素数;
-
格式:
typeName arrayName[arraySize]
:- arraySize:指定元素数目,必须为整型常数(如 8)或 const值,也可以是常量表达式(如 8*sizeof(int)),其值必须已知,不能是变量。
-
注意:不能仅仅将某种东西声明为数组,它必须是特定类型的数组。没有通用的数组类型,但存在许多特定数组类型。如 char 数组 或 long 数组。
-
用途 :可以单独访问数组元素。通过使用下标或索引来对元素进行编号。(C++数组从0开始编号)。数组声明能够使用一个声明创建大量的变量,然后便可以用索引来标识和访问各个元素。
-
程序清单:
#include <iostream>
int main()
{
using namespace std;
int yams[3]; //创建含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. "<<endl;
int total = yams[0]*yamcosts[0]+yams[1]*yamcosts[1];
total = total + yams[2]*yamcosts[2];
cout<<"The total yam expense is "<<total<<" cents."<<endl;
cout<<"\nSize of yams array = "<<sizeof yams;
cout<<" bytes.\n";
cout<<"Size of one element: "<<sizeof yams[0];
cout<<" bytes.\n";
return 0;
}
输出结果:
Total yams = 21
The package with 8 yams costs 30 cents per yam.
The total yam expense is 410 cents.
Size of yams array = 12 bytes.
Size of one element: 4 bytes.
-
数组的初始化规则:只有在定义数组时才能使用初始化,此后就不能使用了,也不能将一个数组赋给另一个数组。
- 可使用下标分别给数组中的元素赋值;
- 初始化数组时,提供的值可以少于数组的元素数目。其他元素会置0处理。
-
数组初始化方法:
-
可省略等号(=);
- double earnings [4] {1.2e4 , 1.6e4, 1.1e4, 1.7e4}
-
可不在大括号内包含任何东西,这将把所有元素都置为零;
-
列表初始化,禁止缩窄转换,值不能超出或低于列表类型范围。
-
1.2 字符串
字符串:是存储在内存的连续字节中的一系列字符。存储连续直接中的一系列字符,意味着可以将字符串存储在char数组中,其中每个字符都位于自己的数组元素中。
处理方式:
-
c-风格字符串:
具有一种特殊的性质:以空字符(null charater)结尾,空字符被写作\0,其ASCII码为0,用来标记字符串的结尾。
char dog[8] = {‘b’, ‘e’, ‘a’, ‘u’, ‘x’, ’ ', ‘I’, ‘I’ }; //不是字符串
char cat[8] = {‘f’, ‘a’, ‘t’, ‘e’, ‘s’, ‘s’, ‘a’, ‘\0’}; //是字符串
如果没有以空字符(null charater)结尾,程序会一直执行,直到遇见为止。 -
基于string类库的方法
针对c-风格字符串操作繁杂——使用大量单引号,且必须记住加上控制符。string类库的方法——只需要一个单引号括起来的字符串即可,这种字符串被称为字符串常量(string constant)或字符串面值(string literal)。如下所示:
char bird[11] = “Mr. Cheeps”; //隐式地包括结尾的空字符
char fish[] = “Bubbles”;
- 注意:字符串常量(使用双引号,如"S",表示由两个字符(字符S和\0)组成的字符串)不能与字符常量互换(使用单引号,如’S’,'S’只是83的另一种写法)。
1.2.1 拼接字符串常量
任何两个由空白(空格、制表符和换行符)分隔的字符串常量都将自动
拼接成一个。
1.2.2 在数组中使用字符串
方法:
- 将数组初始化为字符串常量
- 将键盘或文件输入读入到数组中
程序清单:
# 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;
cout << "Well, " << name1 << ", your name has ";
cout << strlen(name1) << " letters 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;
return 0;
}
输出结果:
Howdy! I'm C++ owboy! What's your name?
kuka
Well, kuka, your name has 4 letters and is stored
in an array of 15 bytes.
your initial is k.
Here are the first 3 characters of my name: C++
请按任意键继续. . .
1.2.3 字符串输入
程序清单:
# 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;
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
return 0;
}
结果显示:
Enter your name:
kuaka kuaka
Enter your favorite dessert:
I have some delicious kuaka for you, kuaka.
请按任意键继续. . .
1.2.4 每次读取一行字符传输入
1.面向行的输入:getline()
- 定义:getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。
- 调用:cin.getline(),第一个参数是用来存储输入行的数组名称,第二个参数是要读取的字符数。
- 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";
return 0;
}
结果输出:
Enter your name:
Lee xin ming
Enter your favorite dessert:
fried noodles
I have some delicious fried noodles for you, Lee xin ming.
请按任意键继续. . .
2.面向行的输入:get()
-
特点:与getline()类似,接受参数相同、解释参数的方式也相同
-
差异:get() 并不再读取并丢弃换行符,而是将其留在输入队列中。如果再次调用时第一个看到的就是换行符,所以没有发现可读取的内容。
-如:
cin.get(name,ArSize);
cin.get(dessert,ArSize); -
升级:使用不带任何参数的cin.get()调用可读取下一个字符(即使是换行符)。
- 如:
cin.get(name,ArSize);
cin.get();
cin.get(dessert,ArSize);
- 如:
-
使用get()的方式是将两个类成员函数拼接起来(合并)
-cin.get(name, ArSize).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";
return 0;
}
结果输出:
Enter your name:
Lee xin ming
Enter your favorite dessert:
fried noodles
I have some delicious fried noodles for you, Lee xin ming.
请按任意键继续. . .
1.2.5 混合输入字符串和数字
混合输入数字和面向行的字符串会导致问题。
#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";
return 0;
}
结果输出:
What year was your house built?
1966
What is its street address?
Year built: 1966
Address:
Done!
请按任意键继续. . .
稍微变一下:
cin>>year;
cin.get();
结果输出:
What year was your house built?
55
What is its street address?
ddd2222c
Year built: 55
Address: ddd2222c
Done!
请按任意键继续. . .