看着《C++编程思想》, 有点意思, 来欣赏一下其中的CStash程序(有略微的改动):
- #include <fstream>
- #include <iostream>
- #include <string>
- using namespace std;
-
- // element: 存储元素
- // cell : 存储空间(除了element之外, 可能还有没有利用、但是已经存在的cell空间)
-
- const int increment = 100; // 定义每次膨胀的cell的个数
-
- typedef struct CStashTag
- {
- int size; //一个cell的字节数
- int quantity; //cell的总数
- int next; //element的总数(也可以认为是下一个element的位置)
- unsigned char* storage; // 指向cell堆空间
- }CStash;
-
- void initiallize(CStash* s, int size);
- void cleanup(CStash* s);
- int add(CStash* s, const void* element);
- void* fetch(CStash* s, int index);
- int count(CStash* s);
- void inflate(CStash* s, int increase);
-
- // 初始化后, 就知道每个cell的大小了, 若element为int, 则一个cell的大小为4
- void initialize(CStash* s, int sz)
- {
- s->size = sz;
- s->quantity = 0;
- s->storage = NULL;
- s->next = 0;
- }
-
- int add(CStash* s, const void* element)
- {
- if(s->next >= s->quantity) // cell数目不足以容纳更多的element, 则需要膨胀
- {
- inflate(s, increment); // 每次膨胀100个cell
- }
-
- // 增加一个element, 需要这个element中的值拷贝到下一个cell空间
- int startBytes = s->next * s->size;
- unsigned char* e = (unsigned char*)element;
- for(int i = 0; i < s->size; i++) //逐个字节拷贝
- {
- s->storage[startBytes + i] = e[i];
- }
-
- s->next++; // element数目自增
-
- return(s->next - 1); //最后一个element的下标
- }
-
- void* fetch(CStash* s,int index)
- {
- if (index >= s->next)
- {
- return NULL;
- }
-
- // 返回index所对应的地址
- return &(s->storage[index * s->size]);
- }
-
- int count(CStash* s)
- {
- return s->next; //element的个数(也可以认为是下一个element的位置)
- }
-
- void inflate(CStash* s, int increase)
- {
- int newQuantity = s->quantity + increase; // 膨胀后的cell的总数
- int newBytes = newQuantity * s->size; // 原来cell的总空间
- int oldBytes = s->quantity * s->size; // 膨胀后cell的总空间
-
- unsigned char* b = new unsigned char[newBytes];
- for(int i = 0; i < oldBytes; i++)
- {
- b[i] = s->storage[i]; //将旧内容复制到新的空间中, 也是逐字节复制
- }
-
- delete [](s->storage);//删除旧的存储空间
-
- s->storage = b; //指向新的堆空间
- s->quantity = newQuantity; // 膨胀后的cell的总数
- }
-
- void cleanup(CStash* s)
- {
- // 我有一点点纳闷, 为什么其他的参数不清零, 而只进行下面的堆空间释放呢?
-
- if(NULL != s->storage)
- {
- cout << "freeing storage" << endl;
- delete []s->storage;
- }
- }
-
-
- int main()
- {
-
- CStash intStash,stringStash;
- int i = 0;
-
- // 初始化int对应的cell
- initialize(&intStash, sizeof(int));
-
- // 申请cell, 并将element写入cell
- for(i = 0; i < 10; i++)
- {
- add(&intStash, &i);
- }
-
- // 打印cell空间中的element
- for(i = 0; i < count(&intStash); i++)
- {
- cout << *(int*)fetch(&intStash, i) << endl;
- }
-
-
- // 如下代码功能类似上面, 所以我就不注释了
-
-
- ifstream in;
- string line;
- const int bufsize = 80;
- in.open("main.cpp");
-
- initialize(&stringStash, sizeof(char) * bufsize);
- while(getline(in, line))
- {
- add(&stringStash, line.c_str());
- }
-
- i = 0;
- char* cp = NULL;
- while(NULL != (cp = (char*)fetch(&stringStash, i++)))
- {
- cout << cp << endl;
- }
-
- cleanup(&intStash);
- cleanup(&stringStash);
-
- return 0;
- }
程序的结果为:
0
1
2
3
4
5
6
7
8
9
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
// element: 存储元素
// cell : 存储空间(除了element之外, 可能还有没有利用、但是已经存在的cell空间
const int increment = 100; // 定义每次膨胀的cell的个数
typedef struct CStashTag
{
int size; //一个cell的字节数
int quantity; //cell的总数
int next; //element的总数(也可以认为是下一个element的位置)
unsigned char* storage; // 指向cell堆空间
}CStash;
void initiallize(CStash* s, int size);
void cleanup(CStash* s);
int add(CStash* s, const void* element);
void* fetch(CStash* s, int index);
int count(CStash* s);
void inflate(CStash* s, int increase);
// 初始化后, 就知道每个cell的大小了, 若element为int, 则一个cell的大小为4
void initialize(CStash* s, int sz)
{
s->size = sz;
s->quantity = 0;
s->storage = NULL;
s->next = 0;
}
int add(CStash* s, const void* element)
{
if(s->next >= s->quantity) // cell数目不足以容纳更多的element, 则需要膨胀
{
inflate(s, increment); // 每次膨胀100个cell
}
// 增加一个element, 需要这个element中的值拷贝到下一个cell空间
int startBytes = s->next * s->size;
unsigned char* e = (unsigned char*)element;
for(int i = 0; i < s->size; i++) //逐个字节拷贝
{
s->storage[startBytes + i] = e[i];
}
s->next++; // element数目自增
return(s->next - 1); //最后一个element的下标
}
void* fetch(CStash* s,int index)
{
if (index >= s->next)
{
return NULL;
}
// 返回index所对应的地址
return &(s->storage[index * s->size]);
}
int count(CStash* s)
{
return s->next; //element的个数(也可以认为是下一个element的位置)
}
void inflate(CStash* s, int increase)
{
int newQuantity = s->quantity + increase; // 膨胀后的cell的总数
int newBytes = newQuantity * s->size; // 原来cell的总空间
int oldBytes = s->quantity * s->size; // 膨胀后cell的总空间
unsigned char* b = new unsigned char[newBytes];
for(int i = 0; i < oldBytes; i++)
{
b[i] = s->storage[i]; //将旧内容复制到新的空间中, 也是逐字节复制
}
delete [](s->storage);//删除旧的存储空间
s->storage = b; //指向新的堆空间
s->quantity = newQuantity; // 膨胀后的cell的总数
}
void cleanup(CStash* s)
{
// 我有一点点纳闷, 为什么其他的参数不清零, 而只进行下面的堆空间释放呢?
if(NULL != s->storage)
{
cout << "freeing storage" << endl;
delete []s->storage;
}
}
int main()
{
CStash intStash,stringStash;
int i = 0;
// 初始化int对应的cell
initialize(&intStash, sizeof(int));
// 申请cell, 并将element写入cell
for(i = 0; i < 10; i++)
{
add(&intStash, &i);
}
// 打印cell空间中的element
for(i = 0; i < count(&intStash); i++)
{
cout << *(int*)fetch(&intStash, i) << endl;
}
// 如下代码功能类似上面, 所以我就不注释了
ifstream in;
string line;
const int bufsize = 80;
in.open("main.cpp");
initialize(&stringStash, sizeof(char) * bufsize);
while(getline(in, line))
{
add(&stringStash, line.c_str());
}
i = 0;
char* cp = NULL;
while(NULL != (cp = (char*)fetch(&stringStash, i++)))
{
cout << cp << endl;
}
cleanup(&intStash);
cleanup(&stringStash);
return 0;
}
freeing storage
freeing storage
其实, 从上面可以看到, CStash结构体显得有点多余, 直接用size, quantity, storage, next也是可以的。 之所以还要用结构体, 完全是为了整体性, 让有点关系的size, quantity, storage, next成为一个有机体, 便于理解, 便于编程, 便于维护, 这就是结构体的最大作用吧