Trang 1 trên tổng số 3 123 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 30 kết quả

Đề tài: Lập trình C++ | Tài liệu lập trình C++ của Phạm Văn Ất

  1. #1
    Ngày gia nhập
    12 2006
    Bài viết
    72

    Mặc định Lập trình C++ | Tài liệu lập trình C++ của Phạm Văn Ất

    Đây được coi là cuốn học lập trình C++ rất cơ bản mà em được biết, và là cuốn sách được dùng trong giảng dạy môn lập trình C++ của nhiều trường đại học, có thể tìm trên thị trường quyến sách này một cách dễ dàng, nhưng em muốn post những bài viết trong cuốn sách để chúng ta cùng bàn luận, đánh giá những bài viết trong đó,em mong rằng qua đây chúng ta học hỏi thêm nhiều điều.
    Theo đúng thứ tự của quyển sách em xin đưa lên vài bài đầu tiên.

    §1. C và C++
    -Có thể nói C++ là sự mở rộng đáng kể của C. Điều đó có nghĩa là mọi khả năng, mọi khái niệm trong C đều có trong C++.
    -Vì trong C++ sử dụng gần như toàn bộ các khái niệm, định nghĩa,các kiểu dữ liệu,các cấu trúc lệnh,các hàm và các công cụ khạc cua C, nên để sử dụng đươc C++ thì bắt buộc phải thành thạo
    C.
    -Vì C++ là sự mở rộng của C nên bản than chương trình C đã là một chương trinh C++.Tuy nhiên trình biên dịch Tc++ yêu cầu mọi hàm chuẩn trong chương trình đều phải khai báo nguyên mẫu bằng câu lệnh #include, trong khi điều này không bắt buộc đối với trình biên dịch củaTC.
    Trong C có thể dung một hàm chuẩn mà bỏ qua câu lệnh #include để khai báo nguyên mẫu của hàm được sử dụng. Điều này không báo lỗi nhưng có thể dẫn đến kết quả sai khi chạy chương trình.
    Ví dụ: khi biên dịch chương trình sau trong môi trường C sẽ không hiện lên dòng cảnh báo(Warning) và thông báo lỗi(error).Nhưng khi chạy sẽ cho kết quả sai.

    Code:
    #include<stdio.h>
    void  main()
    {
    
    float a,b,c,p,s; printf(“\n nhap a,b,c”); scanf(“%f%f&f”,&a&b&c); p=(a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)); printf(“\n dien tich=%0.2f”,s); getch();
    }
    Nếu biên dịch chương trình này trong TC++ sẽ nhận được các thông báo lỗi sau:
    Eror: Funtion ‘sqrt’ should have a prototype
    Eror: Funtion ‘getch’ should have a prototype
    Để biến chương trình trên thành chương trình C++ cần:
    -đặt đuôi tệp chương trình là CPP
    -thêm 2 khai báo: #include<conio.h> và #include<ctype.h>
    §2. LẬP TRÌNH CẤU TRÚC VÀ LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
    2.1)Phương pháp lập trình cấu trúc
    - Tư tưởng chính là tổ chức chương trình thành các chương trình con.Trong pascal có 2 kiểu chương trình con đó là thủ tục và hàm.Trong C chi có 1 loại chương trình con đó là hàm.
    Hàm là một chương trình độc lập dung để thực hiện một phần việc nào đó như: nhập số liệu,in kết quả hay thực hiện một số tính toán. Hàm cần có đối và các biến,mảng cục bộ dung riêng cho hàm.
    Việc trao đổi dữ liệu giữa các hàm được thực hiện thông qua các đối và các biến toàn cục.
    Các ngôn ngữ như C,PASCAL,FOXPRO là các ngôn ngữ cho phép khai triển phương pháp lập trình cấu trúc.
    Một chương trình cấu trúc gồm cấu trúc dữ liệu( biến,mảng,bản ghi) và các hàm ,thủ tục.
    Nhiệm vụ chính của việc tổ chức,thiết kế chương trình cấu trúc là tổ chức chương trình thành các hàm, thủ tục. Chương trình sẽ bao gồm các hàm, thủ tục nào.
    Ví dụ: Viết chương trình nhập toạ độ (x,y) của một dãy các điểm,sau đó tìm một cặp điểm cách xa nhau nhất.
    Theo tư tưởng của lập trình cấu trúc có thể tổ chức chương trình như sau:
    -Sử dụng 2 mảng số thực toàn bộ x và y để chứa tọa bộ dãy điểm
    -Xây dựng 2 hàm:
    +) Hàm nhapsl để nhập toạ đô n điểm, hàm này có 1 đối là biến nguyên n điểm và được khai báo như sau:
    void nhapsl(int n);
    +) Hàm do_dai dung để tính độ dài đoạn thẳng đi qua 2 điểm có toạ độ là i và j và đươc khai báo như sau:
    void do_dai(int i,int j);
    Tư tưởng thuật toán:
    - Gán giá trị của dmax cho do_dai(điểm thứ nhất, điểm thứ 2)
    - Tính độ dài từng cặp điểm
    - Nếu độ dài nào lớn hơn thì gán giá trị đó cho dmax đồng thời đọc vị trí của cặp điểm đó.
    Chương trình thực hiện bài toán trên được viết như sau:
    Code:
    #include<stdio.h>
    #include<conio.h>
    #include<math.h>
    float x[100],y[100];
    float do_dai(int i,int j);
    {
    return sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2));
    }
    void nhapsl(int n)
    {
    int i;
    for(i=1;i<=n;i++)
    {
    printf(“\n Nhap toa do cua diem thu %d”,i);
    scanf(“%f %f”,&x[i]&y[i]);
    }
    }
    void main()
    int n,i,j,imax,jmax;
    float d,dmax;
    printf(“\n So diem: “); scanf(“%d”,&n);
    nhapsl(n);
    dmax=do_dai(1,2); imax=1;jmax=2;
    for(i=1;i<=n;i++)
    for(j=i+1;j<=n;j++)
    {
    d=do_dai(i,j);
    if(d>dmax)
    {
    dmax=d;
    imax=i;
    jmax=j;
    }
    }
    printf(“\n\n doan thang lon nhat co do dai bang:%0.2f”,dmax);
    printf(“\n\n di qua 2 diem co chi so la %d va %d “,imax,jmax);
    getch();
    
    }
    2.2)Phưong pháp lập trình hướng đối tượng:
    - Khái niệm trung tâm của lập trình hướng đối tượng là lớp(class). Có thể xem lớp là sự kết hợp giữa các thành phần dữ liệu và các hàm. Cũng có thể xem lớp là sự mở rộng cấu trúc trong C (struct) bằng cách đưa thêm vào các phương thức (method) hay còn gọi là các hàm thành viên (member function). Một lớp được định nghĩa như sau:
    Class Ten_lop
    {
    //khai báo các thành phần dữ liệu
    //khai báo các phương thức
    };
    - Các phương thức có thể được viết (xây dựng) bên trong hoặc bên ngoài (phía dưới) phần định nghĩa lớp. Cấu trúc (cách viết) phương thức tương tự như hàm ngoại trừ quy tắc sau: Khi xây dựng một phương thúc bên ngoài định nghĩa lớp thì trong dòng đầu tiên cần dung tên lớp và 2 dấu : đặt trước tên phương thức để chỉ rõ phương thức thuộc lớp nào (xem ví dụ bên dưới).
    - Sử dụng các thành phần dữ liệu trong phương thức: Vì phương thức và các thành phần dữ liệu thuộc cùng 1 lớp và vì phương thức được lập lên cốt đẻ xử lí các thành phần dữ liệu,nên trong than của phương thức có quyền truy cập đến các thành phần dữ liệu thuộc cùng 1 lớp.
    - Biến lớp: Sauk hi định nghĩa 1 lớp,có thể dung tên lớp đẻ khai báo các biến kiểu lớp hay còn gọi là các đối tượng. Mỗi đối tượng sẽ có các thành phần dữ liệu và các phương thức. Lời gọi phương thức cần chứa tên đối tượng để xác định phương thức thực hiện đối tượng nào.
    - Một chương trình hướng đối tượng sẽ bao gồm các lớp quan hệ với nhau.
    - Việc phân tích,thiết kế chương trình theo phương pháp hướng đối tượng nhằm thiết kế, xây dựng các lớp.
    - Từ khái niệm lớp đã nảy sinh hang loạt các khái niệm khác như: Thành phần dữ liệu,phương thức,phạm vi,sự đóng gói,hàm tạo,hàm huỷ,sự thừa kế,lớp cơ sở,lớp dẫn xuất, tương ứng bội,phương thức ảo…
    - Ưu điểm của việc thiết kế hướng đối tượng là tập trung xác định các lớp để mô tả các thực thể của bài toán. Mỗi lớp đưa vào các thành phần của thực thểvà xây dựng luôn các phương thức để xử lí dữ liệu. Như vậy việc thiết kế chương trnhf xuất phát từ các nội dung, các vấn đề của bài toán.
    - Các ngôn ngữ thuần tuý hướng đối tượng (Smalltalk) chỉ hỗ trợ thuần tuý các khái niệm về lớp, không hỗ trợ các khái niệm về hàm.
    - C++ là ngôn ngữ lai, nó cho phép sử dụng các khái niệm về lớp cũng như về hàm.
    - Để minh họa cho các khái niệm vừa nêu về lập trình hướng đối tượng ta xét lại bài toán tìm độ dài lớn nhất đi qua 2 điểm. Trong bài toán này ta gặp 1 thực thể là dãy điểm. Các thành phần của lớp dãy điểm bao gồm:
    +) Biến nguyên n là số điểm của dãy
    +) Con trỏ x kiểu thực trỏ đến vùng nhớ chứa dãy hoành độ
    +) Con trỏ y kiểu thực trỏ đến vùng nhứ chứa dãy tung độ
    Các phương thức cần đưa vào theo yêu cầu bài toán bao gồm
    - Nhập toạ độ một điểm
    - Tính độ dài đoạn thẳng đi qua 2 điểm.
    Dưới đây là chương trình viết theo thiết kế hướng đối tượng. Để thưc hiện chương trình này nhớ đặt tên tệp là CPP,khi viết trong Turbo C++ 3.0 thì đuôi của tệp được ghi mặc định là CPP. Trong chương trình ta thấy thêm một điều mới là: Các khai báo biến,mảng có thể viét bất kì chỗ nào trong chương trình miễn là khai báo trước khi sử dụng.
    Thuật toán đã trình bày ở trên dưới đây sẽ là chương trình.
    Code:
    #include<stdio.h>
    #include<conio.h>
    #include<math.h>
    #include<alloc.h>
    class daydiem 
       {
         public:
            int n;
            float *x,*y;
            float do_dai(int i, int j);
                   {
                       return sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2));
                    }
                void nhapsl(void);
              };
          void daydiem::nhapsl(void)
               {
      int i;
      printf(“\n So diem N= “);scanf(“%d”,&n);
      x=(float*)malloc((n+1)*sizeof(float));
      y=(float*)malloc((n+1)*sixeof(float));
      for(i=1;i<=n;i++)
        { 
         printf(“\n\n nhap toa do x,y cua diem thu %d: “,i);
                  scanf(“%f %f”,&x[i],&y[i]);
                }
           }
      void main()
          {
             daydiem p;
             p.nhapsl();
             int n,i,j,imax,jmax;
             float d,dmax;
             n=p.n;
             dmax=p.do_dai(1,2);imax=1;jmax=2;
             for(i=i;i<=n-1;i++)
               for(j=i+1;j<=n;j++)
                  {
                    d=p.do_dai(i,j);
                    if(d>dmax)
                      {
                        dmax=d;
                        imax=i;
                        jmax=j;
                      }
    printf(“\n Doan thang lon nhat co do dai bang: %0.2f”,dmax);
    printf(“\n di qua 2 diem co chi so la %d va %d”,imax,jmax);
    getch();}
    Đã được chỉnh sửa lần cuối bởi Tarzan : 18-12-2006 lúc 11:04 AM.

  2. #2
    Ngày gia nhập
    12 2006
    Bài viết
    72

    §3. Một số mở rộng đơn giản của C++ so với C
    Trong mục này sẽ trình bày một số mở rộng của C++, tuy đơn giản nhưng đem lại rất nhiều tiện lợi.
    3.1) Viết các dòng ghi chú:
    Trong C++ vẫn có thể viết các dòng ghi chú trong các dấu /* và */ như trong C. Cách này cho phép viết ghi chú trên nhiều dòng. Ngoài ra trong C++ còn cho phép viết ghi chú trên 1 dòng sau hai dấu gạch chéo.
    Ví dụ: int x,y; // khai báo hai biến thực.
    3.2) Khai báo linh hoạt:
    Trong C tất cả các câu lệnh khai báo biến, mảng cục bộ phải đặt đầu khối. Do vậy đôi khi vị trí khai báo và vị trí sử dụng ká xa nhau, gây khó khăn trong việc kiểm soát chương trìng. C++ đã khắc phục đựơc nhược điểm này bằng cách cho phép các câu lệnh khai báo biến, mảng ở bất kì chỗ nào trong chương trình trước khi các biến, mảng đó được sử dụng.
    Ví dụ: Chương trình nhập một dãy số thực rồi sắp xếp theo thứ tự tăng dần có thể viết trong C++ như sau:
    Code:
    #include<stdio.h>
        #inclue<conio.h>
     #include<alloc.h>
         void main()
     {
        int n;
        printf(“\n so phan tu cua day N= “);scanf(“%d”,&n);
        float *x=(float*)malloc((n+1)*sixeof(float));
        for( int i=1;i<=n;i++)
          {
             printf(“\n X[%d] = “),i);scanf(“%f”,x+1);
          }
        for(i=1;i<=n;i++)
           for(int j=i+1;j<=n;j++)
              if(x[i]>x[j])
                { 
                   float tg=x[i];
                   x[i]=x[j];
                   x[j]=tg;
                }
    printf(“\n day so sau khi sap xep: “);
    for(i=1;i<=n;i++)
       printf(“%0.2f”,x[i]);
    getch();
    
        }
    3.3) Toán tử ép kiểu:
    Trong C toán tử này được viết như sau:
    (kiểu)biểu thức
    Trong C++ vẫn có thể viết thế này. Ngoài ra C++ cho phép viết một cách khác tiện lợi hơn như sau:
    Kiêu(biểu thức)
    Ví dụ chương trình tính công thức:
    S=2/1+3/2+…+(n+1)/n
    với n là một số nguyên dương nhập từ bàn phím, có thể viết như sau:
    Code:
    #include<stdio.h>
     #include<conio.h>
     void main()
       {
          int n;
          printf(“\n So phan tu cua day N= “);
          scanf(“%d”,&n);
          float s=0;
          for(int i=1;i<=n;i++) 
             s+=float(i+1/float(i);
          printf(“\n S= %0.2f”,s);
          getch();
      }
    3.4) Hằng có kiểu
    Đê tạo ra một hằng có kiểu,ta sử dụng từ khoá conts đặt trước một khai báo khởi gán giá trị. Sau đây là một số ví dụ:
    + Hằng nguyên:
    Const int maxsize=1000;
    int a[maxsize];
    + Cấu trúc hằng :
    typedef struct
    {
    int x,y;
    int mau;
    } DIEM;
    conts DIEM d={320,240,15};
    Chương trình dưới đây minh hoạ cách dung hằng có kiểu. Chương trình tạo một cấu trúc hằng (kiểu DIEM) mô tả giữa màn hình đồ hoạ và màu trắng. Điểm này được hiển thị trên màn hình đồ hoạ.
    Code:
    #include<stdio.h>
                    #include<conio.h>
    #include<graphics.h>
    #include<stdlib.h>
    typedef struct
                {
                  int x,y;
                  int mau;
                }DIEM;
    void main()
       {
         int mh=0,mode=0;
         inỉtgaph(&mh,&mode,””);
         int loi=graphresult();
         if(loi)
           {
              printf(“\n Loi do hoa: %s”,grapherrormsg(loi));
              getch();exit();
           }
         const DIEM gmh= {getmaxx()/2,getmaxxy()/2,WHITE};
         putpixel(gmh.x,gmh.y,gmh.mau);
         getch();
         closegraph();
    }
    Chú ý:
    a. Có thể dùng các hàm để gán giá trị cho các hằng số có kiểu( trong chương trình trên dùng các hàm getmaxx và getchmaxy).
    b. Mọi câu lệnh nhằm thay đổi giá trị của hằng có kiểu đều bị báo lỗi khi biên dịch chương trình. Ví dụ trong chương trình đưa vào chương trình gmh.x=200; thì khi dich chương trình sẽ nhận được thông báo lỗi như sau:
    Cannot modify a const object
    3.5 Các kiểu char và int
    Trong C một hằng kí tự được coi là nguyên do đó nó có kích thước 2byte, ví dụ trong C: sizeof(‘A’)=sizeof(int)=2.
    Còn trong C++ một hằng kí tự được xem là giá trị kiểu char và có kích thước 1 byte. Như vậy trong C++: sizeof(‘A’)=sizeof(char)=1
    3.6 Lấy đị chỉ các phần tử mảng 2 chiều
    Trong turbo C 2.0 không cho phép dung phép & để lấy địa chỉ các phần tử mảng 2 chiều. Vì vậy khi nhập một ma trận thực (dung scanf) ta phải nhập qua một biến trung gian sau đó mới gán cho các phần tử mảng.
    Trong TC 3.0 cho phép lấy địa chỉ các phần tử mảng thực 2 chiều. Do đó có thể dung hàm scanf để nhập trực tiếp các phần tử của mảng.
    Chương trình C++ sau đây sẽ minh hoạ điều này. Chương trình nhập một ma trận thực cấp mxn và xác định phần tử có giá trị lớn nhất.
    Code:
    #include<stdio.h>
                   #include<conio.h>
    void main()
       {
         float a[20][20], smax;
         int m,n,i,j,imax,jmax;
      clrscr();
      puts(“\n Cho biet so hang va so cot cua ma tran: “);    
      scanf(“%d %d”,&m,&n);
      for(i=1;i<=m;i++)
          for(j=1;j<=n;j++)
            {
               printf(“\n a[%d][%d]”,i,j);
               scanf(“%f”,&a[i][j]);  //lấy địa chỉ phần tử mảng thực 2 
                                                     //chiều
            } 
      smax=a[1][1];imax=1;jmax=1;
     for(i=1;1<=m;i++) 
       for(j=1;j<=n;j++)
         if(smax<a[i][j])
            {
              smax=a[i][j];
              imax=i;
              jmax=j;
            }
    puts(“\n\n Ma tran”);
    for(i=1;i<=m;i++)
      for(j=1;j<=n;j++)
          {
            if(j==1) puts(“”);
            printf(“%6.1f”,a[i][j]);
          }
      puts(“\n\n Phan tu max: “);
      printf(“\n\n co gia tri= %6.1f”,smax);
      printf(“\n Tai hang %d cot %d “,imax,jmax);
      getch();
    }
    em tạm post vài bài ,nếu mọi người ủng hộ em tiếp tục đưa lên,đay là mấy bài đầu nên chưa nhiều chuyện để bàn lắm. Nguyện vọng của em khi mọi người nghiên cứu chúng ta sẽ đặt ra các câu hỏi: làm thế nào, tại sao như thế, không thế thì sẽ thế nào? để chúng ta học hỏi nhau nhiều hơn
    Đã được chỉnh sửa lần cuối bởi thangtran : 18-12-2006 lúc 09:37 PM.

  3. #3
    Ngày gia nhập
    12 2006
    Bài viết
    72

    [ §4. Vào ra trong C++
    4.1) Các toán tử và phương thức xuất nhập
    Để in dữ liệu ra màn hình và dữ liệu nhập từ bàn phím, trong C++ vẫn có thể dung các hàm printf và scanf( nhưng chỉ trong các chương trình C++ ở các mục trên).
    Ngoài ra trong C++ còn dung các toán tử xuất:
    cout<<biểu thức<<…<<biểu tức;
    để đưa giá trị các biểu thức ra màn hình dùng các toán tử nhập:
    cin>>biến>>…>>biến;
    để nhập các giá trị số (nguyên, thực) từ bàn phím và gán cho các biến.
    Để nhập một dãy không quá n kí tự và chứa mảng h (kiểu char) có thể dung phương thức cin.get như sau:
    cin.get(h,n);
    Chú ý 1: Toán tử cin>> sẽ để lại kí tự chuyển dòng ‘\n’ trong bộ đệm, kí tự này có thể làm trôi phương thức cin.get. Để khắc phục tình trạng trên cần dung phương thức cin.ignore để bỏ qua 1 kí tự chuyển dòng như sau:
    cin.agnore(1);
    Chú ý 2: Để sử dụng được các toán tử và các phương thức nói trên cần khai báo tệp tiêu đề: #include<iosteam.h>
    Điều thú vị: với C++ ta không cần quan tâm tới các đặc tả của biến , vì khi dịch chương trình dịc đã tự động nhận ra đó là biến loại gì khi gặp câu lệnh khai báo biến
    Chương trình sau sẽ minh họa việc sử dụng các công cụ vào ra mới của C++ để nhập 1 danh sách n thí sinh. Dữ liệu của mỗi thí sinh gồm họ tên,các điểm toán,lí,hoá. Sau đó in danh sách thí sinh theo thứ tự giảm của tổng điểm.
    Code:
    #include<iostream.h>
    #include<conio.h>
    void main()
       {
         struct
             {
                char ht[25];
                float t,l,h,td;
             }ts[50],tg;
         int n,i,j;
         clrscr();
         cout<<” so thi sinh: “;
         cin>>n;
         for”(i=1;i<=n;i++)
            {
              cout<<”\n\n thi sinh thu “<<i;
              cout<<”\n\n ho ten: “; cin.ignore(1);     
              cin.get(ts[i].ht,25);
              cout<<”\n\n diem toan  ,li,  hoa”;
              cin>>ts[i].t>>ts[i].l>>ts[i].h;
              ts[i].td=ts[i].t+ts[i].l+ts[i].h;
            }
         for(i=1;i<=n;i++)
           for(j=i+1;j<=n;j++)
             if(ts[i].td<ts[j].td)
                 {
                   tg=ts[i];
                   ts[i]=ts[j];
                   ts[j]=tg;
                 }
     cout<<”\n\n Danh sach thi sinh sau khi sap xep”;
     for(i=1;i<=n;i++)
       {
         cout<<”\n\n ho ten”<<ts[i].ht;
         cout<<”\n\n Tong diem: “<<ts[i].td;
       }
    getch();
               }
    4.2. Định dạng khi in ra m àn hình
    +Để qui định số thực (float,double) đươc in ra đúng p chữ số sau dấu chấm thập phân,ta sử dụng đồng thời các hàm sau:
    setiosflags(ío::showpoint);// Bật cờ hiệu showpoint
    setprecision(p);
    Các hàm này cần đặt trong toán tử xuất như sau:
    cout<<setiosflags(ios::showpoint)<<setprecision(p) ;
    Câu lệnh trên sẽ có hiệu lực đối với tất cả các toán tử xuất tiếp theo cho đến khi gặp một câu lệnh định dạng mới.
    +Để qui định độ dộng tối thiểu là w vị trí cho giá trị (nguyên,thực,chuỗi) được in trong các toán tử xuất,ta dung hàm
    Set(w)
    Hàm này cần đặt trong toán tử xuất và nó chỉ có hiệu lực cho 1 giá trị được in gần nhất.Các giá trị in ra tiếp theo sẽ có độ rộng tối thiếu là 0. Như vậy câu lệnh:
    cout<<set(3)<<”AB”<<”CD”
    Sẽ in ra 5 kí tự là: một dấu cách và 4 chữ cái A,B,C và D.
    Muốn sử dụng các hàm trên cần đưa ra câu lệnh #include sau:
    #include<iomanip.h>
    Trở lại chương trình trên ta thấy danh sách thí sinh in ra sẽ không thẳng cột. Để khắc phục điều này cần viết lại đoạn chương trình in như sau:
    Code:
    cout<<”\n Danh sach thi sinh sau khi sap xep”;
             cout<<setiosflags(ios::showpoint)<<setprecision(1);
             for(i=1;i<=n;i++)
                {
                  cout<<”\n Ho ten: “<<setw(25)<<ts[i].ht;
                  cout<<”\n Tong diem: “<<setw(5)<<ts[i].td;
                 }
              getch();
    Chương trình dưới đây là một minh hoạ khác về việc sử dụng các toán tử nhập,xuất và các định dạng trong C++. Chương trình nhập 1 ma trận thực cấp mxn. Sau đó in ma trận dưới dạng bảng và tìm một phần tử lớn nhất.
    Code:
    #include<iostream.h>
    #include<conio.h>
    #include<iomanip.h>
    void main()
      {
        float a[20][20],smax;
        int m,n,I,j,imax,jmax;
        clrscr();
        cout<<”\n cho biet so hang va so cot cua ma tran: “;
        cin>>m>>n;
        for(i=1;i<=m;i++)
          for(j=1;j<=n;j++)
             {
                     cout<<”a[“<<i<<”,”<<j<<”]=”;
                     cin>>a[i][j];
                  }
                smax=a[1][1];
                imax=1;
                jmax=1;
            for(i=1;i<=m;i++)
               for(j=1;j<=n;j++)
                 if(smax<a[i][j])
                   {
                     smax=a[i][j];
                     imax=i;
                     jmax=j;
                    }
                 
                    }
                 cout<<”\n\n ma tran”;
                  for(i=1;i<=m;i++)
                     for(j=1;j<=n;j++)
                        {
                          if(j==1) cout<<’\n’;
                          cout<<setw(6)<<a[i][j];
                         }
                    cout<<”\n\n”<<” phan tu max: “<<’\n’;
                    cout<<”co gia tri= “<<setw(6)<<smax;;
                    cout<<”\n tai hang “<<imax<<”cot “<<jamx;
                    getch”();
                }

  4. #4
    Ngày gia nhập
    12 2006
    Bài viết
    72

    hôm nay em xin giới thiệu bài tiếp theo:
    §5.Cấu trúc,hợp và kiểu liệt kê
    5.1. Tên sau từ khoá struct được xem như tên kiểu cấu trúc
    Trong C++ một kiểu cấu trúc cũng được định nghĩa như C theo mẫu:
    struct tên_kiểu_ct
    {
    // khai báo các thành phần của cấu trúc
    };

    Sau đó có thể khai báo các biến,mảng cấu trúc trong c dung như sau:
    struct Ten_kieu_ct danh sách các biến,mảng cấu trúc;
    Như vậy trong C, tên viết sau từ khoá struct chưa phải là tên kiểu và chưa có thể dung để khai báo.
    Trong C++ coi tên viết sau từ khoá struct là tên kiểu cấu trúc và có thể dung nó để khai báo. Như vậy để khai báo các biến,mảng cấu trúc trong C++, ta có thể dung mẫu sau:
    Tên_kiểu cấu_trúc danh sách biến,mảng cấu trúc;
    Ví dụ sau sẽ: Định nghĩa kiểu cấu trúc TS(thí sinh) gồm các thành phần: ht(họ tên), sobd(số báo danh), dt(điểm toán), dl(điểm lí), dh(điểm hoá) và td(tổng điểm), sau đó khai báo biến cấu trúc h và mảng cấu trúc ts.
    struct TS
    {
    char ht[25];
    long sobd;
    float dt,dl,dh,td;
    };
    TS h,ts[1000];

    5.2. Tên sau từ khoá union được xem như tên kiểu hợp
    Trong C++ một kiểu hợp (union) cũng được định nghĩa như trong C theo mẫu:
    union Tên_kiểu_hợp
    {
    // Khai báo các thành phần của hợp.
    };

    Sau đó đê khai báo các biến,mảng kiểu hợp trong C dung mẫu sau:
    Union Tên_kiểu_hợp danh sách biến,mảng kiểu hợp;
    Như vậy trong C, tên viết sau từ khoá union chưa phải là tên kiểu và chưa có thể dung để khai báo.
    Trong C++ xem tên viết sau từ khoá union là tên kiểu hợp và có thể dùng nó để khai báo. Như vậy để khai báo các biến,mảng kiểu hợp, trong C++ có thể dung mẫu sau:
    Tên_kiểu_hợp danh sách biến, mảng kiểu hợp;
    5.3. Các union không tên
    Trong C++ cho phép dung các union không tên dạng:
    union
    {
    int i;
    char ch;
    float x;
    };

    Khi đó các thành phần (khai báo trong union) sẽ dùng chung một vùng nhớ . Điều này cho phép tiết kiệm bộ nhớ và cho phép dễ dàng tách các byte của một vùng nhớ.
    Ví dụ: Nếu các biến nguyên I, biến kí tự ch và biến thực x không đồng thời sử dụng thì có thể khai báo chúng trong 1 union không tên như sau:
    union
    {
    int i;
    char ch;
    float x;
    };

    Khi đó các biến i,ch và f sử dụng một vùng nhớ 4byte.
    Xét 1 ví dụ khác, để tách các byte của một biến unsignedlong ta dung union không tên như sau:
    union
    {
    unsigned long u;
    unsigned char b[4];
    };

    Khi đó nếu gán
    u=0xDDCCBBAA; // Số hệ 16;
    thì
    b[0]=0xAA
    b[1]=0xBB
    b[2]=0xCC
    b[3]=0xDD
    5.4. Kiểu liệt kê (enum)
    + Củng giống như cấu trúc và hợp, tên viết sau từ khoá enum được xem là kiểu liệt kê và có thể dung để khai báo,ví dụ:
    enum MAU {xanh,do,tim,vang};//định nghĩa kiểu MAU
    MAU m,dsm[10]; // khai báo các biến ,mảng kiểu MAU
    + Các giá trị kiểu liệt kê (enum) là các số nguyên. Do đó có thể thực hiện các phép tính trên các giá trị enum, có thể in các giá trị enum, có thể gán giá trị enum cho biến nguyên, ví dụ:
    MAU m1,m2;
    int n1,n2;
    m1=tim;
    m2=vang;
    n1=m1; // n1=2;
    n2=m1+m2 ;// n2=5
    printf(“\n %d”, m2); // in ra số 3
    + Không thể gán trực tiếp 1 giá trị nguyên cho 1 biến enum mà phải dung phép ép kiểu, ví dụ:
    m1=2; //lỗi
    m1=MAU(2); // đúng.

  5. #5
    Ngày gia nhập
    12 2006
    Bài viết
    72

    Khi lập trình mà ta không biết mỗi biến được cấp phát bộ nhớ như thế nào thì sẽ rất khó khăn trong việc sử dụng chúng một cách tối ưu nhất và đây cũng là một vấn đề khá thú vị khi tìm hiểu và so sánh việc cấp phát bộ nhớ của C và C++ có gì khác nhau.
    §6. CẤP PHÁT BỘ NHỚ
    6.1. Trong C++ có thể dung các hàm cấp phát bộ nhớ động của C như: hàm malloc để cấp phát bộ nhớ, hàm free để giải phóng bộ nhớ được cấp phát.
    6.2. Ngoài ra trong C++ còn đưa them toán tử new để cấp phát bộ nhớ và toán tử delete để giải phóng bộ nhớ được cấp phát bởi new.
    6.3 Cách dung toán tử new để cấp phát bộ nhớ như sau:
    + Trước hết cần khai báo 1 con trỏ để chứa địa chỉ vùng nhớ sẽ được cấp phát:
    Kiểu *p;
    ở đây kiểu có thể là :
    - Các kiểu dữ liệu chuẩn trong C++ như int, long, float,double,char …
    - Các kiểu do lập trình viên định nghĩa như: mảng,hợp,cấu trúc, lớp…
    + Sau đó dung toán tử new theo mẫu:
    p=new Kiểu; // Cấp phát bộ nhớ cho một biến (một phần tử)
    p=new Kiểu[n]; // Cấp phát bộ nhớ cho n phần tử.
    ví dụ: Để cấp phát bộ nhớ cho một biến thực ta dung câu lệnh sau:
    float *px=new float;
    Để cấp phát bộ nhớ cho 100 phần tử nguyên ta dung các câu lệnh sau:
    int *pn=new int[100];
    for(i=0;i<100;i++)
    pn[i]= 20*i;// Gán cho phần tử thứ i
    6.4. Hai cách kiểm tra sự thành công của new
    Khi dung câu lệnh:
    Kiểu *p=new Kiểu[n];
    hoặc câu lệnh
    Kiểu *p= new Kiểu;
    để cấp phát bộ nhớ sẽ xuất hiện 1 trong 2 trường hợp: thành công hoặc không thành công
    Nếu thành công thì p sẽ chứa địa chỉ đầu vùng nhớ được cấp phát.
    Nếu không thành công thì p=NULL.
    Đoạn chương trình sau sẽ minh hoạ cách kiểm tra sự thành công của new
    double *pd;
    int n;
    cout<<”\n số phần tử: “;
    cin>>n;
    pd=new double[n];
    if(pd==NULL)
    {
    cout<<”\n lỗi cấp phát bộ nhớ”;
    exit(0);
    }

    Cách thứ hai dùng để kiểm tra sự thành công của toán tử new là dung con trỏ hàm :
    _new_handler
    được định nghia trong tệp “new.h”. Khi gặp lỗi trong toán tử new( cấp phát không thành công) thì chương trình sẽ thực hiện một hàm nào đó do con trỏ _new_handler trỏ tới. Cách dùng con trỏ này như sau:
    + Xây dựng một hàm dung để kiểm tra sự thành công của new
    + gán tên hàm này cho con trỏ _new_handler
    Như vậy hàm kiểm tra sẽ được gọi mỗi khi có lỗi xảy ra trong toán tử new.
    Đoạn chương trình kiểm tra theo cách thứ nhất có thể được viết theo cách thứ 2 như sau:
    void kiem_tra_new(void) // lập hàm kiểm tra
    {
    cout<<”\n loi cap phat bon nho”;
    exit(0);
    }
    _new_handler= kiem_tra_new; // gán tên hàm cho con trỏ
    double *pd;
    int n;
    cout<<”\n So phan tu: “;
    cin>>n;
    pd=new double[n]; //khi xảy ra lỗi sẽ gọi hàm kiem_tra_new
    Chú ý : Có thể dung lệnh gán để gán tên hàm xử lí lỗi cho con trỏ _new_handler như trong đoạn chương trình trên, hoặc dung hàm:
    set_new_handler(tên hàm);
    (xem các chương trình minh hoạ bên dưới)
    6.5. Toán tử delete dung để giải phóng vùng nhớ được cấp phát bởi new
    Cách dung như sau:
    delete p; // p là con trỏ trong new
    Ví dụ:
    float *px;
    px=new float[2000];// cấp phát bộ nhớ cho 2000 phần tử thực.
    // sử dụng bộ nhớ được cấp phát
    delete px; // giải phóng bộ nhớ
    6.6. Hai chương trình minh hoạ
    Chương trình 1: Minh hoạ cách dung new để cấp phát bộ nhớ cho n thí sinh. Mỗi thí sinh là một trường cấu trúc gồm các trường ht(họ tên), sobd(số báo danh) và td(tổng điểm). Chương trình sẽ nhập n,cấp phát bộ nhớ chứa n thí sinh, kiểm tra lỗi cấp phát bộ nhớ( dung cách 1), nhập n thí sinh, sắp xếp thí sinh theo thứ tự giảm dần của tổng điểm, in danh sách thí sinh sau khi sắp xếp, và cuối cùng là giải phóng bộ nhớ đã cấp phát.
    Code:
    #include<iomanip.h>
    #include<iostream.h>
    #include<stdlib.h>
    #include<conio.h>
    struct TS
       {
         char ht[20];
         long sobd;
         float td;
      };
    void main()
     {
       TS *ts;
        int n;
        clrscr();
        cout<<”\n So thi sinh n= “;
        cin>>n;
        ts=new TS[n+1];
        if(ts==NULL)
           {
             cout<<”\n Loi cap phat bo nho”;
             getch();
             exit(0);
           }
       for( int i=1;i<=n;i++)
         {
           cout<<”\n Thi sinh thu “<<i;
           cout<<”\n Ho ten : “;
           cin.ignore(1);
           cin.get(ts[i].ht,20);
           cout<<” \n So bao danh: “;
           cin>>ts[i].sobd;
          cout<<” Tong diem: “;
          cin>>ts[i].td;
        }
    for(i=1;i<=n;i++)
       for(int j=i+1;j<=n;j++)
          if(ts[i].td<ts[j].td)
              {
                TS tg=ts[i];
                      ts[i]=ts[j];
                     ts[j]=tg;
              }
               cout<<setiosflags(ios::showpoint)<<setprecision(1);
         for(i=1;i<=n;i++)
                                           cout<<”\n”<<setw(20)<<ts[i].ht<<setw(6)<<ts[i].sobd<<setw(6)<<ts[i].td;
    delete ts;
    getch();
               }
    Chương trình thứ hai minh hoạ cách dung con trỏ _new_handler để kiểm tra sự thành công của new. Chương trình sẽ cấp phát bộ nhớ cho 1 mảng con trỏ và sẽ theo dõi khi nào thì không đủ bộ nhớ để cấp phát.
    Code:
    #include<new.h>
    #include<iostream.h>
    #include<stdlib.h>
    #include<conio.h>
    int k;
    void loi_bo_nho(void)
          {
            cout<<”\n Loi bo nho khi cap phat bo   nho cho q[“<<k<<”]”;
            getch();
            exit(0);
         }
    void main()
        {
          double *q[100];
          long n;
          clrscr();
          set_new_handler(loi_bo_nho);
          // _new_handler=loi_bo_nho;
          n=1000;
          for(k=0;k<100;k++)
            q[k]=new double[n];
          cout<<”\n\n khong loi”;
          getch();
    }
    có bài này khá thú vị mọi người chạy thử rồi nêu kết quả sau đó giải thích dùm, em không hiểu, hi hi:
    Code:
    #include <iostream.h>
    #include <new.h>
    #include <stdlib.h>
    #include<conio.h>
    void tbao() {
      cerr << "\nKhong the cap phat!";
      getch();
      exit(1);
      }
    
    void main(void) {
      set_new_handler(tbao);
      clrscr();
      char *ptr = new char[100];
      cout << "\nCap phat lan 1: ptr = " << hex << long(ptr);
      ptr = new char[64000U];
      cout << "\n Cap phat lan cuoi: ptr = " << hex << long(ptr);
      set_new_handler(0);  
      getch();
    }

  6. #6
    Ngày gia nhập
    12 2006
    Bài viết
    72

    Mặc định Lập trình C++ | Tài liệu lập trình C++ của Phạm Văn Ất

    Trong những bài đầu tiên ta đã thấy sự mở rộng khá nhiều của C++ so với C
    Hôm nay em sẽ giới thệu cho mọi người một phần khá quan trọng, và phấn này cũng khá quan trọng trong quá trình viết chương trình đó là "HÀM VÀ CÁCH SỬ DỤNG HÀM", riêng phần này C++ đã có khá nhiều cải tiến so với C, vì là cải tiến nên nó vẫn chứa đựng những hàm trong C thêm vào đó là các hàm mang tính tiện lợi hơn cho người viết chương trình như hàm tham chiếu , hàm chồng toán tử.
    Sẽ rất khó khi giới thiệu cùng một lúc tất cả các hàm nên em sẽ giới thiệu ít một và theo kinh nghiệm của em khi nghiên cứu bất kì hàm nào chúng ta nên suy nghĩ kĩ + cố gắng hiểu sâu thì khi viết chương trình ý tưởng sẽ được mã hóa thành chương trình một cách nhanh chóng hơn.
    Thôi em không dài dòng nữa, em xin đi ngay vào bài học của chúng ta:
    § Làm quen với hàm trong C++
    1. Đổi kiểu tham chiếu
    Trong C, để nhận kết quả của hàm cần dung đối con trỏ,làm cho việc xây dựng cũng như sử dụng hàm khá phiền phức. Trong C++ đưa vào đối kiểu tham chiếu (giống như pascal) dung để chứa kết quả của hàm, khiến cho việc tạo lập cũng như sử dụng hàm đơn giản hơn
    2. Đối tham chiếu const
    Đối tham chiếu có đặc điểm là các câu lệnh trong than của hàm có thể truy nhập tới và dễ dàng làm thay đổi giá trị của nó. Nhiều khi ta muốn dung đối kiểu tham chiếu chỉ để tăng tốc độ trao đổi dữ liệu giữa các hàm, không muốn dung nó để chứa kết quả của hàm. Khi đó có thể dung đối tham chiếu const để bảo toàn giá trị của đối trong than hàm.
    3. Đối có giá trị mặc định
    Trong nhiều trường hợp người dung viết một lời gọi hàm nhưng còn chưa biết nên chọn giá trị nào cho các đối. Đẻ khắc phục khó khăn này, C++ đưa ra giải pháp đối có giá trị mặc định. Khi xây dựng hàm ta gán giá trị mặc định cho số đối. Người dung nếu không cung cấp giá trị cho các đối thì hàm sẽ dùng giá trị mặc định
    4. Hàm online
    Đối với một đoạn chương trình nhỏ(số lệnh không lớn) thì việc thay các đoạn chương trình này bằng các lời gọi hàm sẽ làm cho chương trình gọn nhẹ đôi chút nhưng làm tăng thời gian máy. Trong các trường hợp này có thể dung hàm trực tuyến(on line) vừa giảm kích thước chương trình nguồn , vừa làm tăng thời gian chạy máy
    5. Các hàm trùng tên(định nghĩa chồng các hàm)
    Để lấy giá trị tuyệt đối của các số, trong C cần lập nhiều hàm với các tên khác nhau, ví dụ abs cho số nguyên, fabs cho số thực, labs cho số nguyên dài,cabs cho số phức. Điều này rõ rang gây phiền toái cho người sử dụng.Trong C++ cho phép xây dựng các hàm trùng tên nhưng khác nhau về kiểu đối. Như vậy chỉ cần lập một hàm để lấy giá trị tuyệt đối cho nhiều kiểu dữ liệu khác nhau.
    6. Định nghĩa chồng toán tử
    Việc dung phép toán thay cho lời gọi hàm rõ rang làm cho chương trình ngắn gọn,sáng sủa hơn nhiều . Ví dụ để thực hiện phép cộng 2 ma trận nếu dùng phép cộng và viết:
    C=A+B;
    Thì rất gần với toán học. Trong C++ cho phép dung các phép toán chuẩn để đặt tên cho các hàm(gọi là định nghĩa chồng toán tử). Sau đó có thể thay lời gọi hàm bằng các phép toán như ở trên. Như vậy một phép toán mang nhiều ý nghĩa, ví dụ phép cộng có thể cộng 2 số nguyên,2 số thực hoặc 2 ma trận. C++ sẽ căn cứ vào kiểu của số hạng mà quyết định chọn phép cộng cụ thể.

  7. #7
    Ngày gia nhập
    12 2006
    Bài viết
    72

    Hôm nay em xin giới thiệu chi tiết về lí thuyêt đã nói hôm qua
    Đầu tiên là các loại tham chiếu,bài hôm nay đi vào biến tham chiếu
    §1. BIẾN THAM CHIẾU (REFERENCE VARIABLE)
    1.1. Hai loại biến dùng trong C
    Trước khi nói đến biến tham chiếu, chúng ta nhắc đến 2 loại biến thường gặp trong C đó là:
    + Biến giá trị dung để chứa dữ liệu( nguyên, thực, kí tự)
    + Biến con trỏ dung để chứa địa chỉ.
    Các biến này đều được cấp phát bộ nhớ và có địa chỉ. Ví dụ câu lệnh khai báo: double x, *px;

    sẽ tạo ra biến giá trị kiểu double x và biến con trỏ kiểu double px. Biến x có xùng nhớ 8 byte, biến px có vùng nhớ 4 byte (nếu dung mô hình Large). Biến x dùng để chứa giá trị kiểu double, ví dụ lệnh gán:
    x=3.14;
    sẽ đưa giá trị 3.14 vào biến x. Biến px dung để chứa địa chỉ của một biến thực,ví dụ câu lệnh:
    px=&x;
    sẽ lưu giữ địa chỉ của biến x vào con trỏ px.

    1.2. Biến tham chiếu
    Trong C++ cho phép sử dụng loại biến thứ ba là biến tham chiếu.So với 2 loại biến kể trên thì biến này có những đặc điểm sau:
    Biến tham chiếu không được cấp phát bộ nhớ và không có địa chỉ riêng.
    Nó dung làm bí danh cho một biến (kiểu giá trị) nào đó và nó sẽ sử dụng vùng nhớ của biến này. Ví dụ câu lệnh:
    float u,v,&r=u;
    tạo ra biến thực u,v và biến tham chiếu thực r. Biến r không được phát bộ nhớ, nó là một tên khác( bí danh ) của u và nó dung chung vùng nhớ của biến u.
    Thuật ngữ: Khi r là bí danh(alias) của u thì nói r tham chiếu tới u,như vậy 2 thuật ngữ trên được hiểu như nhau.
    Ý nghĩa: Khi r là bí danh của u thì r dung chung vùng nhớ của u, do đó:
    + Trong mọi câu lệnh , viết u hay viết r đều có ý nghĩa như nhau, vì đều truy cập đến cùng một vùng nhớ.
    + Có thể dung biến tham chiếu để truy nhập đến một biến kiểu giá trị.
    Ví dụ:
    int u,v,&r=u;
    r=10; //u=10
    cout<<u; // in ra số 10
    r++; //u=11
    ++u; // r=12
    cout<<r; // in ra số 12
    v=r; // v=12
    &r; // cho địa chỉ của u
    Công dụng: biến tham chiếu thường được sử dụng lam đối của hàm để cho phép hàm truy nhập đến các tham số trong lời gọi hàm.
    Vài chú ý về biến tham chiếu:
    a. Vì biến tham chiếu không có địa chỉ riêng, nó là bí danh của một biến kiểu giá trị, nên trong khai báo phải chỉ rõ tham chiếu tới biến nào.Ví dụ nếu khai báo:
    double &x;
    thì trình biên dịch sẽ báo lỗi:
    Reference variable ‘x’ must be initialized
    b. Biến tham chiếu có thể tham chiếu tới một phần tử của mảng, ví dụ:
    int a[10], &r=a[5];
    r=25; // a[5]=25
    c. Không cho phép khai báo mảng tham chiếu.
    d. Biến tham chiếu có thể tham chiếu tới một hằng. Khi đó nó sẽ sử dụng vùng nhớ của hằng và nó có thể làm thay đổi giá trị chứa trong vùng nhứ này.
    Ví dụ nếu khai báo:
    Int &s=23;
    Thì trình biên dịch sẽ đưa ra cảnh báo (warning)
    Temporary used to initialize ‘s’
    Tuy nhiên chương trình vẫn làm việc. Các câu lệnh dưới đây vẫn thực hiện và cho kết quả như sau;
    s++;
    cout<<”\n s=<<s; // in ra s=24
    Chương trình dưới đây minh hoạ cách dung biến tham chiếu tới một phần tử của mảng cấu trúc để nhập dữ liệu và thực hiện các phép tính trên trường của phần tử mảng cấu trúc.
    Code:
    #include<iostream.h>
    #include<conio.h>
    struct TS
       {
           char ht[25];
           float t,l,h,td;
       };
    void main()
         {
           TS ts[10], &h=ts[1];// h tham chiếu tới thí sinh 1.
            cout<< “\n Ho ten: “;
            cin.get(h.ht,25);
            cout<<” Cac diem toan ly hoa: “”;
            cin>>h.t>>h.l>>h.h;
            h.td=h.t+h.l+h.h;
            cout<< “\n Ho ten: “<< ts[1].ht;
            cout<<”\n Tong diem: “<<ts[1].td;
            getch();
        }
    1.3. Hằng tham chiếu (const)
    Hằng tham chiếu được khai báo theo mẫu:
    int n=10;
    const int &r=n;
    Cũng như biến tham chiếu, hằng tham chiếu có thể tham chiếu tới một biến hoặc một hằng. Ví dụ:
    int n=10;
    const int &r=n;// hằng tham chiếu r tham chiếu tới biến n
    cónt int &s=123; // hằng tham chiếu tham chiếu tới hằng 123
    Sự khác nhau giữa biến và hằng tham chiếu ở chỗ: Không cho dung hằng tham chiếu để làm thay đổi giá trị của vùng nhứ mà nó tham chiếu.
    Ví dụ:
    int y=12,z;
    const int &py=y; // hằng tham chiếu py tham chiếu tới biến y.
    y++; // đúng
    z=2*py;// đúng z=26
    cout<<y<<” “<<py; // in ra 13 13
    py=py+1; // sai , trình biên dịch sẽ thong báo lỗi:
    // Cannot modify a const object
    Cách dung: Hằng tham chiếu cho phép sử dụng giá trị chưa trong một vùng nhứ, nhưng không cho phép thay đổi giá trị này.
    Hằng tham chiếu thường được sử dụng làm đối của hàm để cho phép hàm sử dụng giá trị của các tham số trong lời gọi hàm, nhưng tránh không làm thay đổi giá trị của các tham số

  8. #8
    Ngày gia nhập
    12 2006
    Bài viết
    72

    Nhớ diễn đàn quá, hôm nay phải post một bài mới được
    Vâng hôm nay em xin gửi đến mọi người bài tiếp theo của chúng ta
    §2. TRUYỀN GIÁ TRỊ CHO HÀM THEO THAM CHIẾU
    2.1. Hàm trong C
    Trong C chỉ có một cách truyền dữ liệu cho hàm theo giá trị:
    + Cấp phát vùng nhớ cho các đối.
    + Gán giá trị các tham số trong lời gọi hàm cho các đối sau đó hàm làm việc trên vùng nhớ của các đối chứ không lien quan gì đến các tham số.
    Như vậy chương trình sẽ tạo ra các bản sao (các đối) của các tham số và hàm sẽ thao tác trên các bản sao này, chứ không làm việc trực tiếp với các tham số. Phương pháp này có 2 nhược điểm chính:
    Tốn kém về thời gian và bộ nhớ vì phải tạo ra các bản sao. Không thao tác trực tiếp trên tham số, vì vậy không làm thay đổi giá trị các tham số
    2.2. Truyền giá trị hàm theo tham chiếu
    Trong C++ cung cấp them cách truyền dữ liệu cho hàm theo tham chiếu bằng cách dung đối là biến tham chiếu hoặc đối là hằng tham chiếu. Cách này có các ưu điểm:
    Không cần tạo ra các bản sao của các tham số, do đó tiết kiệm bộ nhớ và thời gian chạy máy. Hàm sẽ thao tác trực tiếp trên vùng nhớ của các tham số, do đó dễ dàng thay đổi giá trị của các tham số khi cần.
    2.3. Mối quan hệ giữa đối và tham số trong lời gọi hàm
    Nếu đối là biến hoặc hằng tham chiếu kiểu K thì tham số( trong lời gọi hàm) phải là biến hoặc phần tử mảng kiểu K. Ví dụ:
    + Đối là biến hoặc hằng tham chiếu kiểu double, thì tham chiếu là biến hoặc phần tử mảng kiểu double
    + Đối là biến hoặc hằng tham chiếu kiểu cấu trúc, thì tham số là biến hoặc phần tử mảng kiểu cấu trúc
    2.4. Các chương trình minh hoạ
    /*
    Chương trình được tổ chức thành 3 hàm:
    Nhập dãy số double
    Hoán vị 2 biến double
    Sắp xếp dãy số double theo thứ tự tăng dần
    Chương trình sẽ nhập 1 dãy số và in ra dẫy sau khi sắp xếp thamchieu1.cpp
    */

    Code:
    #include<iostream.h>
    #include<conio.h>
    void nhap(double *a,int n)
       {
          for(int i=1;i<=n;i++)
                {
                  cout<<”\n nhap so thu “<<i;
                  cin>>a[i];
                }
    void hv(double &x,double &y)
        {
           double tg=x; x=y; y=tg;
        }
    void sapxep(double *a, int n)
       {
         for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
              if(a[i]>a[j]) hv(a[i],a[j]);
       }
    void main()
       {
         double a[100]; int n;
         cout<<”\n nhap so phan tu : “; cin>>n;
         nhap(a,n);
         sapxep(a,n);
         cout<<”\n cac phan tu duoc sap xep lai”;
         for(int i=1;i<=n;i++)
          cout<<”\n\n “<<a[i];
         getch();
      }
    Chương trình 2
    /*
    Chương trình gồm các hàm:
    Nhập 1 dãy cấu trúc( mỗi cấu trúc chứa dữ liệu 1 thí sinh)
    Hoán vị 2 biến cấu trúc
    sắp xếp dẫy thí sinh theo thứ tự giảm dần của tổng điểm
    In 1 cấu trúc (in họ tên và tổng điểm)
    Chương trình sẽ nhập dữ liệu 1 danh sách các thí sinh, nhập điểm chuẩn và in danh sách thí sinh đã trúng tuyển thamchieu2.cpp
    */

    Code:
    #include<iostream.h>
    #include<conio.h>
    #include<iomanip.h>
    struct TS 
      {
        char ht[25];
        float t,l,h,td;
      };
    void ints(const TS &ts)
       {
         cout<<setiosflags(ios::showpoint)<<setprecission(1);
         cout<<”\n Ho ten: “<<setw(20)<<ts,ht<<setw(6)<<ts.td;
       }
    void nhapsl(TS *ts,int n)
       {
         for(int i=1;i<=n;i++)
            {
              cout<<”\n thi sinh thu “<<i<<”:”;
              cout<<”\n ho ten: “;
              cin.ignore(1);
              cin.get”(ts[i].ht,25);
              cout<<”\n cac diem toan ly hoa “;
              cin>>ts[i].t>>ts[i].l>>ts[i].h;
              ts[i].td=ts[i].t+ts[i].l+ts[i].h;
            }
      }
    void hvts(TS &ts1,TS &ts2)
        {
          TS tg=ts1; ts1=ts2;ts2=tg;
        }
    void sapxep(TS *ts,int n)
        {
          for(int i=1;i<=n;i++)
             for(int j=i+1;j<=n;j++)
                if(ts[i].td<ts[j].td)
                   hvts(ts[i],ts[j]);
        }
    void main()
        {
           TS ts[100];
           int n,i;
           clrscr();
           cout<<”\n so thi sinh: “;
           cin>>n;
           nhapsl(ts,n);
           sapxep(ts,n);
           float dc;
           cout<<”\n\n diem chuan: “;
           cin>>dc;
           cout<<”\n danh sach trung tuyen”;
           for(i=1;i<=n;i++)
             if(ts[i].td>=dc)
               ints(ts[i]);
             else break;
               getch();
      }
    /*
    Chương trình sau gồm các hàm:
    Nhập 1 ma trận thực cấp mxn
    In 1 ma trận thực dưới dạnh bảng
    Tìm phần tử lớn nhất và nhỏ nhất của dãy số thực
    Chương trình sẽ nhập 1 ma trận, in ra ma trận vừa nhập và in ra các phần tử lớn nhất và nhỏ nhất trên mỗi hang của ma trận thamchieu3.cpp

    */
    Code:
    #include<ỉoteam.h>
    #include<iomanip.h>
    #include<conio.h>
    #include<stdio.h>
    void nhapmt(float a[20][20],int m,int n)
       {
         for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            {
              cout<<”\n\n a[“<<i<<”]”<<”[“<<j<<”]=  ”;
              cin>>a[i][j];
            }
      }
    void inmt(float a[20][20],int m,int n)
       {
         cout<<setiosflags(ios::showpoint)<<setprecision(1);
         for(int i=1;i<=m;i++)
            for(j=1;j<=n;j++)
              {
                if(j==1) cout<<”\n”;
                cout<<setw(6)<<a[i][j];
             }
       }
    void maxminds(float *x,int n,int &vtmax,int &vtmin)
       {
         vtmax=vtmin=1;
         for(int i=2;i<=n;i++)
           {
             if(x[i]>x[vtmax]) vtmax=i;
             if(x[i]<x[vtmin]) vtmin=i;
           }
       }
    void main()
      {
        float a[20][20]; int m,n;
        clrscr();
        cout<<”\n so hang va so cot cua ma tran: “;
        cin>>m>>n;
        nhapmt(a,m,n);
        clrscr();
        inmt(a,m,n);
        float *p=(float*)a;
        int vtmax,vtmin;
        for(int i=1;i<=m;i++)
          {
            p=((float*)a)+i*20;
            maxminds(p,n,vtmax,vtmin);
      printf(“\n hang %d phan tu max= %6.1f tai cot                               %d”,I,p[vtmax],vtmin); 
            printf(“\n phan tu min= %6.1f tai cot %d”,p[vtmin],vtmin);
          }
    
        getch();
      }
    Hẹn gặp lại các bác trong những bài tiếp theo.
    Chúc mọi người vui vẻ!

  9. #9
    Ngày gia nhập
    12 2006
    Bài viết
    72

    Các bác ạ, tìm hiểu biến tham chiếu khá ngán ngẩm rồi, hôm nay em post nôt phần còn lại rồi ta chuyển sang phần mới.
    §3. HÀM TRẢ VỀ CÁC THAM CHIẾU
    Hàm có thể có kiểu tham chiếu và trả về giá trị tham chiếu. Khi đó có thể dung hàm để truy nhập đến một biến hoặc một phần tử mảng nào đó. Dưới đây là một số ví dụ
    Ví dụ1. Trình bày một hàm trả về một tham chiếu tới một biến toàn bộ. Do đó có thể dung hàm để truy nhập đến biến này. Hamthamchieu1.cpp
    Code:
    #include<iostream.h>
                #include<conio.h>
                int z;
                int &f() // hàm trả về bí danh của biến toàn bộ z
                  {
                     return z;
                  }
                void main(void)
                   {
                     clrscr();
                     f()=50; //z=50
               cout<<”\n z= “<<z;
               getch();
             }
    Ví dụ 2: trình bày 1 hàm trả về bí danh của một biến cấu trúc toàn bộ. Khác với ví dụ trên ở đây không dung hàm một cách trực tiếp mà ta gán hàm cho một biến tham chiếu,sau đó dung biến tham chiếu này để truy nhập tới biến cấu trúc toàn bộ. hamthamchieu2.cpp
    Code:
    #include<iostream.h>
    #include<conio.h>
    stuct TS
      {
        char ht[25];
        float t,l,h,td;
      };
    TS ts;
    TS &f()
       {
         return ts;
       }
    void main() 
      {
        TS &h=f(); // h tham chiếu đến biến ts
         cout<<”\n Ho ten: “;
        cin.get(h.ht,25);
        cout<<”\n Cac diem toan li hoa : “;
        cin>>h.t>>h.l>>h.h;
        h.td=h.t+h.l+h.h;
        cout<<”\n ho ten: “<<ts.ht;
        cout<<”\n Tong diem: “<<ts.td;
        getch();
      }
    Ví dụ 3: Trình bày hàm trả về bí danh của một phần tử mảng cấu trúc toàn bộ. Hàm sẽ kiểm tra xem chỉ số của mảng có vượt ra ngoài miền qui định hay không. Sau đó dung hàm này để truy nhập đến phần tử mảng cấu trúc
    Code:
    #include<iostream.h>
    #include<conio.h>
    #include<stdlib.h>
    struct TS
         {
            char ht[25];
      
            float t,l,h,td;
         }
    TS *ts;
    void cap_phat_bo_nho_nhapsl(int n)
       {
         ts=new TS[n+1];   
         if(ts==NULL)
           {
             cout<<”\n loi cap phat bo nho “;
             exit(1);
           }
         for(int i=1;i<=n;i++)
           {
             TS &h=ts[i];
             cout<<”\n thi sinh thu “<<i;
             cout<<”\n ho ten : “;
             cin.ignore(1);
             cin.get(h.ht,25);
             cout<<”\n cac diem toan li hoa: “;
             cin>>h.t>>h.l>>h.h;
             h.td=h.t+h.l+h.h;
           }
       }
    TS &f(int i,int n)  
            {
               if(i<1|| i>n)
                {
                  cout<<”\n chi so mang khong hop le”;
                   exit(1);
                }
              return ts[i];
            }
          void main()
              {
                int i,n;
               cout<<”\n so thi sinh: “;
               cin>>n;
               cap_phat_bo_nho_nhapsl(n);
               while(1)
                  {
                    cout<<”\n\n can xem thi sinh thu may? “;
                    cout<<”\n chon so tu 1 den “<<n<<”(bam sai de ket thu chuong trinh)”;
                    cin>>i;
                    TS &h=f(i,n);
                     cout<<”\n ho ten: “<<h.ht;
                     cout<<”\n tong diem: “<<h.td;
                 }
              }

  10. #10
    Ngày gia nhập
    12 2006
    Bài viết
    72

    Bài này tìm hiểu về đối có giá trị mặc định, rất hay đó.
    § 4. ĐỐI CÓ GIÁ TRỊ MẶC ĐỊNH
    4.1. Thế nào là đối có giá trị mặc định
    Một trong các khả năng mạnh của C++ là cho phép xây dựng hàm với các đối có giá trị mặc định. Thông thường số tham số trong lời gọi hàm phải bằng số đối của hàm. Mối đối sẽ được khởi gán giá trị theo tham số tương ứng của nó. Trong C++ cho phép tạo ra các giá trị mặc định cho các đối. Các đối này có thể có hoặc không có tham số tương ứng trong lời gọi hàm. Khi không có tham số tương ứng, đối được khởi gán bằng giá trị mặc định.
    Ví dụ: hàm delay với đối số mặc định được viết theo 1 trong 2 cách như sau:
    Cách 1: (không khai báo nguyên mẫu)
    void delay(int n=1000)
    {
    for(int i=0;i<n;i++)
    ;
    }
    Cách 2 (có khai báo nguyên mẫu) ;
    void delay(int n=1000)
    void delay(int n)
    {
    for(int i=0;i<n;i++)
    ;
    }
    Cách dung:
    + cung cấp giá trị cho đối n( có tham số trong lời gọi hàm)
    delay(5000); // đối n=5000
    + sử dụng giá trị mặc định của đối( không có tham số trong lời gọi hàm)
    delay(); // đối n=1000
    4.2. Quy tắc xây dựng hàm với đối mặc định
    + các đối mặc định phải là các đối cuối cùng tính từ trái sang phải. Giả sử có 5 đối theo thứ tự từ trái sang phải là
    d1,d2,d3,d4,d5
    Khi đó
    nếu 1 đối mặc định thì phải là d5
    nếu 2 đối mặc định thì phải là d5,d4
    ….
    Các ví dụ sai:
    d3 và d4 mặc định( d5 cũng phải là mặc định)
    d3 và d5 mặc định( d4 cũng phải là mặc định)
    + Khi xây dựng hàm, nếu sử dụng khai báo nguyên mẫu thì các đối mặc định cần được khởi gán trong nguyên mẫu, ví dụ:
    // Khởi gán giá trị mặc định cho 3 đối mặc định d3,d4,d5
    void f(int d1,float d2, char *d3=”HA NOI”,int d4=100,double d5=3.14);
    void f(int d1,float d2,char d3,int d4,double d5)
    {
    // các câu lệnh trong than hàm
    }
    Không được khởi gán lại đối mặc định trong dòng đầu của định nghĩa hàm. Nếu vi phạm điều này thì chơng trình dịch sẽ báo lỗi.
    + Khi xây dựng hàm nếu không khai báo nguyên mẫu, thì các đối mặc định được khởi gán trong dòng đầu của định nghĩa hàm,ví dụ:
    // khởi gán giả trị cho 3 đối mặc định d3,d4,d5
    void f(int d1,float d2,char *d3=”HANOI”,int d4=100,double d5=3.14)
    {
    //các câu lệnh có trong than hàm
    }
    +Giá trị dung để khởi gán cho đối mặc định
    Có thể dung hằng ,các biến toàn bộ, các hàm để khởi gán cho đối mặc định,ví dụ:
    int MAX=1000;
    void f(int n,int m=MAX,int xmax=getmaxx(),
    int ymax=getmaxy();
    4.3. Cách sử dụng hàm có đối mặc định
    Lời gọi hàm cần viết như sau:
    Các tham số thiếu vắng trong lời gọi hàm phải tương ứng với các đối mặc định cuối cùng(tính từ trái sang phải)
    Nói cách khác: Đã dung giá trị mặc định cho một đối(tất nhiên là phải đối mặc định ) thì cũng phải sử dụng đối mặc định cho các đối còn lại.
    Ví dụ hàm có 3 đối mặc định:
    void f(int d1,float d2,char *d3=”HANOI”,int d4=100,
    double d5=3.14);
    thì các lời gọi hàm sau đúng:
    f(3,3.4,”ABC”,10,1.0);// đầy đủ tham số
    f(3,3.4,”ABC”); // Thiếu 2 tham số cuối
    f(3,3,4); // Thiếu 3 tham số cuối
    và các lời gọi sau là sai:
    f(3); // thiếu tham số cho đối không mặc định
    f(3,3.4,,10); // đã dung giá trị mặc định cho d3 thì cũng phải dung giá trị mặc định cho d4 và d5
    4.4. Các ví dụ
    Hàm ht dưới đây dung để hiển thị chuỗi kí tự dc trên n dòng màn hình. Các đối dc và n đều mang giá trị mặc định
    Code:
    #include<iostream.h>
    #include<conio.h>
    void ht(char *dc=”HANOI”,int n=10)
    void ht(char *dc,int n)
        {
          for(int i=1;i<=n;i++)
            Cout<<”\n\n”<<dc;
        }
    void main()
       {
         ht();
         getch();
         clrscr();
         ht(“abc”,3);getch();clrscr();
         ht(“def”);
         getch();
      }
    Ví dụ dưới đây trình bày hàm hiển thị một chuỗi str trên màn hình đồ hoạ, tại vị trí (x,y) và có màu m. Các đối x,y và m là mặc định.Dùng các hàm getmaxx() và getmaxy()để khởi gán cho x,y. Dùng hằng RED gán cho m
    Code:
    #include<conio.h>
    #include<graphics.h>
    void hiendc(char *str,int x=getmaxx()/2,int y=getmaxy/2,int m=RED);
    void hiendc(char *str,int x,int y,int m)
        {
          int mau_ht=getcolor();//lưu màu hiện tại
          setcolor(m);
          outtextxy(x,y,str);
        setcorlor(mau_ht); //khôi phục màu hiện tại
      }
    void main()
        {
          int mh=0,mode=0;
          innigraph(&mh,&mode,””);
          setbkcolor(BLUE);
          hiendc(“HELLO”);
          hiendc(“ CHUC MUNG”,1,1);
          hiendc(“CHAO”,1,400,YELLOW);
          getch();
        }
    Ví dụ dưới đây sẽ trình bày hàm tính tích phân xác định gồm 3 đối: f là hàm cần tính tích phân, a và b là các cận dưới, trên(a<b). Cả 3 đối f,a và b đều mặc định. Giá trị mặc định của con trỏ hàm f là địa chỉ của hàm bp( bình phương), của a=0 và của b=1.
    Code:
    #include<conio.h>
    #include<iotsream.h>
    #include<iomanip.h>
    #include<math.h>
    double bp(double x);
    double tp(double (*f)(double)=bp,double a=0.0,double b=1.0);
    double bp(double x)
        {
          return x*x;
       }
    double tp(double (*f)(double),double a,double b)
       {
         int n=1000;
         double s=0, h=(b-a)/n;
         for(int i=0;i<n;i++)
           s+=f(a+i*h+h)+f(a+i*h);
         return s*h/2;
      }
    void main()
       {
         clrscr();
         cout<<setiosflags(ios::showpoint)<<setprecision(2);
         cout<<”\n Tich phan tu o den 1 cua x*x= “<<tp();
         cout<<”\n tich phan tu 0 den 1 cua exp(x)= “<<tp(exp);
         cout<<”\n tich phan tu 0 den PI/2 cua sin(x)= “<<tp(sin,0,3.14/2);
         getch();
      }

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

  1. Bán Chung Cư Văn Phú Victoria Văn Phú 96m2 16tr/m2
    Gửi bởi nguyentiennhien trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 23-11-2012, 01:11 PM
  2. Biệt thự văn phú, liền kề văn phú, căn góc, hướng đẹp, giá ưu đãi
    Gửi bởi ephat_tt86 trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 14-12-2011, 09:12 AM
  3. Liền kề văn phú, dự án văn phú, giá bán = gốc + chênh thấp
    Gửi bởi ephat_tt86 trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 07-12-2011, 11:40 AM
  4. Liền kề Văn Phú TT28, bán Liền kề Văn Phú TT2, TT9, TT12, TT33
    Gửi bởi datphat191 trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 20-10-2011, 12:10 PM
  5. Cần Bán Chung Cư Văn Phú Victoria- Văn Phú Hà Đông
    Gửi bởi huybm90 trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 1
    Bài viết cuối: 03-10-2011, 10:42 AM

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