Từ 1 tới 3 trên tổng số 3 kết quả

Đề tài: Hix! Lỗi nhỏ trong cách sử dụng thư viện string!

  1. #1
    Ngày gia nhập
    02 2012
    Bài viết
    0

    Mặc định Hix! Lỗi nhỏ trong cách sử dụng thư viện string!

    Các bạn giải thích hộ mình 2 cách sử dụng này:

    Cách 1: void DoiTen(char *a) { ten = a; } => KQ xuất chính xác
    Cách 2: void DoiTen(char *a) { strcpy(ten, a); } => xuất KQ sai

    Mình nghĩ 2 cách dùng này như nhau.... nhưng tại sao lại có sự khác nhau về KQ??? Giúp mình với nhé! Cảm ơn...

    Đây là full code của mình! (code này dùng theo cách 1)
    Code:
    #include<iostream.h>
    #include<conio.h>
    #include<iomanip.h>
    #include<string.h>
    
    char dummy;
    class SanPham
    {
          protected:
                  int leng;
                  char *ten;
                  unsigned long ma;
                  int nam;
          public:
                 SanPham() { ten = new char[leng]; }
                 SanPham(char *ten, unsigned long ma, int nam) { this->ten = ten; this->ma = ma; this->nam = nam; leng = strlen(ten); }
                 void Nhap()
                 {
                      char dummy;
                      cout<<"Nhap Ten san pham: "; cin.getline(ten, 20);
                      cout<<"Nhap Ma san pham - Nam san xuat: "; cin>>ma>>dummy>>nam; 
                 }
                 void Xuat() { cout<<ten<<setw(10)<<ma<<setw(10)<<nam; }
    };
    
    class TiVi:public SanPham
    {
          private:
                  int cdai;
                  int crong;
                  TiVi *next;
          public:
                 TiVi() { next = NULL; }
                 TiVi(char ten[20], unsigned long ma, int nam, int cdai, int crong):SanPham(ten, ma, nam)
                 { this-> cdai = cdai; this->crong = crong; }
                 TiVi* laynext() {return this->next; } 
                 void datnext(TiVi *M) { this->next = M; }
                 void Nhap() { SanPham::Nhap(); cout<<"Nhap chieu dai - chieu rong TiVi: "; cin>>cdai>>dummy>>crong; cin.ignore(1); }
                 void Xuat() { SanPham::Xuat(); cout<<setw(10)<<DienTich()<<endl; }
                 int operator>(TiVi *M) { if(this->DienTich() > M->DienTich()) return 1; else return 0; }
                 friend void Doi(TiVi *M, TiVi *N);
                 int DienTich() { return cdai*crong; }
    
                 unsigned long LayMa() {return ma; }
                 int LayNam() {return nam; }
                 char* LayTen() {return ten; }
                 void DoiTen(char *a) { ten = a; } // ???????????????????????????????????????????????
                 void DoiMa(unsigned long k) { ma = k; }
                 void DoiNam(int k) { nam = k; }
                 
    };
    TiVi *first, *last, *p;
    char c;
    
    void Nhap()
    {
         do{
               p = new TiVi;
               p->Nhap();
               if(first == NULL)
               {
                  first = p;
                  last = p;
               }
               else
               {
                   last->datnext(p);
                   last = p;
               }
               cout<<"Ban co muon tiep tuc khong (c/k)?";
               cout<<endl;
               c = getch();
         }while(c!='k');
    }
    void Doi(TiVi *M, TiVi *N)
    {
      
         int nam;
         nam = M->LayNam();
         M->DoiNam(N->LayNam());
         N->DoiNam(nam);
         unsigned long ma;
         ma = M->LayMa();
         M->DoiMa(N->LayMa());
         N->DoiMa(ma);
         char *ten;  
         ten = M->LayTen();   
         M->DoiTen(N->LayTen()); 
         N->DoiTen(ten);  
    }
    void SapXep()
    {
         TiVi *a, *b;
         a = first;
         b = NULL;
         while(a!=NULL)
         {
            b = a->laynext();
            while(b!=NULL)
            {
               if(*a>b)
                  Doi(a, b);
               b = b->laynext();
            }
            a = a->laynext();
         }
    }
    void HienThi()
    {
         TiVi *a;
         a = first;
         while(a!=NULL)
         {
            a->Xuat();
            a = a->laynext();
         }
    }
    main()
    {
          first = NULL;
          Nhap();
          SapXep();
          HienThi();
          getch();
    }

  2. #2
    Ngày gia nhập
    10 2011
    Bài viết
    552

    Sai là vì bạn ko nắm rõ được con trỏ char *ten đã được cấp vùng nhớ hay chưa ?
    Vài nó ra sai vì vùng nhớ của char *ten ko rõ ràng, ko khớp hoặc gì gì đấy với chuỗi a.
    Mình nghĩ 2 cách dùng này như nhau.... nhưng tại sao lại có sự khác nhau về KQ??? Giúp mình với nhé! Cảm ơn...
    Làm sao mà giống nhau được ?
    Bạn đang ở ngôi nhà có cái cửa màu xanh . Giờ ko thích nữa, thích cái cửa màu đỏ cơ. Bạn qua ở với ngôi nhà màu đỏ , quên ngôi nhà màu xanh đi
    Với chuyện khác là bạn cũng đi sắm 1 cái cửa màu đỏ như ngôi nhà kia, về lắp cho nhà bạn. Nó khác nhau chứ ?
    ____________________________
    Có nhiều cách để làm cho câu đó chạy được.
    Điển hình là cấp phát tĩnh thuộc tính char ten[50]; chẳng hạn.
    Thì bây giờ câu lệnh 2 sẽ thực hiện chính xác, còn câu lệnh 1 ...(thử đi rồi biết số phận ra sao).
    Từ đó => Khoanh vùng dc cốt lõi vấn đề. Và tự tùy biến cấp phát, khởi tạo vùng nhớ sao cho chúng dc chính xác.

    Và với cái cấp phát động mà dùng câu lệnh 1 như trên sẽ rất nguy hiểm, tạo mem leak (vứt rác mà không ai dọn).
    Cần sửa lại câu lệnh 1 cho AN TOÀN nếu muốn dùng nó
    void DoiTen(char * a){ delete ten; ten=a;}; để đốt rác trước khi làm gì thêm
    Nhưng mà nói chung cách móc rợ thế này cũng ko ổn. Nhỡ cái vùng nhớ a được vay mượn đó nó thay đổi 1 cái là hư cả dữ liệu hết.
    Đi ở nhờ nhà người ta thì ko hay bằng là tự ở nhà chính mình.
    Đã được chỉnh sửa lần cuối bởi clchicken : 21-02-2012 lúc 09:06 PM.
    Um Mani Padme Hum...!!

  3. #3
    Ngày gia nhập
    04 2010
    Bài viết
    1,534

    Trích dẫn Nguyên bản được gửi bởi nguyennhutbinh Xem bài viết
    Các bạn giải thích hộ mình 2 cách sử dụng này:

    Cách 1: void DoiTen(char *a) { ten = a; } => KQ xuất chính xác
    Cách 2: void DoiTen(char *a) { strcpy(ten, a); } => xuất KQ sai

    Mình nghĩ 2 cách dùng này như nhau.... nhưng tại sao lại có sự khác nhau về KQ??? Giúp mình với nhé! Cảm ơn...

    ...
    Hai cách không thể gọi là như nhau.
    Cách 1, copy trị của a vào ten, tức là chỉ con trỏ ten vào một chuỗi a, ten và a bây giờ cùng chỉ vào 1 chuỗi.
    Cách 2, copy những phần tử của chuỗi a vào chuỗi ten, nếu thành công (*) thì ten và a sẽ là hai chuỗi riêng biệt tuy có trị giống nhau.

    (*) Từ "nếu thành công" được đặt ra là vì ten chỉ là một con trỏ. Nếu nó chưa được cấp vùng nhớ thì hàm strcpy sẽ không thành công.

    tb. theo từ chuyên môn của C++, cách 1 là thuật chép cạn (shallow copy) và cách 2 là thuật chép sâu (deep copy)

Các đề tài tương tự

  1. Method String.CompareTo(string strB) trong C# thực hiện so sánh 2 chuỗi như thế nào?
    Gửi bởi tpqnnd trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 5
    Bài viết cuối: 27-05-2012, 10:52 AM
  2. Bài tập C++ tạo toán tử ==trong lớp string với tham số là string, char
    Gửi bởi truonglong99 trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 2
    Bài viết cuối: 24-10-2011, 08:56 AM
  3. Lập trình C++ sử dụng string trong C++. Lỗi C2146: syntax error : missing ';' before identifier tại string string_rep()const;?
    Gửi bởi levanvuonglvv trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 3
    Bài viết cuối: 15-09-2011, 10:28 PM
  4. So sánh string với String trong C#
    Gửi bởi qhhqnavy trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 12
    Bài viết cuối: 17-04-2011, 09:24 AM
  5. Tìm string trong string bằng C#?
    Gửi bởi ngocthangmediasoft trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 1
    Bài viết cuối: 20-03-2010, 07:54 PM

Quyền hạn của bạn

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