相关代码例如以下:

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++编程思想》第二章 数 据 抽 象(原书代码+习题+答案)的更多相关文章

  1. 《C++编程思想》第四章 初始化与清除(原书代码+习题+解答)

    相关代码: 1. #include <stdio.h> class tree { int height; public: tree(int initialHeight); ~tree(); ...

  2. [Java编程思想] 第二章 一切都是对象

    第二章 一切都是对象 2.1 用引用操纵对象   创建一个String引用: String s;   这里所创建的只是引用,并不是对象.   创建一个引用的同时便初始化: String s = &qu ...

  3. JAVA编程思想第二章答案

    欢迎访问我的CSDN博客查看https://mp.csdn.net/mdeditor/94797839# 有其他问题欢迎发送邮箱至hpzhangjunjiell@163.com 感谢

  4. [书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

    本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解J ...

  5. 3-8《Ruby元编程》第二章对象模型

    <Ruby元编程> 第二章 对象模型 类定义揭秘inside class definitions: class关键字更像一个作用域操作符,核心作用是可以在里面随时定义方法. [].meth ...

  6. 第二章:排序算法 及其他 Java代码实现

    目录 第二章:排序算法 及其他 Java代码实现 插入排序 归并排序 选择排序算法 冒泡排序 查找算法 习题 2.3.7 第二章:排序算法 及其他 Java代码实现 --算法导论(Introducti ...

  7. c++学习书籍推荐《C++编程思想第二卷》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <C++编程思想>(第2卷)是惟一一本如此清晰地阐述如何重新思考以面向对象方法构造程序的书籍.<C++编程思想>(第2卷)介绍实用的编 ...

  8. [Java编程思想] 第一章 对象导论

    第一章 对象导论 "我们之所以将自然界分解,组织成各种概念,并按其含义分类,主要是因为我们是整个口语交流社会共同遵守的协定的参与者,这个协定以语言的形式固定下来--除非赞成这个协定中规定的有 ...

  9. java多线程编程核心技术——第二章

    第一节synchronized同步方法目录 1.1方法内的变量为线程安全的 1.2实例变量非线程安全 1.3多个对象多个锁 1.4synchronized方法与锁对象 1.5脏读 1.6synchro ...

随机推荐

  1. 第1章 HTML基础

    1.1 HTML概述 1.1.1 什么是HTML HTML(Hyper Text Markup Language,超 文本 标记 语言)是纯文本类型的语言,它是Internet上用于编写网页的主要语言 ...

  2. Python中@property和@classmethod和@staticmethod

    前戏 首先,先要弄清楚一个类里面的,各个组成部分都应该怎么称呼. - 注:可能叫法会不太一样. 关于@property 顾名思义:它的意思为‘属性’. 作用: 1:使用它你将会把类方法,变为类属性.并 ...

  3. java 二叉树递归遍历算法

    //递归中序遍历 public void inorder() { System.out.print("binaryTree递归中序遍历:"); inorderTraverseRec ...

  4. c++面试须知

    这些都是从zhihu上看到的. 指针,多态(虚函数表.内存layout),作用域,内存的管理 算法与数据结构,数据结构上由掌握哈希.优先级队列,算法上有字符串处理,简单的DFS.BFS.动态规划 系统 ...

  5. HDU3232 Crossing Rivers 数学期望问题

    Crossing Rivers                                                                                     ...

  6. ruby 发送邮件

    产品构建.打包.部署完需要发送邮件通知相关人员进行验证.请看过程 #encoding:utf-8 require 'mail' #~ branch = ARGV.to_s.sub('[','').su ...

  7. hihoCoder #1758 加减

    $\DeclareMathOperator{\lowbit}{lowbit}$ 题目大意 对于一个数 $x$,设它最低位的 1 是第 $i$ 位,则 $\lowbit(x)=2i$ . 例如 $\lo ...

  8. webstorm卡顿

    http://blog.csdn.net/qq673318522/article/details/50583831 http://www.xiaobai8.com/Blog/1000.html

  9. artTemplate模板引擎的不同使用方式

    arttemplate提供了两种不同的使用方式 一种是将模板写在页面内 <script id="test" type="text/html"> &l ...

  10. BZOJ【1606】购买干草

    1606: [Usaco2008 Dec]Hay For Sale 购买干草 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 859  Solved: 63 ...