Trang 1 / 2 12 LastLast
Hiển thị kết quả từ 1 đến 10 / 15
  1. #1
    Tham gia
    16-07-2004
    Bài viết
    337
    Like
    0
    Thanked 0 Times in 0 Posts

    Tạo 1 lớp mới để lưu màng 1000 phần từ có size <1000/8 byte?

    Bài tập cụ thể là viết 1 lớp mới để lưu mảng bit với dung lượng bộ nhớ gần như số bit dc sử dụng và có thể dụng dc như sau :

    + ArrayBit b(1000);
    + dùng dc các biến từ b[0]->b[999]
    + có thể gán b[x]= 0 or 1

    Ví dụ tạo mảng 1000 phần tử.
    Ý tưởng của mình là :
    - Trong lớp đó sẽ cấp phát động 1 mảng có 1000/(sizeof(int)*8) phần tử .
    - Sau đó tạo cái operator[] như sau :
    Code:
    int operator[](int a)
    	{
    		return (p[a/sizeof(int*8)]>>(a%(sizeof(int)*8)) & 0x1);
    	}
    Vì tạo operator[] như vậy nên mình bị "bí" ở operator=
    Mình không thể truy xuất dc operator= vì a[x] ko phải là 1 đối tượng của ArrayBit .

    Có ai chỉ mình cách nào để operator[] có thể lưu giữ giá trị x của a[x] ko ?
    Hay có cách nào khác chỉ mình với !
    Quote Quote

  2. #2
    Tham gia
    02-02-2005
    Bài viết
    219
    Like
    0
    Thanked 3 Times in 3 Posts
    Đoạn này tớ dịch tốt chứ, có sao đâu.
    Code:
    class p
    {
    long a,b;
    long operator[](long arg) {return (a*b); }
    };

    Có thể, bạn dùng C DOS nên giới hạn tĩnh là 64k. Còn đây, 1MB trong Win32 quá nhỏ bé:
    Code:
    typedef unsigned long ar1000[1000];
    ar1000 ar_mot_trieu[1000];
    
    long i,j;
    for (i=0;i<1000;i++);
    for (j=0;j<1000;j++);
    ar_mot_trieu[i][j]  =  i*j;

  3. #3
    Tham gia
    03-01-2004
    Bài viết
    903
    Like
    0
    Thanked 11 Times in 7 Posts
    Thân gửi bạn edogawaconan,

    + ArrayBit b(1000);
    + dùng dc các biến từ b[0]->b[999]
    + có thể gán b[x]= 0 or 1

    int operator[](int a) {
    return (p[a/sizeof(int*8)]>>(a%(sizeof(int)*8)) & 0x1);
    }

    Vì tạo operator[] như vậy nên mình bị "bí" ở operator=
    Mình không thể truy xuất dc operator= vì a[x] ko phải là 1 đối tượng của ArrayBit.
    Tui nghĩ nếu bạn bị bí ở chỗ:

    ArrayBit b(1000);
    int k;
    .................
    k = b[0]; // viết như vậy thì làm được (gán bit đầu tiên vô k)
    // xài toán tử '=' bình thường; chớ không xài ArrayBit::operator= :
    b[0] = k; // viết như vậy thì không làm được (sẽ không gán được k vô bit đầu tiên)

    Tui nghĩ bạn phải làm: b.SetBit(bitNo, bitValue);
    thay cho b[bitNo] = bitValue;
    (trong trường hợp này: mình chỉ xài toán tử ArrayBit::[] ở vế phải chớ không xài ở vế trái được . Tui có thử đổi lại để xài được toán tử ArrayBit::[] ở vế trái; nhưng lại không xài được ở vế phải !)

    Post xong phần trên, đọc kỹ lại đề tui mới thấy đề bài yêu cầu:
    + dùng dc các biến từ b[0]->b[999] => xài được ở vế phải
    + có thể gán b[x]= 0 or 1 => xài được ở vế trái

    => để tui thử nghĩ tiếp coi sao

    (hiểu biết nông cạn; có gì sai sót mong được góp ý, xin cám ơn)

    -thân
    Được sửa bởi bete lúc 03:34 ngày 29-09-2007

  4. #4
    Tham gia
    03-01-2004
    Bài viết
    903
    Like
    0
    Thanked 11 Times in 7 Posts
    Thân gửi bạn edogawaconan,

    Tui đã thử như vầy:

    1) để viết được: a[bitNo] = bitValue
    thì mình cần:
    a) cho a[bitNo] trả về 1 đối tượng thuộc class ArrayBitElem. Đối tượng này phải cất giữ bitNo và a.p
    b) overload ArrayBitElem::operator= => nhận vô bitValue và thay đổi tại vị trí tương ứng ở bitNo

    2) để viết được: bitValue = a[bitNo]
    thì mình cần tạo 1 phương thức ép kiểu ArrayBitElem::operator int() => đổi từ kiểu ArrayBitElem về 1 giá trị kiểu int

    Tuy nhiên làm như vậy là để thỏa yêu cầu của đề bài mà thôi chớ chạy rất chậm vì mỗi lần truy xuất a[i] là phải tạo ra 1 đối tượng kiểu ArrayBitElem

    Muốn cho chạy nhanh thì nên tạo phương thức ArrayBit::SetBit và ArrayBit::GetBit
    Hoặc tạo ArrayBit::SetBit và overload ArrayBit::operator= (thay cho ArrayBit::GetBit)

    (hiểu biết nông cạn; có gì sai sót mong được góp ý, xin cám ơn)

    -thân

  5. #5
    Tham gia
    02-02-2005
    Bài viết
    219
    Like
    0
    Thanked 3 Times in 3 Posts
    đúng là OverLoad chỗ này hơi bí.
    Những bản chất bí là lưu đến từng bit, tớ thì tớ cứ lấy byte làm bit, tốn những đơn giản.

    Code:
    class p
    {
    public:
    p();
    char & operator[](long arg);
    char  a[64000];
    private:
    char b1,b2;
    }
    p::p(){int i; for (i=0; i<64000; i++)a[i]=0;}
    
    char & p::operator[](long arg)
    {
    return a[arg];
    }
    class p p1;
    void main()
    {
    long out;
    out= p1[2];
    p1[2]=1;
    out=p1[2];
    
    }

  6. #6
    Tham gia
    16-07-2004
    Bài viết
    337
    Like
    0
    Thanked 0 Times in 0 Posts
    Đây là cách giải bài này của bạn mình :
    Code:
    #include "iostream" 
    #include "conio.h" 
    using namespace std; 
    
    class BitArray{ 
    protected: 
       char *arr; 
       int size,         // kick thuoc 1 dvi dlieu trong arr. 
          n,            // so bit dang luu. 
          pos,         // vi tri trong arr dang xet. 
          index,         // vi tri bit dang xet trong arr[pos]. 
          tmp,         // place holder. 
          iErr;         // error code. 
    public: 
       int& operator[](int i){ 
           
          if(tmp)      arr[pos] |= (1<<index); 
          else      arr[pos] &=  (~(1<<index)); 
    
          if((i>=0) && (i<n)){ 
             pos = i/size; 
             index = i%size; 
             tmp = (arr[pos] >> index) & 1; 
             return tmp; 
          } 
          clog << "Wrong index! (i=" << i << ", n=" << n << ")\n"; 
          return iErr; 
       } 
       BitArray(int num){ 
          iErr = -1; 
          size = 8*sizeof(char); 
          n = num; 
          pos = index = tmp = 0; 
          int upperBound = n / size + (int)((n%size)?1:0); 
          arr = new char[upperBound]; 
          for(int i=0;i<upperBound;arr[i++]=0); 
       } 
       ~BitArray(){ 
          delete[] arr; 
       } 
    }; 
    
    void main(){ 
       BitArray a(10); 
       for(int i =0; i<10; cout << a[i++] << " "); 
       cout << endl; 
    
       a[5] = 1; 
       a[9] = -3;               // hay cai ji cung dc, khac 0 thi la 1. 
       cout << a[9] << endl; 
       cout << a[3] << endl; 
       cout << a[10] << endl;   // error!!! 
    
       for(int i =0; i<10; cout << a[i++] << " "); 
    
       _getch(); 
    }

  7. #7
    Tham gia
    03-01-2004
    Bài viết
    903
    Like
    0
    Thanked 11 Times in 7 Posts
    Thân gửi bạn edogawaconan,

    Cách giải này rất là hay. Độc đáo ở chỗ là nghĩ ra được chuyện làm trễ (delay) phép gán kiểu a[BitNo] = bitValue. Do đó không cần đặt thêm kiểu ArrayBitElem => chạy nhanh hơn; và chạy ngon lành với các toán tử kiểu '|=', '&=', '^=' (nếu làm kiểu thêm ArrayBitElem thì phải overload mấy toán tử này luôn)
    Tuy nhiên vì phép gán kiểu a[BitNo] = bitValue bị làm trễ cho nên trường hợp sau đây bị trục trặc:

    Code:
    void main(){
       BitArray a(10); 
       int *p = &(a[9]);
       a[9] = 1;
       a[5] = 0;
       cout << "a[9] = " << *p << endl;
    }
    => sẽ in ra "a[9] = 0" (sai) thay vì in ra "a[9] = 1" (đúng)

    Lý do là vì:
    a) "int *p = &(a[9])" => p trỏ tới a.tmp
    b) a.tmp luôn chứa vế bên phải của phép gán "a[BitNo] = bitValue" cuối cùng

    Nhưng phải nói là tui học được rất nhiều từ cách giải này => xin cám ơn nhiều lắm (ngưới nghĩ ra cách giải này thiệt là thông minh !!!)

    (hiểu biết nông cạn; có gì sai sót mong được góp ý, xin cám ơn)

    -thân

  8. #8
    Tham gia
    02-02-2005
    Bài viết
    219
    Like
    0
    Thanked 3 Times in 3 Posts
    Bài giải sai rồi.
    Đầu tiên,
    ------
    + ArrayBit b(1000);
    + dùng dc các biến từ b[0]->b[999]
    + có thể gán b[x]= 0 or 1
    ------

    nưng ở bài giải gán ngoài 01

    Điẻm sai quan trọng nhất, lần gán sau dùng tmp và pos của lần trước, update lần trước.



    như thế này có sao đâu
    Code:
    //---------------------------------------------------------------------------
    
    #include <conio.h>
    #include <stdio.h>
    #include <iostream.h>
    #pragma hdrstop
    
    //---------------------------------------------------------------------------
    
    #pragma argsused
    
    void main()
    {
       long  BitArray[100000];
       for(long i =0; i<100000; i++ ) BitArray[i]=0;
    
       BitArray[1]=1;
       BitArray[2]=0;
       BitArray[3]=0;
       BitArray[4]=0;
       BitArray[5]=1;
       BitArray[6]=1;
       cout << BitArray[1] << "\n";
       cout << BitArray[2] << "\n";
       cout << BitArray[3] << "\n";
       _getch();
    }
    Được sửa bởi huyphuc1981_nb lúc 15:41 ngày 29-09-2007

  9. #9
    Tham gia
    03-01-2004
    Bài viết
    903
    Like
    0
    Thanked 11 Times in 7 Posts
    Bài giải sai rồi. nhưng ở bài giải gán ngoài 0,1
    => đây chỉ là chuyện nhỏ (thêm 1 cái kiểm tra nhỏ nữa là được; kiểu như tác giả đã làm range checking)

    Cần thấy được ý tưởng làm trễ phép gán để thấy được tác giả đã giải quyết chỗ "bí" một cách rất độc đáo ra sao. Có thể nói tác giả đã nghĩ ra được 1 cách ít ai nghĩ tới. Đây là 1 điều rất tốt cho dân tin học (thường thì mình nghĩ theo 1 lối sáo mòn)

    -thân

  10. #10
    Tham gia
    19-11-2006
    Bài viết
    140
    Like
    0
    Thanked 1 Time in 1 Post
    Cho mình hỏi một chut được không, đọc đi đọc lại, mình vẫn không ý bài này muốn làm j, bạn có thể giải thích cho mình không. Hic, sorry tại mình dốt quá

Trang 1 / 2 12 LastLast

Bookmarks

Quy định

  • Bạn không thể tạo chủ đề mới
  • Bạn không thể trả lời bài viết
  • Bạn không thể gửi file đính kèm
  • Bạn không thể sửa bài viết của mình
  •