码迷,mamicode.com
首页 > 编程语言 > 详细

《C++编程思想》第二章 数 据 抽 象(习题+答案)

时间:2015-07-27 01:56:38      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:c++   c++编程思想   c语言   

相关代码如下:

1.

<span style="font-size:18px;">/*声明与定义的区别*/

#include <iostream>
using namespace std;

extern int i;//声明
extern float f(float);//声明

float b;//定义+声明
float f(float a)//定义
{

	return a + 1.0;
}

int i;//定义
int h(int x)//定义+声明
{
	return x + 1;
}

int main()
{
	b = 1.0;
	i = 2;
	cout<<f(b)<<endl;
	cout<<h(i)<<endl;

	return 0;
}</span>

2.

<span style="font-size:18px;">/*test.h*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* 一个袖珍C库    C     */
typedef struct STASHtag
{
	int size;              //Size of each space
	int quantity;          //Number of storage spaces
	int next;              //Next empty space
	unsigned char* storage;//storage指针是一个unsigned char*。这是 C 编译器支持的最小的存储片,尽管在某些机器
                           //上它可能与最大的一般大,这依赖于具体实现。 storage指向的内存从堆中分配
}Stash;

void initialize(Stash* S, int Size);//initialize()完成对 struct stash 的必要的设置,即设置内部变量为适当的值。最初,设置
                                    //storage指针为零,设置size 指示器也为零,表示初始存储未被分配。
void cleanup(Stash* S);             //清除
int add(Stash* S, void* element);   //add()函数在stash的下一个可用位子上插入一个元素。首先,它检查是否有可用空间,如
                                    //果没有,它就用后面介绍的 inflate() 函数扩展存储空间。
void* fetch(Stash* S, int index);   //fetch()首先看索引是否越界,如果没有越界,返回所希望的变量地址,地址的计算采用与
                                    //add()中相同的方法
int count(Stash* S);                //返回所存储空间大小
void inflate(Stash* S, int increase);
/*inflate()函数使用realloc()为stash得到更大的空间块。 realloc()把已经分配而又希望重分配
的存储单元首地址作为它的第一个参数(如果这个参数为零,例如 initialize()刚刚被调用时,
realloc()分配一个新块)。第二个参数是这个块新的长度,如果这个长度比原来的小,这个块
将不需要作拷贝,简单地告诉堆管理器剩下的空间是空闲的。如果这个长度比原来的大,在堆
中没有足够的相临空间,所以要分配新块,并且要拷贝内存。 assert()检查以确信这个操作成
功。(如果这个堆用光了, malloc()、 calloc()和realloc()都返回零。)*/</span>

<span style="font-size:18px;">/*test.c*/

/*假设有一个程序设计工具,当创建时它的表现像一个数组,但它的长度能在运行时建
立。我称它为stash*/

#include "test.h"

void initialize(Stash* S, int Size)
{
	S->size = Size; 
	S->quantity = 0;
	S->storage = 0; 
	S->next = 0;    
}

void cleanup(Stash* S)
{
	if(S->storage)
	{
		puts("freeing storage");
		free(S->storage);
	}
}

int add(Stash* S, void* element)
{
	if(S->next >= S->quantity)
	{
		inflate(S,100);
	}
	memcpy(&(S->storage[S->next * S->size]),element,S->size );
	/*我们必须用标准 C 库函数memcpy( )一个字节一个字节地拷贝这个变量,第一个参数是 memcpy()
	开始拷贝字节的目的地址,由下面表达式产生:
	                &(S->storage[S->next * S->size])
	它指示从存储块开始的第 next个可用单元结束。这个数实际上就是已经用过的单元号加一
	的计数,它必须乘上每个单元拥有的字节数,产生按字节计算的偏移量。这不产生地址,而是
	产生处于这个地址的字节,为了产生地址,必须使用地址操作符 &。
	memcpy()的第二和第三个参数分别是被拷贝变量的开始地址和要拷贝的字节数。 n e x t计数
	器加一,并返回被存值的索引。这样,程序员可以在后面调用 fetch( )时用它来取得这个元素。*/
	S->next ++;
	return (S->next - 1);
}

void* fetch(Stash* S, int index)
{
	if(index >= S->next || index < 0)
	{
		return 0;
	}
	return &(S->storage[index * S->size]);
}

int count(Stash* S)
{
	return S->next;
}

void inflate(Stash* S, int increase)
{
	void* v = realloc(S->storage,(S->quantity + increase)*S->size );
	assert(v);
	S->storage = v;//在 C 库中的 inflate()中,可以将void *赋给其他任何指针,例如S->storage = v;而且编译器能够通过。
	S->quantity += increase;
}</span>


<span style="font-size:18px;">/*main.c*/

#include "test.h"

#define BUFSIZE 80

int main()
{
	Stash intStash,stringStash;
	int i;
	FILE* file;
	char buf[BUFSIZE];
	char* cp;

	initialize(&intStash,sizeof(int));
	for(i = 0;i < 100;++i)
	{
		add(&intStash,&i);
	}

	initialize(&stringStash,sizeof(char)*BUFSIZE);
	file = fopen("main.c","r");
	assert(file);
	while(fgets(buf, BUFSIZE, file))
	{
		add(&stringStash, buf);
	}
	fclose(file);

	for(i = 0;i < count(&intStash);++i)
	{
		printf("fetch(&intStash, %d) = %d\n",i ,
			*(int*)fetch(&intStash,i));
	}
	i = 0;
	while((cp = fetch(&stringStash,i++)) != 0)
	{
		printf("fetch(&stringStash, %d) = %s",
			i-1,cp);
	}
	putchar('\n');
	cleanup(&intStash);
	cleanup(&stringStash);

	return 0;
}</span>


3.

<span style="font-size:18px;">#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//C++
struct stash
{
	int size;                 //Size of each space
	int quantity;             //Number of storage spaces
	int next;                 //Next empty space
	unsigned char* storage;   //storage指针是一个unsigned char*。这是 C 编译器支持的最小的存储片,尽管在某些机器
	                          //上它可能与最大的一般大,这依赖于具体实现。 storage指向的内存从堆中分配
	void initialize(int Size);//initialize()完成对 struct stash 的必要的设置,即设置内部变量为适当的值。最初,设置
	                          //storage指针为零,设置size 指示器也为零,表示初始存储未被分配。
	void cleanup();           //清除
	int add(void* element);   //add()函数在stash的下一个可用位子上插入一个元素。首先,它检查是否有可用空间,如
	                          //果没有,它就用后面介绍的 inflate() 函数扩展存储空间。
	void* fetch(int index);   //fetch()首先看索引是否越界,如果没有越界,返回所希望的变量地址,地址的计算采用与
	                          //add()中相同的方法
	int count();              //返回所存储空间大小
	void inflate(int increase);
	/*inflate()函数使用realloc()为stash得到更大的空间块。 realloc()把已经分配而又希望重分配
	的存储单元首地址作为它的第一个参数(如果这个参数为零,例如 initialize()刚刚被调用时,
	realloc()分配一个新块)。第二个参数是这个块新的长度,如果这个长度比原来的小,这个块
	将不需要作拷贝,简单地告诉堆管理器剩下的空间是空闲的。如果这个长度比原来的大,在堆
	中没有足够的相临空间,所以要分配新块,并且要拷贝内存。 assert()检查以确信这个操作成
	功。(如果这个堆用光了, malloc()、 calloc()和realloc()都返回零。)*/
};
</span>


<span style="font-size:18px;">/*test.cpp*/

/*假设有一个程序设计工具,当创建时它的表现像一个数组,但它的长度能在运行时建
立。我称它为stash*/

#include "test.h"

void stash::initialize(int Size)
{
	size = Size; 
	quantity = 0;
	storage = 0; 
	next = 0;    
}

void stash::cleanup()
{
	if(storage)
	{
		puts("freeing storage");
		free(storage);
	}
}

int stash::add(void* element)
{
	if(next >= quantity)
	{
		inflate(100);
	}
	memcpy(&(storage[next * size]),element,size );
	/*我们必须用标准 C 库函数memcpy( )一个字节一个字节地拷贝这个变量,第一个参数是 memcpy()
	开始拷贝字节的目的地址,由下面表达式产生:
	                &(S->storage[S->next * S->size])
	它指示从存储块开始的第 next个可用单元结束。这个数实际上就是已经用过的单元号加一
	的计数,它必须乘上每个单元拥有的字节数,产生按字节计算的偏移量。这不产生地址,而是
	产生处于这个地址的字节,为了产生地址,必须使用地址操作符 &。
	memcpy()的第二和第三个参数分别是被拷贝变量的开始地址和要拷贝的字节数。 n e x t计数
	器加一,并返回被存值的索引。这样,程序员可以在后面调用 fetch( )时用它来取得这个元素。*/
	next ++;
	return (next - 1);
}

void* stash::fetch(int index)
{
	if(index >= next || index < 0)
	{
		return 0;
	}
	return &(storage[index * size]);
}

int stash::count()
{
	return next;
}

void stash::inflate( int increase)
{
	void* v = realloc(storage,(quantity + increase)*size );
	assert(v);
	storage = (unsigned char*)v;
	quantity += increase;
}</span>

<span style="font-size:18px;">#include "test.h"
#define BUFSIZE 80

int main()
{
	stash intStash,stringStash;
	int i;
	FILE* file;
	char buf[BUFSIZE];
	char* cp;

	intStash.initialize(sizeof(int));
	for(i = 0;i < 100;++i)
	{
		intStash.add(&i);
	}

	stringStash.initialize(sizeof(char)*BUFSIZE);
	file = fopen("main.cpp","r");
	assert(file);
	while(fgets(buf, BUFSIZE, file))
	{
		stringStash.add(buf);
	}
	fclose(file);

	for(i = 0;i < intStash.count();++i)
	{
		printf("intStash.fetch(%d) = %d\n",i,
			*(int*)intStash.fetch(i));
	}
	i = 0;
	while((cp = (char*)stringStash.fetch(i++)) != 0)
	{
	     printf("stringStash.fetch(%d) = %s",
			i-1,cp);
	}
	putchar('\n');
	intStash.cleanup();
	stringStash.cleanup();
	return 0;
}</span>

4.

<span style="font-size:18px;">/*1.h     C     */
typedef struct STASHtag
{
	int size;              //Size of each space
	int quantity;          //Number of storage spaces
	int next;              //Next empty space
	unsigned char* storage;//storage指针是一个unsigned char*。这是 C 编译器支持的最小的存储片,尽管在某些机器
                           //上它可能与最大的一般大,这依赖于具体实现。 storage指向的内存从堆中分配
}Stash;

void initialize(Stash* S, int Size);//initialize()完成对 struct stash 的必要的设置,即设置内部变量为适当的值。最初,设置
                                    //storage指针为零,设置size 指示器也为零,表示初始存储未被分配。
void cleanup(Stash* S);             //清除
int add(Stash* S, void* element);   //add()函数在stash的下一个可用位子上插入一个元素。首先,它检查是否有可用空间,如
                                    //果没有,它就用后面介绍的 inflate() 函数扩展存储空间。
void* fetch(Stash* S, int index);   //fetch()首先看索引是否越界,如果没有越界,返回所希望的变量地址,地址的计算采用与
                                    //add()中相同的方法
int count(Stash* S);                //返回所存储空间大小
void inflate(Stash* S, int increase);
/*inflate()函数使用realloc()为stash得到更大的空间块。 realloc()把已经分配而又希望重分配
的存储单元首地址作为它的第一个参数(如果这个参数为零,例如 initialize()刚刚被调用时,
realloc()分配一个新块)。第二个参数是这个块新的长度,如果这个长度比原来的小,这个块
将不需要作拷贝,简单地告诉堆管理器剩下的空间是空闲的。如果这个长度比原来的大,在堆
中没有足够的相临空间,所以要分配新块,并且要拷贝内存。 assert()检查以确信这个操作成
功。(如果这个堆用光了, malloc()、 calloc()和realloc()都返回零。)*/</span>


<span style="font-size:18px;">//C++2.h
struct stash
{
	int size;                 //Size of each space
	int quantity;             //Number of storage spaces
	int next;                 //Next empty space
	unsigned char* storage;   //storage指针是一个unsigned char*。这是 C 编译器支持的最小的存储片,尽管在某些机器
	                          //上它可能与最大的一般大,这依赖于具体实现。 storage指向的内存从堆中分配
	void initialize(int Size);//initialize()完成对 struct stash 的必要的设置,即设置内部变量为适当的值。最初,设置
	                          //storage指针为零,设置size 指示器也为零,表示初始存储未被分配。
	void cleanup();           //清除
	int add(void* element);   //add()函数在stash的下一个可用位子上插入一个元素。首先,它检查是否有可用空间,如
	                          //果没有,它就用后面介绍的 inflate() 函数扩展存储空间。
	void* fetch(int index);   //fetch()首先看索引是否越界,如果没有越界,返回所希望的变量地址,地址的计算采用与
	                          //add()中相同的方法
	int count();              //返回所存储空间大小
	void inflate(int increase);
	/*inflate()函数使用realloc()为stash得到更大的空间块。 realloc()把已经分配而又希望重分配
	的存储单元首地址作为它的第一个参数(如果这个参数为零,例如 initialize()刚刚被调用时,
	realloc()分配一个新块)。第二个参数是这个块新的长度,如果这个长度比原来的小,这个块
	将不需要作拷贝,简单地告诉堆管理器剩下的空间是空闲的。如果这个长度比原来的大,在堆
	中没有足够的相临空间,所以要分配新块,并且要拷贝内存。 assert()检查以确信这个操作成
	功。(如果这个堆用光了, malloc()、 calloc()和realloc()都返回零。)*/
};
</span>

<span style="font-size:18px;">#include "1.h"
#include "2.h"
#include <stdio.h>

struct A
{
	int I[100];
};

struct B
{
	void f();
};

void B::f()
{}

int main()
{
	printf("sizeof struct A = %d bytes\n",
		sizeof(A));//每个 int 占二个字节
	printf("sizeof struct B = %d bytes\n",
		sizeof(B));//struct B 是奇异的,因为它是没有数据成员的 struct
	printf("sizeof Stash in C = %d bytes\n",
		sizeof(Stash));
	printf("sizeof stash in C++ = %d bytes\n",
		sizeof(stash));
	/*最后两个 sizeof 语句表明在 C++ 中的结构长度与 C 中等价版本的长度相同。 C++ 尽力不
    增加任何花费*/

	return 0;
}</span>


5.

<span style="font-size:18px;">#ifndef NESTED_H_
#define NESTED_H_

struct stack//这个嵌套 struct 称为 link,它包括指向这个表中的下一个 link 的指针和指向存放在 link 中的数据的指针,如果 next 指针是零,意味着表尾。
{
	struct link
	{
		void* data;
		link* next;
		void initialize(void* Data, link* Next);
	}*head;
	void initialize();
	void push(void* Data);
	void* peek();
	void* pop();
	void cleanup();//cleanup 去除每个栈元素,并释放data 指针
};
#endif</span>


<span style="font-size:18px;">#include "nested.h"
#include <stdlib.h>
#include <assert.h>

void stack::link::initialize(void* Data, link* Next)
//简单地两次使用范围分解运算符,以指明这个嵌套 struct 的名字。 stack::link::initialize( ) 函数取参数并把参数赋给它的成员们
{
	data = Data;
	next = Next;
}

void stack::initialize()
//stack::initialize( ) 函数置 head 为零,使得这个对象知道它有一个空表
{
	head = 0;
}

void stack::push(void* Data)
//stack::push( ) 取参数,也就是一个指向希望用这个 stack 保存的一块数据的指针,并且把
//这个指针放在栈顶
{
	link* newlink = (link*)malloc(sizeof(link));
	assert(newlink);
	newlink->initialize(Data, head);
	head = newlink;
}

void* stack::peek()
//返回head的值
{
	return head->data;
}

void* stack::pop()
//stack::pop( )取出当前在该栈顶部的 data 指针,然后向下移 head 指针,删除该栈老的栈顶元素
{
	if(head == 0)
	{
		return 0;
	}
	void* result = head->data;
	link* oldHead = head;
	head = head->next;
	free(oldHead);
	return result;
}

void stack::cleanup()
//stack::cleanup()创建cursor 在整个栈上移动,用free()释放每个link的data和link 本身
{
	link* cursor = head;
	while(head)
	{
		cursor = cursor->next;
		free(head->data);
		free(head);
		head = cursor;
	}
}</span>


<span style="font-size:18px;">#include "nested.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define BUFSIZE 100

int main(int argc, char** argv)
{
	stack textlines;
	FILE* file;
	char* s;
	char buf[BUFSIZE];
	assert(argc == 2);
	textlines.initialize();
	file = fopen(argv[1],"r");
	assert(file);
	while(fgets(buf, BUFSIZE, file))
	{
		char* string = (char*)malloc(strlen(buf)+1);
		assert(string);
		strcpy(string, buf);
		textlines.push(string);
	}

	while((s = (char*)textlines.pop()) != 0 )
	{
		printf("%s",s);
		free(s);
	}
	textlines.cleanup();

	return 0;
}</span>


6.

<span style="font-size:18px;">#include <iostream>
using namespace std;
//如果在 S::f() 中没有范围分解,
//编译器会缺省地选择 f() 和 A 的成员版本
int A;
void f()
{}

struct S
{
	int A;
	void f();
};

void S::f()
{
	::f();
	::A++;
	A--;
}
int main()
{
	return 0;
}</span>



1) 创建一个 struct 声明,它有单个成员函数,然后对这个成员函数创建定义。创建这个新数据类型的对象,再调用这个成员函数。

#include <iostream>
using namespace std;

struct Student
{
	void play();
};

void Student::play()
{
	cout<<"Funny!"<<endl;
}

int main()
{
	Student s;
	s.play();
	return 0;
}


2) 编写并且编译一段代码,这段代码完成数据成员选择和函数调用。

#include <iostream>
#include <string>
using namespace std;

struct Student
{
	string address;
	void play(string address);
};

void Student::play(string address)
{
	cout<<address<<" "<<"is Funny!"<<endl;
}

int main()
{
	Student s;
	s.play("Xi'an");
	return 0;
}


3) 写一个在另一个结构中的被声明结构的例子(嵌套结构)。并说明如何定义这个结构的成员。

#include <iostream>
#include <string>
using namespace std;

#ifndef TEST_H_
#define TSET_H_

struct family
{
	struct school
	{
		string address;
		void schools(string address);
	}*addr;
	int number;
	void families(int number);
};

#endif

#include "test.h"

void family::school::schools(string address)//取参数并输出
{
	cout<<"The school's address: "<<address<<endl;
}
void family::families(int number)//取参数并输出
{
	cout<<"The family's people number: "<<number<<endl;
}

#include "test.h"

int main()
{
	family f; 
	f.families(5);

	return 0;
}


4) 结构有多大?写一段能打印各个结构的长度的代码。创建一些结构,它们只有数据成员,另一些有数据成员和函数成员。然后创建一个结构,它根本没有成员。打印出所有这些结构的长度。对于根本没有成员的结构的结果作出解释。

#include <stdio.h>

struct A
{
	char a;
	int  b;
};

struct B
{
	void f();
	double d;
};

struct C
{

};

void B::f()
{}

int main()
{
	printf("sizeof struct A = %d bytes\n",
		sizeof(A));//每个 int 占四个字节,char占一个字节,但是要是四的倍数即为八
	printf("sizeof struct B = %d bytes\n",
		sizeof(B));//每个double占八个字节,函数字节数为八
	printf("sizeof struct C = %d bytes\n",
		sizeof(C));//struct C 是奇异的,因为它是没有数据成员的 struct

	return 0;
}


5) C++对于枚举、联合和 struct 自动创建 typedef 的等价物,正如在本章中看到的。写一个能说明这一点的小程序。

#include <iostream>
#include <string>
using namespace std;

typedef struct 
{
	int age;
	string address;
}student;

typedef union
{
	int a;
	double d;
}number;

typedef enum
{
	white,black,blue,green
}colour;

int main()
{
	student s;
	s.address = "Xi'an";
	s.age = 18;
	cout<<"student's address: "<<s.address<<endl;
	cout<<"student's age: "<<s.age<<endl;

	number n;
	n.a = 5;
	cout<<"people number:"<<n.a<<endl;

	colour c = white;
	cout<<"number of enum: "<<c<<endl;

	return 0;
}


对于上述答案仅供参考,如有错误希望大家指出,谢谢大家。



版权声明:本文为博主原创文章,未经博主允许不得转载。

《C++编程思想》第二章 数 据 抽 象(习题+答案)

标签:c++   c++编程思想   c语言   

原文地址:http://blog.csdn.net/qaz3171210/article/details/47075335

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!