C++ ダイナミックオープンスペース
2022-02-14 03:03:48
<スパン C++のダイナミックオープンスペースです。
<スパン 1. 可変長一次元配列
ここでいう可変長配列とは、コンパイル時に配列の長さを決定できず、プログラムが実行時に動的にメモリ空間を確保する必要がある配列のことです。可変長配列の最も単純な実装は可変長一次元配列で、次のようにします。
//ファイル名:array01.cpp
#include<iostream>
名前空間std.を使用する
int main()
{
int lenです。
cin>>len;
// ポインタ p を使って、長さ len*sizeof(int) の新しい動的割り当てメモリ空間を指定します。
int *p=new int[len];
<スパン ...........
delete[] p;
は 0 を返します。
}
int *p=new int[len]; という行に注意してください、このようなことはできません。
int p[len];
C++コンパイラは、この形式で配列を宣言する場合、コンパイル時に配列のサイズを決定する必要があるため、lenのサイズが決定できないというエラーを報告します。そして、このように動作しないのです。
int p[]=new int[len];
コンパイラは、int* 型を int[] 型に変換することはできない、なぜならメモリのセクションを new で開くとそのメモリのセクションの最初のアドレスが返されるので、そのアドレスをポインタに代入しなければならない、だから int *p=new int[len] としなければならない、と言うでしょう。
array01.cppは可変長の一次元配列を実装していますが、ポインタpを書き落とすことに注意して、newで開放されたメモリ空間をプログラムが解放するように習慣付けるとよいでしょう。
もちろん可変長配列は、C++標準テンプレートライブラリ(STL)のベクトルを使って実装することも可能です。
//ファイル名:array02.cpp
#include<iostream>
#include<vector>
名前空間std.を使用する
int main()
{
int lenです。
cin>>len;
vector<int> array(len);// 長さ可変の配列を宣言する。
for(int i=0;i<len;i++)
{
array[i]=i;
cout<<array[i]<<"\t";
}
は 0 を返します。
}
ここでいう可変長配列は、javaのjava.utilパッケージのvectorやC#のArrayListを連想させますが、これらの言語でも可変長配列を実装することが可能です。ただし、C++のベクターには、C#のように占有したメモリ空間を回収するマネージドガベージコレクション機構はありませんが、ベクターを使い終わったら、~vector() デストラクタを呼び出してメモリを解放することが可能です。
<スパン 2. 可変長n次元配列
可変長n次元配列は実装が少し難しいですが、工学やソフトウェア設計の用途でよく使われるので、ここでは可変長2次元配列を中心に説明しますが、可変長n次元配列も同様の方法で実装することが可能です。まず、C言語で可変長2次元配列を実装する古典的な例から見ていきましょう。
//ファイル名:array03.c
#include <stdio.h>
#include <malloc.h>
void main()
{
int x,y,i,j;
float **a,*b;
printf("解こうとしている連立一次方程式の行数xを入力してください。x=")です。
scanf("%d",&x);
printf("Please enter column number y of the system of linear equations you are solving: y=")。
scanf("%d",&y);
a=(float **)malloc(sizeof(float *) *x);
b=(float *)malloc(sizeof(float) *x);
for(i=0;i<x;i++)
{
*(a+i)=(float *)malloc(sizeof(float) *y)。
}
/*データ読込*/
printf("係数の値を行の順番に入力してください(%d項目): ",x*y)。
for(i=0;i<=x-1;i++)
for(j=0;j<=y-1;j++)
scanf("%f",&a[i][j]);
printf("定数の値を列順に入力してください(全部で%d項目): ",x)。
for(j=0;j<=x-1;j++)
scanf("%f",&b[j]);
printf("The augmented matrix of your input system of equations is: \n");
for(i=0;i<=x-1;i++)
{
for(j=0;j<=y-1;j++)
printf("%.5f ",a[i][j])を実行します。
printf("%.5f ",b[i])を実行します。
printf("\n");
}
free(b)です。
for(i=0;i<x;i++)
free (*(a+i));
}
<スパン では、C++で実装するにはどうすればよいのでしょうか。C++では、newとdeleteという演算子で動的に領域を開放・解放することができます。newはC言語のmalloc関数、deleteはC言語のfree関数に似ています。C++で可変長の2次元配列を実装するには、ダブルポインタ方式とSTLのベクタ(ベクトル)方式の2つの方法があります。
まず、ダブルポインタ方式を紹介します。ダブルポインタとは、ポインタのように見えるポインタのことで、例えば、次のような配列を宣言します。
int **p = new int*[num1];
そして、各 *p (合計 num1 *p) に対して、1組のメモリ空間が要求されます。
for(int i=0; i<num1; ++i)
p[i] = new int[num2];
ここで、num1 は配列の行数、num2 は配列の列数です。このテストのソースプログラムは次のとおりです。
//ファイル名:array04.cpp
#include <iostream>
#include <iomanip>
名前空間std.を使用する
int main()
{
int num1,//行数
num2;//列の数
cout<<"Please enter number for row and column: "<<endl.を入力してください。
cin >> num1 >> num2;
// 2次元配列のためのオープンスペース
int **p = new int*[num1];
for(int i=0; i<num1; ++i)
p[i] = new int[num2];
for(int j=0;j<num1;j++)
{
for(int k=0;k<num2;k++)
{
p[j][k]=(j+1)*(k+1) となります。
cout<<setw(6)<<p[j][k]<<':'<<setw(8)<<&p[j][k];
}
cout<<endl;
}
//2次元配列が占有する空間を解放する。
for(int m=0;m<num1;m++)
delete[] p[m];
delete[] p;
は 0 を返します。
}
<スパン 以下は、その実行結果である。
<スパン 行と列の番号を入力してください。
<スパン 4 5
1:004915f0 2:004915f4 3:004915f8 4:004915fc 5:00491600
2:00491180 4:00491184 6:00491188 8:0049118C 10:00491190
3:00491140 6:00491144 9:00491148 12:0049114C 15:00491150
4:00491100 8:00491104 12:00491108 16:0049110C 20:00491110
<スパン 任意のキーを押して続行
プログラムリストarray04.cppには、割り当てられたメモリ空間ユニットのアドレスが表示されています。このように,配列は動的に確保されるため,異なる行の配列要素のアドレスは異なるnewで確保されるため,配列行間のアドレス空間は不連続となります.また、各行の列間のアドレス空間は連続しています。
では、ベクトルを使った2次元配列はどのように実装するのでしょうか。以下にそのソースプログラムを示します。
//ファイル名:array05.cpp
#include <iostream>
#include <vector>
#include <iomanip>
名前空間std.を使って
int main()
{
int i,
j,
m, //行数
n; //列の数
cout << "m,nの入力値:"。
cin>>m>>n;
//次の行に注意してください: vector<int の後に、2つの ">" の間にスペースがあること! さもないと、">"のオーバーロードとみなされます。
vector<vector<int> > vecInt(m, vector<int>(n));
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
vecInt[i][j] = i*j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
cout<<setw(5)<<vecInt[i][j]<<":"<<setw(9)<<&vecInt[i][j];
cout<<endl;
}
は 0 を返します。
}
<スパン 以下は、その実行結果である。
m,n の入力値:3 4
0: 00491180 0: 00491184 0: 00491188 0: 0049118C
0: 00491140 1: 00491144 2: 00491148 3: 0049114C
0: 00491100 2: 00491104 4: 00491108 6: 0049110C
<スパン 任意のキーを押して続行
このように、vectorの要素に対するメモリの割り当ては、ダブルポインタで実装された2次元配列と同じ性質を持っていることがわかります。しかし、ダブルポインタを使うよりもベクトルの方がはるかに単純で、メモリ領域を確保する際の安全性が高く、配列の初期化コードも単純なので、STLベクトルを使って可変長多次元配列を実装することをお勧めします。(以下は可変長の3次元配列です)
//ファイル名:array06.cpp
#include <iostream>
#include <vector>
#include <iomanip>
名前空間std.を使用する
int main()
{
int i,
j,
k,
m, //一次元の座標
n, //2次元座標
l; //三次元座標
cout << "入力値 for m,n,l:";
CIN>>M>>N>>L.
vector<vector<int> > vecInt(m, vector<vector<int> >(n, vector<int>(l))) を使用します。
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
for (k = 0; k < l; k++)
vecInt[i][j][k] = i+j+k;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
for(k = 0; k<l; k++)
cout<<setw(5)<<vecInt[i][j][k]<":"<<setw(9)<&vecInt[i][j][k] です。
cout<<endl;
}
cout<<endl;
}
は 0 を返します。
}
<スパン 走った結果
m,n,l の入力値:2 3 4
0: 00492fe0 1: 00492fe4 2: 00492fe8 3: 00492fec
1: 00492fa0 2: 00492fa4 3: 00492fa8 4: 00492fac
2: 00492f60 3: 00492f64 4: 00492f68 5: 00492f6c
1: 00492ec0 2: 00492ec4 3: 00492ec8 4: 00492ecc
2: 00492e80 3: 00492e84 4: 00492e88 5: 00492e8c
3: 00492e40 4: 00492e44 5: 00492e48 6: 00492e4c
から取得した。 http://hi.baidu.com/ouyangyuanling/item/dbf618eab47ef7c4baf37d4f
関連
-
undefinederror: 'dynamic_cast' の前に unqualified-id を指定する必要があります。
-
error: 'vector' does not name a type
-
C++-コラムフィッティングフィットシリンダー
-
コンパイルエラー: 制御が非ボイド関数の末尾に達する可能性がある
-
34:5: エラー: 制御が非ボイド関数の終わりに達する可能性がある [-Werror,-Wreturn-type] エラー解析
-
エラー: "***"の前にイニシャライザーがあります。
-
警告を表示します。ISO C++は文字列定数を'char*'に変換することを禁じています[-Write-strings]。
-
c++ 11 random ライブラリの簡単な使い方
-
C++11 ランダムライブラリ乱数
-
C++ inet_pton, inet_ntop 関数
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Linux の 'pthread_create' への未定義参照問題を解決しました。
-
C++11での移動セマンティクス(std::move)と完全な前進(std::forward)。
-
c++ エラー: 'map' は型名ではありません。
-
gcc/g++ コンパイル時のエラー解析で期待される型指定子の前に
-
C++のコンパイルエラーで修飾子が破棄される [-fpermissive] 。
-
不完全なクラス型へのポインタが許可されていないのですが、どのようなエラーですか?
-
C++ [エラー] 'std::string {aka std::basic_string<char>}' を 'char*' に変換できないエラー
-
gccコンパイルエラーの一覧
-
C++プロジェクトのコンパイル時に再定義の多重定義問題を解決する
-
ベクトル添え字が範囲外のコンテナの使用、その他類似のエラー