Index

HOME > プログラムTOP > C++



C++の壺・構造体篇

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

sasaraan programming

Exposition

●構造体の基礎

 構造体では、異なるデータ型の要素(メンバ)を複数持つことができます。この時、変数を同時に宣言することも可能です。また、宣言した後は、データ型と同じように扱うことができ、メンバへのアクセスには ‘ .’ を利用します。
【モデル】
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;
} 

www.sasaraan.net

(c) morijoh