|
C++の壺・構造体篇
C++の基本テクニックのTipsです。構造体篇では、構造体の基礎的な知識から、構造体同士の演算、関数への適用、動的確保と破棄について記述しています。
| [INDEX]
| ・構造体の基礎 | :: 構造体の宣言 / 構造体の初期化 / 構造体メンバ |
| ・構造体の演算 | :: 構造体のコピー / 構造体配列 / 構造体のポインタ |
| ・構造体と関数 | :: 構造体の引数 / 戻り値としての構造体 |
| ・動的構造体 | :: 構造体の動的確保 / 構造体の破棄 |

構造体では、異なるデータ型の要素(メンバ)を複数持つことができます。この時、変数を同時に宣言することも可能です。また、宣言した後は、データ型と同じように扱うことができ、メンバへのアクセスには ‘ .’ を利用します。
【モデル】 struct タグ名 { 要素1; 要素2; : } (変数1, 変数2, ...);
|
【要素のみ宣言】 struct xdata { int index; char name[64]; } ;
|
【変数も宣言】 struct xdata { int index; char name[64]; } item1, item2 ;
|
【変数を初期化】 struct xdata { int index; char name[64]; } item1 = {0, "John"} , item2 = {1, "Bob"} ;
|
構造体は、配列のように、要素の値を並べることで初期化をすることが可能です。(上例右端参照)。また、クラスのように、関数を定義することもできます(下例参照)。
// 構造体の宣言と初期化
#include <stdio.h> // printf
#include <string.h> // strcpy
#include <conio.h> // getch
// xdata構造体
struct xdata
{
int index;
char name[64];
} ;
// main 関数
void main()
{
xdata x1 = {77, "Picasso"};
printf("%d, %s\n", x1.index, x1.name);
xdata x2;
x2.index = 88;
strcpy(x2.name, "Chagall");
printf("%d, %s\n", x2.index, x2.name);
if (getch()) return;
}
|
// 構造体とメンバ関数
#include <stdio.h> // printf
#include <conio.h> // getch
// point構造体
struct point {
int X;
int Y;
void init() { X = Y = 0;}
} ;
// main 関数
void main() {
point pt = {10, 10};
printf("%d, %d\n", pt.X, pt.Y);
pt.init(); // 0 で初期化
printf("%d, %d\n", pt.X, pt.Y);
pt.X = 333;
pt.Y = 444;
printf("%d, %d\n", pt.X, pt.Y);
if (getch()) return;
}
|
構造体同士は、‘=’ を使って簡単にコピーすることができます。要素ごとにアクセスする必要はありません。文字列が混じっていてもコピーされます。また、配列やポインタ、アドレスなども、通常のデータ型と同じように使用することができます。ただし、ポインタ表現の場合、メンバへのアクセスには ‘->’ を利用します。
// 構造体のコピーとポインタ
#include <stdio.h> // printf
#include <string.h> // strcpy
#include <conio.h> // getch
// xdata 構造体
struct xdata
{
int index;
char name[64];
} ;
// main 関数
void main()
{
xdata x1 = {999, "unknown"};
// コピー
xdata x2;
x2 = x1;
printf("%d, %s\n", x2.index, x2.name);
// ポインタ
xdata* p;
p = &x1; // アドレスを代入
printf("%d, %s\n", p->index, p->name);
p->index = 16;
strcpy(p->name, "Picasso");
printf("%d, %s\n", p->index, p->name);
if (getch()) return;
}
| // 構造体配列とポインタ
#include <stdio.h> // printf
#include <string.h> // strcpy
#include <conio.h> // getch
// xdata 構造体
struct xdata {
int index;
char name[64];
} ;
// main 関数
void main() {
xdata a[10];
xdata *p;
p = a; // 先頭のアドレスを代入
p->index = 0;
strcpy(p->name, "Picasso");
p++;
p->index = 1;
strcpy(p->name, "Chagall");
p++;
p->index =2;
strcpy(p->name, "Renoir");
for (int i=0; i<3; i++) {
printf("%d, %s\n", a[i].index, a[i].name);
}
if (getch()) return;
}
|
構造体は、通常のデータ型と同じように、関数の引数や戻り値に利用することができます。
// 構造体の引数
#include <stdio.h> // printf
#include <string.h> // strcpy
#include <conio.h> // getch
struct xdata {
int index;
char name[64];
} ;
void setdata(xdata* x, int n, char* s) {
x->index = n;
strcpy(x->name, s);
}
// main 関数
void main() {
xdata a[10];
xdata *p;
p = a;
setdata(p++, 0, "Picasso");
setdata(p++, 1, "Chagall");
setdata(p++, 2, "Renoir");
for (int i=0; i<3; i++) {
printf("%d, %s\n", a[i].index, a[i].name);
}
if (getch()) return;
}
| // 戻り値としての構造体
#include <stdio.h> // printf
#include <string.h> // strcpy
#include <conio.h> // getch
struct xdata {
int index;
char name[64];
} ;
xdata getdata(int n, char* s) {
xdata x;
x.index = n;
strcpy(x.name, s);
return x;
}
// main 関数
void main() {
xdata a[10];
a[0] = getdata(0, "Picasso");
a[1] = getdata(1, "Chagall");
a[2] = getdata(2, "Renoir");
for (int i=0; i<3; i++) {
printf("%d, %s\n", a[i].index, a[i].name);
}
if (getch()) return;
}
|
構造体は、通常のデータ型と同じように、new 演算子を使用して、動的にオブジェクトを作成することができます。ただし、メモリの解放は自動ではされないので、使用後は delete 演算子を使用してメモリを解放する必要があります。この時、配列の場合は “[]” の記述が必要となります。
// 構造体の動的管理
#include <stdio.h> // printf
#include <string.h> // strcpy
#include <conio.h> // getch
struct xdata {
int index;
char name[64];
} ;
// main 関数
void main()
{
xdata* p;
p = new xdata;
p->index = 0;
strcpy(p->name, "unknown");
printf("%d, %s", p->index, p->name);
delete p;
if (getch()) return;
}
| // 構造体配列の動的管理
#include <stdio.h> // printf
#include <string.h> // strcpy
#include <conio.h> // getch
struct xdata {
int index;
char name[64];
} ;
// main 関数
void main() {
xdata* p;
p = new xdata[10];
for (int i=0; i<10; i++) {
(p+i)->index = i;
strcpy((p+i)->name, "unknown");
}
delete [] p;
if (getch()) return;
}
|
|