救命啊 C++编程思想-> 数据抽象 看不懂了
//: C04:CLib.h
// Header file for a C-like library
// An array-like entity created at runtime
typedef struct CStashTag {
int size; // Size of each space
int quantity; // Number of storage spaces
int next; // Next empty space
// Dynamically allocated array of bytes:
unsigned char* storage;
} CStash;
void initialize(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);
///:~
//: C04:CLib.cpp {O}
// Implementation of example C-like library
// Declare structure and functions:
#include "CLib.h"
#include <iostream>
#include <cassert>
using namespace std;
// Quantity of elements to add
// when increasing storage:
const int increment = 100;
void initialize(CStash* s, int sz) {
s->size = sz;
s->quantity = 0;
s->storage = 0;
s->next = 0;
int add(CStash* s, const void* element) {
if(s->next >= s->quantity) //Enough space left?
inflate(s, increment);
// Copy element into storage,
// starting at next empty space:
int startBytes = s->next * s->size; 这个startBytes是指整个STRUCT类的大小吗?
unsigned char* e = (unsigned char*)element; 这里的指针E和element的地址不是垃圾值?
for(int i = 0; i < s->size; i++)
s->storage[startBytes + i] = e[i];//这个e[i]数组也是垃圾值啊??? 那赋值过去又有什么用呢?
s->next++;
return(s->next - 1); // Index number
}
void* fetch(CStash* s, int index) {
// Check index boundaries:
assert(0 <= index);
if(index >= s->next)
return 0; // To indicate the end
// Produce pointer to desired element:
return &(s->storage[index * s->size]);
}
int count(CStash* s) {
return s->next; // Elements in CStash
}
void inflate(CStash* s, int increase) {
assert(increase > 0);
int newQuantity = s->quantity + increase;
int newBytes = newQuantity * s->size;
int oldBytes = s->quantity * s->size;
unsigned char* b = new unsigned char[newBytes];
for(int i = 0; i < oldBytes; i++)
b[i] = s->storage[i]; // Copy old to new
delete [](s->storage); // Old storage
s->storage = b; // Point to new memory
s->quantity = newQuantity;
}
void cleanup(CStash* s) {
if(s->storage != 0) {
cout << "freeing storage" << endl;
delete []s->storage;
}
} ///:~
//: C04:CLibTest.cpp
//{L} CLib
// Test the C-like library
#include "CLib.h"
#include <fstream>
#include <iostream>
#include <string>
#include <cassert>
using namespace std;
int main() {
// Define variables at the beginning
// of the block, as in C:
CStash intStash, stringStash;
int i;
char* cp;
ifstream in;
string line;
const int bufsize = 80;
// Now remember to initialize the variables:
initialize(&intStash, sizeof(int));
for(i = 0; i < 100; i++)
add(&intStash, &i);
for(i = 0; i < count(&intStash); i++)
cout << "fetch(&intStash, " << i << ") = "
<< *(int*)fetch(&intStash, i)
<< endl;
// Holds 80-character strings:
initialize(&stringStash, sizeof(char)*bufsize);
in.open("CLibTest.cpp");
assert(in);
while(getline(in, line))
add(&stringStash, line.c_str());
i = 0;
while((cp = (char*)fetch(&stringStash,i++))!=0)
cout << "fetch(&stringStash, " << i << ") = "
<< cp << endl;
cleanup(&intStash);
cleanup(&stringStash);
} ///:~
[解决办法]
int startBytes = s->next * s->size; 这个startBytes是指整个STRUCT类的大小吗?
计算当前应该插入的元素的起始地址
unsigned char* e = (unsigned char*)element; 这里的指针E和element的地址不是垃圾值?
element是形参,是你传进来的,垃不垃圾显然由你负责,此处只是做了一个指针类型转换而已 void* --> unsigned char* 不会改变其指向的内容
[解决办法]
为啥大家都先看Thinking in C++...
那是思想性很强的书,不是教科书……
建议先去看看《C++ Primer》,而且估计楼主C语言可能也需要补补课。
就你提问的这两行看:
//...提示:看看函数名叫add,说明这个函数的目的是要把element里的数据加到s后面。而且后面也有注释// Copy element into storage, // starting at next empty space:// 仔细想想这段代码就不难理解了。 int startBytes = s->next * s->size; //这个是你当前的用到内存的大小,也就是说如果你有新内容输入就要写在后面,看看后面的for循环 //里面s->storage[startBytes + i]也就是你新的内容插入的位置。 unsigned char* e = (unsigned char*)element; //好了,这个就是要插入的数据了!!看看输入的数据类型叫什么?“void*”对吧?后面for循环里 //要把void *指向的值复制到一个unsigned char数组里,类型不匹配啊?!所以要做指针类型的转换 //这样做还有一个目的后面的循环里e[i]要每次跳过一个和你unsigned char一样大数据类型。编译器 //不知道应该跳多远,只有告诉他“我每次要一个unsigned char这么长的距离”他才会明白。 for(int i = 0; i < s->size; i++) s->storage[startBytes + i] = e[i];//看看上面的注释:)//...
[解决办法]
UP楼上的~!~
[解决办法]
//Quantity of elements to add// when increasing storage:const int increment=100; void initialize(CStash* s,int sz) //初始化函数,接受一个CStash结构体指针{ //以及存放的数据的字节长度 s->size=sz; //这个长度应该是固定的 s->quantity=0; //比如,如果你要在CStash里放int,那么就应该是sizeof(int) s->storage=0; //这样也确保了你能够从storage[里提取到正确的数据 s->next=0; //next是目前有已加入多少元素} //quantity是目前能够存放多少元素,一旦next超过quantity就要执行 //inflate( ) 用于扩充storage int add(CStash* s,const void* element) //为CStash结构体对象添加新元素(数据) { if(s->next >= s->quantity)//Enough space left? 前面说过,判断目前的storage[是否够用,不够用就inflate( )扩充 inflate(s,increment); //increment代表扩充多少数量 //Copy element into storage, // starting at next empty space: int startBytes=s->next * s->size; //用next * size就可以得出在storage数组中第一个没有被用到的字节的位置(偏移量) unsigned char* e=(unsigned char*)element; //将element转换成为unsigned char型,因为storage[也是unsigned char型的 //当然了storage 如果是char型也没有关系 for (int i=0;i <s->size;i++) //将element一个字节一个字节拷贝到storage[里去 s->storage[starBytes +i]=e[i]; //但是不会覆盖目前storage 目前的数据,因为前面已得出了startBytes s->next++; //增加了一个元素就要将next自增 return (s->next-1);//Index number //返回当前被加入的元素的索引位置,因为next表示的是目前已加入多少元素,是从1开始的} //而索引号是从0开始的,所以要 next - 1void* fetch(CStash* s,int index) //根据索引号index从一个CStash对象中提取元素{ //Check index boundaries: assert(0 <=index); //首先断言index是大于等于0的,因为索引号如果是负数的话是非法的,一旦索引号是负数,程序就会终止并退出 if(index >=s->next) //再判断索引号是否大于等于next,如果大于等于就说明你正在试图获取一个不存在的元素 return 0;//To indicate the end //Produce pointer to desired element: return &(s->storage[index * s->size]);//返回的是storage 里面偏移量,也就是位置 //记住,因为你存放的东西可能不是1字节大小的,所以不可以直接用Index获取storage[里的数据} //而是要乘以size(前面说过的,代表你存放在里面的数据的大小)int count(CStash* s) //这里返回你目前CStash对象里有多少个元素被存放了{ return s->next; //Elements in increase);}void inflate(CStash* s, int increase) //为storage扩容的函数{ assert(increase >0); //既然是扩容index就必须>0,否则就是非法的 int newQuantity=s->quantity+increase; //newQuantity代表扩容后应该能够存放多少个东西 int newBytes =newQuantity * s->size; //newBytes代表扩容后storage[应有的大小 int oldBytes =s->quantity * s->size; //oldBytes代表原来storage[的大小 unsigned char* b=new unsigned char[newBytes]; //new 申请新的内存空间,大小是newBytes for (int i=0;i <oldBytes;i++) b[i]=s->storage[i];//Copy old new memory 将原来storage[的数据统统copy到一个新的内存空间中去 delete []s->storage; //将旧空间释放掉 s->storage=b; //Point to new memory //storage指向新的内存空间 s->quantity=newQuantity; //既然storage扩容了,那么也要相应的更新quantity}void cleanup(CStash* s) //清除程序{ if (s->storage !=0) //首先判断storage是否等于0,如果等于0就不用释放了 { cout < <"freeing storage" < <endl; delete[]s->storage; //释放storage的内存 } system("pause"); }
[解决办法]
楼上注释太疯狂了……
[解决办法]