西工大《C++プログラミング》——(三)

26096 ワード

文書ディレクトリ
  • 第13回:配列の定義と
  • の使用
  • 第14講:配列と関数
  • 第15講:文字列の処理
  • 第16講:配列の応用
  • 第17講:ポインタの定義と使用
  • 第18講:ポインタと配列
  • 第19講:ポインタと関数
  • 13番目:配列の定義と使用
  • 次元配列の定義、メモリ形式(連続記憶)、初期化.
  • 静的配列と動的配列の初期値.
  • 二次元配列の定義、メモリ形式(行ごとに連続的に格納)、初期化.
  • 多次元配列の参照.

  • 14番目:配列と関数
  • 配列要素を関数パラメータとして使用します.
  • 配列全体が関数パラメータとして機能し、配列のヘッダアドレスが伝達されるため、実パラメータと形パラメータは同じオブジェクトとなる.
  • 配列が関数パラメータである場合、コンパイラは配列の長さをチェックしないため、配列のヘッダアドレスを関数に入力する場合、実パラメータ配列の長さを表すために別のパラメータを入力する必要があることが多い.ただし、多次元配列の1次元を除く残りの次元の長さは省略できません.そうしないと、配列のベースタイプを特定できません.

  • 第15回:文字列の処理
  • コンパイラは、文字列定数をコンパイルすると、その末尾に自動的に終了符'\0'を付ける.
  • 【文字列処理関数】
  • 【文字列オブジェクト】:クラスはstringヘッダファイルで定義され、文字列オブジェクトは\0の終端記号を必要とせず、動的メモリ管理を採用し、メモリの境界をチェックします.
  • 文字列オブジェクトは、文字列処理関数を呼び出すことなく、文字列定数を直接割り当てることができます.
  • 文字列オブジェクトの操作:付与演算、接続演算、関係演算.

  • 16番目:配列の応用
  • 配列でソート問題を解決します:ソートを交換し、ソートを選択します.
  • 配列で検索問題を解決します:順序検索、二分検索.
  • 【二分ルックアップ例】:
  • #include 
    using namespace std;
    int BinarySearch(int A[], int n, int find){
    	int low, upper, mid, result=-1;
    	low = 0, upper = n-1;
    	while(low<=upper){
    		mid = low +(upper-low)/2;	//    low+upper  
    		if(A[mid]<find)
    			low = mid+1;
    		else if(A[mid]>find)
    			upper = mid-1;
    		else
    			result = A[mid];	// result     
    	}
    	return result;
    }
    
    

    17番目:ポインタの定義と使用
  • データの書き込みと読み出しはいずれもメモリと関連しており、ポインタタイプはメモリアドレスを処理するデータタイプである.ポインタはプログラムの効率を高めるだけでなく、ある関数を別の関数のローカル変数にアクセスさせることができるので、ポインタは関数がデータ交換を行うために不可欠なツールです.
  • プログラムのデータオブジェクトは、ライフサイクル中に常に一定の記憶空間を占有し、特定の記憶位置を有する.オブジェクト名によるアクセスオブジェクトは直接アクセス、ポインタによるアクセスオブジェクトは間接アクセスです.
  • ポインタの特殊性のため、ポインタの初期化と付与は一定の制約を受け、以下の4つの値のみである:
  • 0定数式
  • int a, z=0;
    int *p1=a;	//   ,         
    p1 = z;		//            ,     0
    p1 = 4000; 	//   ,           
    p1 = null; 	//   
    p1 = 0; 	//   
    
    
  • 型同一のオブジェクトのアドレス値
  • int a, *p1;
    float b, *p2;
    p1 = &a; 	//   
    p1 = &bl;	//   
    p2 = &b;	//   
    
  • ベースタイプの同じポインタ変数の値
  • オブジェクト記憶空間の次の有効アドレス
  • 【ポインタの有効性】:ポインタが記憶領域を特定するオブジェクトを指す場合は有効ポインタであり、そうでない場合は無効ポインタである.
  • 【無効なポインタ】:0値ポインタ(空のポインタ);初期化されていない、値が割り当てられていない、または演算後に未知のオブジェクトを指すポインタ.オブジェクトが解放された後も値が変わらないポインタを指します.
  • 【ポインタ演算】:ポインタが連続記憶空間に作用してこそ意味があり、例えばポインタ加減整数、同型ポインタ減算、ポインタ間の関係演算である.
  • 【ポインタの制限】:
  • const int a=10, b=20;
    const int *p;
    p = &a;
    p = &b;
    *p = 12;	//   ,*p    
    
  • constオブジェクトのアドレスを非constベースタイプのポインタ変数に割り当てるのはエラーです.
  • const double pi=3.14;
    double *p=&pi;	//   ,p const  
    const double *ptr=&pi;	//   ,ptr const   
    
  • は、const以外のオブジェクトのアドレスをconstベースタイプのポインタ変数に割り当てることを可能にするが、constベースタイプのポインタによって、その指すconst以外のオブジェクトの値を変更することはできない.const は、実パラメータを読み取り専用に制限するために関数パラメータによく使用され、プログラムの堅牢性を向上させることができる.
  • const double pi=3.14;
    const double *p=&pi;	//   
    double f=3.14;	// f  const  
    p = &f;	//   
    f = 3.14159;	//   
    *p = 3.141;	//   ,    const              
    
  • constポインタ:ポインタ自体は値を変更できませんが、その指す変数は値を変更できます.
  • int a=10, b=20;
    int *const p=&a;	//         
    p = &b;	//   ,p    
    p = p;	//   ,p    
    p++;	//   ,p    
    *p = 2019;	//   
    
    

    18番目:ポインタと配列
  • C++は、配列名が配列そのものを表すとともに、配列全体のアドレスを表すか、その最初の要素のアドレス値を表すかを規定している.配列名は定数です.
  • ポインタのベースタイプは、そのポインタが指すオブジェクトのタイプと一致する必要があります.
  • C++はオブジェクトへのアクセスを拡張しています.参照アクセスです.
  • 参照は、オブジェクトの別名であり、いずれもconstタイプであり、その宣言形式は & = である.
  • 参照は初期化され、有効なメモリオブジェクトを参照できません.初期化後、参照関係を変更することはできません.指定したタイプの参照は、他のタイプのオブジェクトに初期化できません.リファレンスの初期化は、リファレンスに付与された値とはまったく異なります.
  • int &r;	//     ,  
    int x, &ref=x, y;	//   
    int &ref = y;	//   
    //*******//
    int x;
    int &r=x;	//    ,r x   
    r = 100;
    //******//
    int x, &r=x;
    int *p1=&x;	// p1  x
    int *p2=&r;	// p2  r,     x
    

    第19回:ポインタと関数
  • C++拡張参照タイプは主に関数パラメータのタイプを拡張するためであり、これにより関数パラメータ伝達は3つの方式に増加した:伝達オブジェクト自体、伝達オブジェクトのポインタ、伝達オブジェクトの参照(この方法はポインタを関数パラメータとして使用するよりも明確で簡潔である).
  • #include
    using namespace std;
    void swap(int &a, int &b){
        int t;
        t = a;
        a = b;
        b = t;
    }
    int main(){
        int x=3, y=4;
        swap(x,y);
        cout<<x<<","<<y<<endl;
    
        return 0;
    }
    
  • 関数は、参照を返す、すなわち、入力されたエンティティ自体を返すので、関数が返す参照は左の値とすることができる.
  • #include
    using namespace std;
    //       ,          
    int *fun1(int *a, int *b){
        return (*a>*b)?a:b;
    }
    //       ,      
    int &fun2(int &a, int &b){
        return a>b?a:b;
    }
    int main(){
        int x=3, y=4;
        cout<<x<<","<<y<<endl;
        *fun1(&x, &y) = 5;
        cout<<x<<","<<y<<endl;
        fun2(x, y)=6;
        cout<<x<<","<<y<<endl;
    
        return 0;
    }
    
  • C++は、関数入口アドレスを関数とするポインタ、すなわち関数名が関数であり、関数を表すポインタ(アドレス)を規定する.【これによりプログラム機能の本質は、操作メモリ上でアドレスによって識別するデータであることがわかる】
  • .
    #include
    using namespace std;
    int *fun1(int *a, int *b){
        return (*a>*b)?a:b;
    }
    int main(){
        int x=3, y=4, z;
        int *(f)(int *, int *)=fun1(int *, int *);	 //   ,             
        
        //      ,   ,        ,       
        int *(&fun)(int *, int *)=fun1; 	
        //      ,       
        int *(*funp)(int *, int *)=fun1;	
        
        z = *fun(&x, &y);
        cout<<x<<","<<y<<endl<<z<<endl;
        x = 5;
        z = *funp(&x, &y);
        cout<<x<<","<<y<<endl<<z<<endl;
    
        return 0;
    }
    
  • 関数ポインタは、積分関数を求めるなど、戻り値のタイプが同じ異なる関数を動的に呼び出すためによく使用される.