C++语言指南(十六)——数据结构体

*********************************************************

       原文:http://www.cplusplus.com/doc/tutorial/

*********************************************************


数据结构体
我们已经学习了如何在 C++ 中使用成组的连续数据。但是这总是有些限制,因为在很多情况中我们想存储的不仅仅是所有元素都是相同数据类型的序列,而是不同元素拥有不同数据类型的集合。
数据结构体
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
一个数据结构体就是被组合到一个名字底下的一组数据元素。这些数据元素,叫做“成员( members ”,可以有不同的类型和不同的长度。数据结构体用下面的文法来在 C++ 中声明:

struct structure_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;

其中 structure_name 是这个结构体类型的名字, object_name 可以是一些有效的标识符,这些标识符用来标示那些拥有这个结构体类型的对象。在花括号 {} 中是数据成员的一个列表,每一个都用一个类型和一个作为其名字的有效的标识符来说明。
我们需要知道的第一件事是:数据结构体创造了一个新的数据类型:一旦一个数据结构体被声明,一个以 structure_name 作为标识符的新的数据类型就被创建了,并且可以在程序的其他地方像使用任何其他类型那样被使用。例如:
struct product {
 int weight;
 float price;
} ;
 
product apple;
product banana, melon;
我们首先声明了一个叫做 product 的结构体类型,它有两个成员: weight price ,每个都是不同的基本数据类型。然后我们用结构体类型的这个名字( product )声明了三个这种类型的对象: apple banana melon ,就像我们定义任何基本数据类型的对象那样。
一旦被声明了, product 就成为了同基本数据类型如 int char short 相像的新的有效的类型名,并且从那点起我们能够声明这种新的复合类型的对象(变量)了,就像我们对 apple banana melon 做的那样。
在结构体声明一结束,并且在表示结束的分号之前,我们可以用可选域 object_name 来直接声明这种结构体类型的对象。例如,我们也可以在我们定义这个数据结构体类型的同时就声明这个结构体的对象 apple banana melon ,方法是:
struct product {
 int weight;
 float price;
} apple, banana, melon;
清楚什么是结构体类型名和什么是有这种结构体类型的一个对象(变量)是非常重要的。我们可以从一个单独得结构体类型( product )实例化得到很多对象(变量,如: apple banana melon )。
一旦我们声明了我们的三个确定结构体类型的对象( apple banana melon ),我们就可以直接操作它们的成员。为了这么作我们使用一个点( . )插入到对象名和成员名之间。例如,我们可以像这些元素是他们类型的标准变量那样来操作他们:
apple.weight
apple.price
banana.weight
banana.price
melon.weight
melon.price

他们每一个的数据类型同这些成员他们本身的类型一致: apple.weight, banana.weight melon.weightint型;而apple.price, banana.price melon.price float.

让我们来看一个真实的例子,从中你可以看到一个结构体类型是如何被像基本类型那样使用的:
/
/ example about structures
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
 
struct movies_t {
 string title;
 int year;
} mine, yours;
 
void printmovie (movies_t movie);
 
int main ()
{
 string mystr;
 

 mine.title = "2001 A Space Odyssey";

 mine.year = 1968;
 
 cout << "Enter title: " ;
 getline (cin,yours.title);
 cout << "Enter year: " ;
 getline (cin,mystr);

 stringstream(mystr) >> yours.year;

 
 cout << "My favorite movie is:/n " ;
 printmovie (mine);
 cout << "And yours is:/n " ;
 printmovie (yours);
 return 0;
}
 
void printmovie (movies_t movie)
{
 cout << movie.title;
 cout << " (" << movie.year << ")/n" ;
}
Enter title: Alien
Enter year: 1979
 
My favorite movie is:
 2001 A Space Odyssey (1968)
And yours is:
 Alien (1979)
这个例子展现了我们是如何像使用普通变量那样来使用一个对象的成员的。例如,成员 yours.year 是一个有效的 int 型变量,而 mine.title 是一个有效的 string 型变量。
对象 mine yours 也可以被作为类型 movies_t 的有效变量来对待,例如,我们把它们就像我们对通常的变量那样,传递给了函数 printmovie 。因此,数据结构体的一个最主要有点就是:我们即可以分别使用它们的成员,也可以只用一个标识符来把整个结构体看作是一个块。
数据结构体是一个可以被用来描述数据库的特性,特别是如果我们考虑创建它们的数组的可能:
// array of structures
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
 
#define N_MOVIES 3
 
struct movies_t {
 string title;
 int year;
} films [N_MOVIES];
 
void printmovie (movies_t movie);
 
int main ()
{
 string mystr;
 int n;
 
 for (n=0; n<N_MOVIES; n++)
 {
    cout << "Enter title: " ;
    getline (cin,films[n].title);
    cout << "Enter year: " ;
    getline (cin,mystr);

    stringstream(mystr) >> films[n].year;

 }
 
 cout << "/nYou have entered these movies:/n" ;
 for (n=0; n<N_MOVIES; n++)
    printmovie (films[n]);
 return 0;
}
 
void printmovie (movies_t movie)
{
 cout << movie.title;
 cout << " (" << movie.year << ")/n" ;
}
Enter title: Blade Runner
Enter year: 1982
Enter title: Matrix
Enter year: 1999
Enter title: Taxi Driver
Enter year: 1976
 
You have entered these movies:
Blade Runner (1982)
Matrix (1999)
Taxi Driver (1976)
指向结构体的指针
同任何其他类型相同,结构体可以被它自身类型的指针所指向:
struct movies_t {
 string title;
 int year;
};
 
movies_t amovie;
movies_t * pmovie;
这里 amovie movies_t 类型的一个对象,而 pmovie 是一个指向类型 movies_t 对象的指针。因此,下面的代码也是有效的:
pmovie = &amovie;
指针 pmovie 的值将被赋为对象 amovie 的一个引用(它的内存地址)。
我们现在将看一个包含指针的另一例子,它同时被用来介绍一个新的操作符:箭头操作符( arrow pcerator )( -> ):
// pointers to structures
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
 
struct movies_t {
 string title;
 int year;
};
 
int main ()
{
 string mystr;
 
 movies_t amovie;
 movies_t * pmovie;
 pmovie = &amovie;
 
 cout << "Enter title: " ;
 getline (cin, pmovie->title);
 cout << "Enter year: " ;
 getline (cin, mystr);

 (stringstream) mystr >> pmovie->year;

 
 cout << "/nYou have entered:/n" ;
 cout << pmovie->title;
 cout << " (" << pmovie->year << ")/n" ;
 
 return 0;
}
Enter title: Invasion of the body snatchers
Enter year: 1978
 
You have entered:
Invasion of the body snatchers (1978)
前面的代码包含一个很重要的介绍:箭头操作符( -> )。这是一个只用于指向带有成员的对象的指针的间接取值操作符。这个操作符用来访问我们所引用的对象的一个成员。在例子中我们用了:
pmovie->title
这和下面表达式的目的是相同的:
 (*pmovie).title

两个表达式pmovie->title (*pmovie).title都是有效的,而且都意味着我们在计算被叫做pmovie的指针指向的数据结构体的成员title。你必须清楚同:

*pmovie.title
的区别,它等价于 :
*(pmovie.title)
那将访问被叫做 title 的成员,前提它是一个指针,所指向的值。下面的表格总结了可能的指针和结构体成员的组合:
表达式
含义
等价于
a.b
对象 a 的成员 b
 
a->b
a 指向的对象的成员 b
(*a).b
*a.b
对象 a 的成员 b 所指向的值
*(a.b)
结构体的嵌套
结构体也能被嵌套,因此一个结构体的一个有效的元素也可以是另一个结构体变量。
s
truct movies_t {
 string title;
 int year;
};
 
struct friends_t {
 string name;
 string email;
 movies_t favorite_movie;
 } charlie, maria;
 
friends_t * pfriends = &charlie;
在前面的声明之后,我么可以使用下面任何一个表达式:
c
harlie.name
maria.favorite_movie.title
charlie.favorite_movie.year
pfriends->favorite_movie.year
(顺便说一下,其中最后两个表达式涉及同一个成员)。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值