Trang 4 / 8 FirstFirst 1234567 ... LastLast
Hiển thị kết quả từ 31 đến 40 / 77
  1. #31
    Tham gia
    11-07-2007
    Bài viết
    74
    Like
    0
    Thanked 0 Times in 0 Posts
    hix,...lên diễn đàn đã để là câu hỏi nhỏ mà mấy bác xé nó ra lớn quá ah`...hiccc...
    ..Em làm lại rồi,chạy rồi nhưng vẫn post lên cho các bro xem...có j` chỉ bảo em nha.Mới vào học thôi...cần chỉ dạy nh` mới đạt đến tầm cỡ như các bro đc..
    #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    void main()
    {
    char ho_ten[50];
    clrscr();
    long luong;
    int tuoi;
    strcpy (ho_ten,"nguyen hinh hieu");
    luong=100000;
    tuoi=18;
    printf("\nho_ten %s",ho_ten);
    printf("\nluong%ld",luong);
    printf("\ntuoi%d",tuoi);
    getch();
    }

    Xem cho em nha

  2. #32
    Tham gia
    12-02-2007
    Location
    HCM - NT
    Bài viết
    218
    Like
    0
    Thanked 1 Time in 1 Post
    Ngày trước khi tiếp xúc với C với môi trường lập trình BC3.1, tôi cũng có một thời gian xài char* kiểu này. Đến khi làm một project cuối kỳ tôi mới phát hiện lỗi và ký tự xuất ra không còn chính xác, có lẽ lỗi này chỉ ở BC3.1 và từ đó trở đi tôi bao giờ xài và gán trược tiếp char*. Nếu các bạn được học đúng cơ bản trên nền BC3.1 trở đi, chắc hẳn bạn sẽ được nhắc điều này.

    Trình biên dịch VC đã khắc phục điều này bằng const char và tôi không biết điều này! Xin lỗi. Cám ơn một số bạn đã nhắc nhỏ.

    Còn chuyện huy phúc chửi tôi chắc cũng vì công thành riêng tư thôi. Cậu ta vốn chẳng ưa gì tôi mà! Tôi cũng chả chấp.

  3. #33
    Tham gia
    04-10-2007
    Bài viết
    138
    Like
    0
    Thanked 0 Times in 0 Posts
    Chả có cái gì không chính xác cả. Có chú dùng không đúng thôi.
    Thứ duy nhất không chính xác là chú.


    Quote Được gửi bởi eXecutive View Post
    Ngày trước khi tiếp xúc với C với môi trường lập trình BC3.1, tôi cũng có một thời gian xài char* kiểu này. Đến khi làm một project cuối kỳ tôi mới phát hiện lỗi và ký tự xuất ra không còn chính xác, có lẽ lỗi này chỉ ở BC3.1 và từ đó trở đi tôi bao giờ xài và gán trược tiếp char*. Nếu các bạn được học đúng cơ bản trên nền BC3.1 trở đi, chắc hẳn bạn sẽ được nhắc điều này.

    Trình biên dịch VC đã khắc phục điều này bằng const char và tôi không biết điều này! Xin lỗi. Cám ơn một số bạn đã nhắc nhỏ.

    Còn chuyện huy phúc chửi tôi chắc cũng vì công thành riêng tư thôi. Cậu ta vốn chẳng ưa gì tôi mà! Tôi cũng chả chấp.

  4. #34
    Tham gia
    04-10-2007
    Bài viết
    138
    Like
    0
    Thanked 0 Times in 0 Posts
    Quote Được gửi bởi zZzPC-NODzZz View Post
    hix,...lên diễn đàn đã để là câu hỏi nhỏ mà mấy bác xé nó ra lớn quá ah`...hiccc...
    ..Em làm lại rồi,chạy rồi nhưng vẫn post lên cho các bro xem...có j` chỉ bảo em nha.Mới vào học thôi...cần chỉ dạy nh` mới đạt đến tầm cỡ như các bro đc..
    #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    void main()
    {
    char ho_ten[50];
    clrscr();
    long luong;
    int tuoi;
    strcpy (ho_ten,"nguyen hinh hieu");
    luong=100000;
    tuoi=18;
    printf("\nho_ten %s",ho_ten);
    printf("\nluong%ld",luong);
    printf("\ntuoi%d",tuoi);
    getch();
    }

    Xem cho em nha


    Đoạn của bạn thì đúng, bạn lập trình giỏi hơn cu teo rồi đấy, nhưng in ra thế này.
    Code:
    ho_ten nguyen hinh hieu
    luong100000
    tuoi18

  5. #35
    Tham gia
    05-09-2007
    Location
    HCMC
    Bài viết
    106
    Like
    0
    Thanked 5 Times in 2 Posts
    @zZzPC-NODzZz bạn làm vậy cũng được nhưng không kiểm tra dữ liệu (ví dụ tên quá dài ký tự) thì sẽ có thể phát sinh lỗi. Còn chuyện này thì bé thật nhưng không nắm vững thì sẽ không ổn đâu. Nếu bạn mới bắt tay vào lập trình thì cần nắm vững vấn đề này không nên để đến khi học cái này cái khác mới phát hiện ra là mình không hiểu gì.

    Để phân tích đoạn này:

    Quote Được gửi bởi eXecutive View Post
    Tôi xin sửa lại!
    Code:
    char *a = "abasd";
    hay 
    char *a;
    a = "adaskjdaskdj";
    TẤT CẢ ĐỀU SAI!!!

    Tôi sẽ phân tích cái lỗi này cho các bạn xem! Bởi vì nó không xuất hiện ngay lập tức mà phải một thời gian sử dụng bộ nhớ nó mới xuất hiện. Ở Visual C rất khó thấy cái này vì nó hỗ trợ bộ nhớ tới stack 4MB, nhưng với Borland C 3.1 thì rõ ràng vì nó là ứng dụng 16 bit nên chỉ có 64Kb.

    Tại sao sai???
    char *p;
    Nó chỉ là một con trỏ và trỏ đại một ví trị bất kỳ nào đó.
    Bạn khai báo:
    a = "abcd";
    Không vấn đề gì vì bộ nhớ đang trống rất nhiều.
    Nhưng đến một lúc nào đó thì sẽ xuất hiện trường hợp "rác" trong chuỗi ký tự, ví dụ như nó sẽ là:
    cout << a; -> "abcd@!*#&AKDHasjdhyqwue"
    Bởi vì không ai xác nhận vùng nhớ mà ta gán "abcd" là vùng nhớ đã cấp phát! Sau nhiều lần gán thì nó sẽ bị chồng chép lên nhau!

    Tuy nhiên khi ta khai báo.
    -> char str[] = "HELLO ABCDEF";
    Đây mới là cách khai báo đúng mà tôi nhầm;
    Mặc định nó sẽ là strlen("HELLO ABCDEF") byte được cấp phát và không có ai can thiệp bộ nhớ của nó.

    Test 1 cái đơn giản:
    char *a = "cong hoa xa hoi";
    strcpy(a,"abcd"); // Lỗi ngay lập tức khi chạy.

    char a[] = "cong hoa xa hoi"
    strcpy(a,"data"); // Không lõi!

    Tôi đã từng bị lỗi này rồi nên tôi nhớ. Sử dụng con trỏ không cấp phát là điều kiên kỵ nhất của C/C++. Do đó luôn xác định trước kích thước của nó khi sử dụng!
    Tôi nói ra không vừa ý thì thôi! Đừng chửi ngu vì hãy xem lại mình.

    Phần 1:
    char *a = "cong hoa xa hoi";
    Bạn có thể xem như sau:
    a trỏ đến 1 vùng nhớ bad allocate, tui dùng VC6 nên thường sẽ là 0xCCCCCCCC. Trong khi đó "cong hoa xa hoi" là một string literal đã có rồi nó địa chỉ bắt đầu là 0x0042F038 (chỉ là ví dụ thôi dùng debug để xem). Câu lệnh trên chỉ là gán nội dung con trỏ a để a trỏ tới vùng nhớ đó (không đụng chạm gì đến nội dung của vùng nhớ). Nhưng literal string "cong hoa xa hoi" được đại diện là 1 const char *, có nghĩa là con trỏ char * tới 1 vùng nhớ const, bạn không có quyền thay đổi nội dung vùng nhớ này. Câu lệnh thứ 2 strcpy sai là hiển nhiên.

    Vào debug memory window (alt+6) sẽ thấy "cong hoa xa hoi" tại địa chỉ
    0042F038 63 6F 6E 67 20 68 6F 61 20 78 61 20 68 6F 69 00 00 00 00 00 70 08 43 00 cong hoa xa hoi.....p.C.

    Phần thứ 2:
    char a[] = "cong hoa xa hoi"
    strcpy(a,"data"); // Không lõi!

    a sẽ được cấp phát một vùng nhớ tại địa chỉ 0x0012FF70 có nghĩa là không bad allocate và chiều dài vừa đủ chứa chuỗi "cong hoa xa hoi".
    0012FF70 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC C0 FF 12 00 49 9C 40 00 フフフフフフフフフフフフフフフフ ..I廖.
    Còn chuỗi "cong hoa xa hoi" đang ở đâu. Nó ở đâu đó, với phần chạy thử ở trên và chương trình tui chỉ sửa lại char *a thành char a[] thì tui biết là nó cũng ở vị trí cũ tức 0x0042F038.
    0042F038 63 6F 6E 67 20 68 6F 61 20 78 61 20 68 6F 69 00 00 00 00 00 70 08 43 00 cong hoa xa hoi.....p.C.
    Sau câu khai báo này thì a vẫn trỏ tới 0x0012FF70 nhưng nội dung 0x0012FF70 là "cong hoa xa hoi". Tất nhiên vùng này không phải là const nên có thể thay đổi.

    @thanggia bạn viết cái câu while(true) đó không thể làm cho những người chưa biết gì hiểu được, đâu có gì được cấp phát mới đâu mà giới hạn 64K hay không, đây chỉ là gán ho_ten đến đúng địa chỉ cũ.

    Không cần nói nhiều vì nếu thực sự biết rõ thì phải hiểu chứ không phải viết kiểu 'Tôi đã từng bị lỗi này rồi nên tôi nhớ' mà không biết vì sao lỗi rồi thòng thêm vài câu rất chân lý 'Sử dụng con trỏ không cấp phát là điều kiên kỵ nhất của C/C++. Do đó luôn xác định trước kích thước của nó khi sử dụng!'

    Cái phát biểu char a[] = "cong hoa xa hoi" mới đúng là cách cấp phát làm cho khó xác định kích thước được cấp phát của a.

  6. #36
    Tham gia
    04-10-2007
    Bài viết
    138
    Like
    0
    Thanked 0 Times in 0 Posts
    Con trỏ là phương pháp sử dụng bộ nhỡ dĩ nhiên phải cần. Ngôn ngữ napf cũng có khái niệm con trỏ. Tuy vậy, con trỏ của Pascal trong sáng hơn, dễ hơn nhiều.

    Con trỏ C thì do truyền thống, có một số cách viết tắt hay dùng lẫn. Nhưng làm việc với con trở luôn phải ý thức được nó, chứ không phải luôn cấp phát. Việc cấp phát chỉ con trỏ cụ thể, nó làm hạn chế sự linh động của con trỏ. Ở đây, tôi trình bầy về cái ngu ngốc của những kẻ hoàn toàn không hiểu bài học đầu tiên cho Beginer.

    char * a; //dòng 1
    a= new char[100]; //dòng 2
    strcpy (a,"xyzt"); //dòng 3
    printf(a); //dòng 4


    Việc cần làm là in chuối xyzt ra. Nhưng đoạn trên ngu ngốc ở chỗ, không copy xyzt ra màn hình. Người lập trình copy dữ liệu đó vào một vùng trung gian (được cấp ở dòng 2) rồi mới in ra. Lỗi sẽ sảy ra khi không gian được cấp nhỏ hơn biến copy. Điều này hết sức dễ xảy ra khi xyzt không phải là hằng, mà là biến.

    đoạn trên, có thể "dịch" sơ bộ như say, kt là không tên:

    char * a; //dòng 1
    a= new char[100]; //dòng 2
    char[5] kt;
    kt <- "xyzt"#0;
    strcpy (a,kt); //dòng 3
    printf(a); //dòng 4
    -----------------

    còn
    char * a="abcd";

    được dịch thành
    char[5] kta; //cấp phát một vùng nhớ, chạy lúc dịch. Vùng nhớ bằng chiều dài chuỗi +1
    kta="abcd"#0 //gán giá trị chuỗi vào đó, chạy lúc dịch. Chuỗi được thêm số 0 cuối (Null string).
    a=addr(kta); //gán giá trị địa chỉ chuỗi vào biến con trỏ a, chạy lúc dịch và được tái định vị khi load

    trong đó, kta là cái kiểu mà C++ thiếu, sau này mới được bỏ sung trong C#. Nó là cái mà con trỏ trỏ đến. Đoạn trên hianf toàn hợp lệ và an toàn, chương trình dịch tự động cấp phát một vùng nớ dài length (kta)+1 và thêm số không vào cuối chương trình.

    Vậy nên
    char *a ="abcd";
    printf("\n%s\n",a)
    luôn luôn chạy đúng. Ở đây, cấp phát vùng nhớ cho a là ngu ngốc.

    nhưng sau đây sai.
    char *a = "abcd";
    strcpy (a,"xyzt") //copy dữ liệu vào hằng.
    Việc copy này sẽ sinh lỗi như thế nào mình đã nói rồi.

    Việc cấp phát vùng nhỡ ngu ngốc thế nào mình cũng đã nói trang trước.

    char * a;
    a= new char[10]; //dự định buffer in ra. Lỗi phát sinh khi tràn buffer, đây là lỗi lúc chạy.
    strcpy(a,"0123456789a"); //lỗi.

  7. #37
    Tham gia
    04-10-2007
    Bài viết
    138
    Like
    0
    Thanked 0 Times in 0 Posts
    Đây là ví dụ mình đã nói. Ghi vào Hằng. Mình đã nói, chuyện này đặc biệt nghiêm trọng với class.
    Nếu may mắn chạy được, c2.ch1 chưa bị gán đã bị đổi.

    Những diễn biến này hoàn toàn đúng luật và rõ ràng. Chỉ có điều, cu teo éo bít sai ở đâu, rồi đổ cho C không chính xác.

    Code:
    //---------------------------------------------------------------------------
    
    #pragma hdrstop
    #include<stdio.h>
    #include<conio.h>
    #include<string.h>
    #include"iostream.h"
    class ch
    {
    public:
    ch()
    {
    cout << "init ch class";
    ch1="abcdefghijklmn"; //gán vào địa chỉ hằng dùng chung
    ch2="12345678901234";
    }
    ~ch()
    {
    cout << "destroy ch class";
    }
    
    in()
    {
    char *temp;
    temp=ch1; printf("\n ch1 :\n");printf("\n%s\n",temp);
    temp=ch2;
    printf("\n ch2 :\n");printf("\n%s\n",temp);
    temp=ch1; //gán biến temp vào địa chỉ hằng dùng chung
    strcpy(temp,"xyzt"); //hằng dùng chung bị đổi. strcpy không làm thay đổi giá trị con 
    //trỏ, nó chỉ lamd thay đổi giá trị con trỏ trỏ đến. Con trỏ trỏ đến của temp là 
    //hằng dùng chung. Tất cả các instance của class đều bị ảnh hưởng.
    printf("\n ch1 strcpy :\n");printf("\n%s\n",temp);
    getch();
    }
    private:
    char *ch1,*ch2;
    };
    
    void main()
    {
    class ch c1,c2;
    c1.in();
    printf("\nbat dau in c2\n");
    getch();
    c2.in(); //chưa gán đã đổi.
    }
    //---------------------------------------------------------------------------

    Kết quả đây:
    Code:
    init ch classinit ch class // init class
     ch1 :
    
    abcdefghijklmn //c1.ch1 chưa thay đổi được in ra
    
     ch2 :
    
    12345678901234  //c1.ch2 được in ra
    
     ch1 strcpy :
    
    xyzt  //c1.ch1 đã thay đổi được in ra
    
    bat dau in c2
    
     ch1 :
    
    xyzt // c2.ch1 chưa thay đổi nhưng đã chết. Do hằng "abc..." đã bị đổi khi c1.in() chạy. Việc đổi này 
    //tác động đến toàn bộ các Instance, vậy nên nhiều chương trình dịch tống hằng dùng 
    //chung vào CS để báo lỗi protection.
    
     ch2 :
    
    12345678901234
    
     ch1 strcpy :
    
    xyzt
    Được sửa bởi thanggia lúc 02:20 ngày 08-10-2007

  8. #38
    Tham gia
    18-08-2005
    Location
    Montclair
    Bài viết
    8,722
    Like
    20
    Thanked 1,457 Times in 600 Posts
    Cũng may đây chỉ là "Một câu hỏi nhỏ về type Char".

  9. #39
    Tham gia
    04-10-2007
    Bài viết
    138
    Like
    0
    Thanked 0 Times in 0 Posts
    cái post edit này sao hay điên thế nhẩy.
    Được sửa bởi thanggia lúc 10:36 ngày 08-10-2007

  10. #40
    Tham gia
    04-10-2007
    Bài viết
    138
    Like
    0
    Thanked 0 Times in 0 Posts
    Quote Được gửi bởi The Old Man View Post
    Cũng may đây chỉ là "Một câu hỏi nhỏ về type Char".
    Ừa.
    Một cái nhỏ về char. Thế mà cu teo không vượt qua được. Một hòn gạch không có, nhưng cu teo và mạ con làm nhiều nhiều chương trình danh tiếng lớn lao.

    Thật ra, ở C++ có nhiều điểm viết tắt và dùng theo truyền thống, hơi sai logic. Đó là hiện tượng trong ngôn ngữ. Giống như cô giáo thì gọi cô xưng cháu, bà ngoại gọi bà xưng con. Ngôn ngữ Pascal tuy hết sức chặt chẽ những bắt buộc phải có cái .... truyền thống.
    Ví dụ
    Code:
    type
    con_tro_kieu_1= ^kieu_1; //dòng này "láo theo truyền thống thành đúng", tham chiếu kieu_1 chưa định nghĩa.
    kieu_1= record
    .. định nghĩa kiểu 1...
    end;
    Nhưng ở Pascal, chỉ có chỗ đó là láo đáng kể. C++ thì nhiều vô kể.
    Ví dụ

    const char *const_char_1="1234567890";
    theo đúng ngữ pháp, thì cái biến con trỏ const_char_1 mới là const. Nhưng vì thói quyen của C++, chương trình dịch cho "1234567890" (không có tên), là hằng. Điều này thì là dĩ nhiên (chả cần thế nó vẫn là hằng), nên về sau, người ta ném béng cái const ở đầu câu lệnh đi.

    Vì vậy,
    const char *const_char_1="1234567890"; //ồ, đừng tưởng const_char_1 là hằng, nó là biến. "1234567890" mới là hằng, nhưng nó không có tên và chỉ có thể sử dụng ở đây.
    const_char_1="1234567890ABCDEF.." ; //đúng, gán giá trị khác cho biến const_char_1
    printf("\n%s\n",const_char_1); // kết quả: 1234567890ABCDEF..


    Vì những ngọng nghịu "tiếng làng ta" đó của C++, người ta đàng phải chế ra C#, một hậu duệ của Pascal.

    Cái đoạn ví dụ class trên cho thấy ngọng giụ của C++
    đáng ra char *ch1="111111"; thay bằng một khai báo có kiểu string như Pascal thì đâu phải cho C++ nghỉ hưu sớm như thế.

    Nhưng không thể nói những cái ngọng nghịu ấy là sai. Vì nó diễn biến hết sức đúng theo yêu cầu của typist. Mà thật ra, cái nhược điểm lấn dẫn đến các chách viết tắt trên là do C++ thiếu hẳn một số lớp cơ bản, như string. C++ cũng hay làm người ta nhầm giữa a và a^. Nhưng rõ ràng, "hay làm người ta nhầm" có vẻ sai, vì ở đây, nó chỉ làm "cu teo nhầm" thôi, chứ có ai nhầm đâu.
    Được sửa bởi thanggia lúc 10:45 ngày 08-10-2007

Trang 4 / 8 FirstFirst 1234567 ... 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
  •