首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++编程思想-> 数据抽象 看不懂了

2012-02-17 
救命啊 C++编程思想- 数据抽象 看不懂了//: C04:CLib.h// Header file for a C-like library// An array-

救命啊 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语言可能也需要补补课。

就你提问的这两行看:

C/C++ code
//...提示:看看函数名叫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楼上的~!~
[解决办法]
C/C++ code
//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"); } 


[解决办法]
楼上注释太疯狂了……
[解决办法]

探讨
楼上注释太疯狂了……

热点排行