前回の記事で述べたように、C言語のデータ型には、基本データ型、構築データ型、ポインタ型の3種類があります。
基本的なデータ型については上記で説明しましたが、この記事ではデータ型の構造を紹介します。構築されたデータ型はさらに、配列型、構造体型、共用体型、列挙型の 3 つの型に分類されます。
配列型
まず第一に、なぜ配列があるのかという疑問を明確にする必要があります。
例: 10 人の学生の成績をカウントする必要があります。基本データ型を使用して、これらのデータを保存する少なくとも 10 個の変数を定義する場合、学生が 100 人いる場合は、少なくとも 100 個の変数が必要です。
float a0,a1,a2,a3,a4,a5,a6,a7,a8,a9;
基本データ型を使って変数を定義する場合、同じ型の変数がたくさんあると定義が面倒になります。上記の問題を配列を使って解決すると非常に便利ですが、
float a[10];
同じ型の複数の変数の定義を実現するのに必要なステートメントは 1 つだけですが、配列の利点が強調されるため、配列が必要になります。この実際的な問題により、同じ型のデータの集合である配列の概念が理解しやすくなります。
配列と配列要素: 配列は、名前で表される同じ型のデータの集合であり、この名前は配列名と呼ばれます。配列内のデータは添字によって区別される変数に格納され、これらの変数は添字変数または配列要素と呼ばれます。各添字変数は単純変数と等価であり、配列の型は配列の添字変数のデータ型でもあります。配列は構造体型に属し、構造体型のデータは基本型のデータから一定の規則に従って構成されます。
C言語で使用される配列には、1次元配列と多次元配列があります。
一次元配列
1次元配列の定義
定義形式:
データ型配列名[定数式];
「データ型」: 配列要素のデータ型です。
「配列名」:C言語の識別子の規則に従います。
「定数式」:配列内の要素の数、つまり配列の長さを示します。整数定数、整数定数式、または記号定数を使用できます。
int a[5];
1 次元配列 a が定義されています。int は、配列内の a の各要素が整数であることを意味し、配列名は a で、この配列には 5 つの要素があります。配列の添字は 0 から始まるため、上で定義した配列の 6 つの要素は a[0]、a[1]、a[2]、a[3]、a[4] となり、メモリに連続的に格納されます。配列の最初のアドレスは a[0] のアドレスで、配列名は配列の最初のアドレス (アドレスは非常に重要で、ポインタで使用されます)、つまり の値を表します。 a と a[0] のアドレス値 (&a[0] ) は同じです。
1D配列リファレンス
参考形式:
配列名[添字式];
このうち「添字式」:整数定数または整数式のみとなります。
注: 添え字は 0 から始まり (下限は 0)、配列の最大添え字 (上限) は配列の長さから 1 を引いた値になります。
int a[10];
a[0]=0;
scanf("%d",&a[10]);/*下标越界*/
上記のコードの 3 行目は間違って使用されており、配列の添字は (n-1) 桁までしか到達できません。n は配列要素の数です。
1次元配列の初期化
1. 配列を定義する場合。すべての配列要素を初期化します
int a[5]={
0,1,2,3,4};
a[0]の値は0、a[1]の値は1、...、a[4]の値は4です。すべて
の配列要素に初期値を代入する場合、配列の長さは次のように別の方法で指定することもできます。
int a[]={
0,1,2,3,4};
システムは、初期値の数に応じて、配列の長さを 5 として定義します。
2. 配列を定義する際、配列の一部の要素に初期値を代入します
int a[5]={
0,1,2};
a[0] の値は 0、a[1] の値は 1、a[2] の値は 2、残りの要素は 0 です。
二次元配列
2次元配列の定義
定義形式:
データ型配列名 [定数式1] [定数式2];
[定数式1]は2次元配列の行数を示し、[定数式2]は2次元配列の列数を示します。
float x[2][3];
x を 2 行 3 列の合計 6 つの要素を持つ配列として定義します。各要素は float 型です。システムは 2 次元配列のメモリ内に連続した記憶領域を割り当て、要素の配置順序は行、つまり x[0][0]、x[0][1]、x[ に格納されます。 0][2]、x[1][0]、x[1][1]、x[1][2]。配列名は配列の最初のアドレスを表します。
2 次元配列は 1 次元配列の特殊な種類とみなすことができ、x 配列は 2 つの大きな要素を含む 1 次元配列とみなすことができ、各要素は 3 つの要素を含む 1 次元配列となります。
x[0]------x[0][0]、x[0][1]、x[0][2]
x[1]------x[1][0] 、x[1][1]、x[1][2]
x[0] は 2 次元配列の最初の行の最初のアドレス、つまり x[0][0] のアドレスです。 x[1] は 2 次元配列の 2 行目の先頭アドレス、つまり x[1][0] のアドレスです。
2次元配列への参照
参考形式:
配列名 [行の添字式] [列の添字式]
注:2次元配列の行および列の添字は0から始まります(下限は0)
int a[3][4];
a[0][0]=3;
a[0][1]=a[0][0]+10;
エラー参照:
a[3][4]=3;/*下标越界*/
a[1,2]=1;/*应写成a[1][2]=1;*/
2次元配列の初期化
1. 行ごとに初期値を割り当てます。
int a[2][3]={
{
1,2,3},{
4,5,6}};
初期化結果:
1 行目: 1 2 3 2
行目: 4 5 6
2. 配列要素がメモリ内に配置されている順序に従って、各要素に初期値を割り当てます。
int a[2][3]={
1,2,3,4,5,6};
初期化結果:
1 行目: 1 2 3 2
行目: 4 5 6
3. いくつかの要素に初期値を割り当てます。
int a[2][3]={
{
1},{
4}};
初期化結果:
1行目:1 0 0
2行目:4 0 0
特記事項 - 文字配列
前述の整数配列や実数配列と同様に、文字配列も配列の一種です。では、なぜ文字配列を個別に発生させる必要があるのでしょうか? 他のタイプの配列とは異なり、整数配列の場合は整数データを格納し、実数配列の場合は実データを格納します。ただし、文字配列は文字データと文字列の両方を保存でき、文字列は文字配列にのみ保存できるのが特徴です。
弦
文字配列に格納されている文字データが文字列であるかどうかを確認するには、まず文字と文字列の違いを確認する必要があります。文字と文字列の違いは、文字列の終了マーク ('\0') の有無です。文字列終了フラグがある場合は文字列、それ以外の場合は文字です。
char a[5]={
'C','h', 'i', 'n', 'a' };
char b[6]={
'C','h', 'i', 'n', 'a' , '\0'};
上の 2 行のコードに示されているように、a 配列には文字列の終了マーク ('\0') がないため、a 配列に格納される文字は 'C'、'h'、'i'、'n になります。 '、'a';、および '\0' が b 配列に含まれ、文字列 China が b 配列に格納されます。
文字配列の初期化
1. 文字定数を使用して初期値を割り当てる
char a[5]={
'C','h', 'i', 'n', 'a' };
a 配列には文字列ではなく 5 つの文字データが格納され、各配列要素と添字は整数配列に対応します。
char b[6]={
'C','h', 'i', 'n', 'a' , '\0'};
b 配列では b[5]='\0' であるため、文字列は b 配列に格納されます。
2. 初期値を文字列定数で代入する
char str[10]= {
"a string"};
char str[10]= "a string";
上記の 2 行のコードは同じ機能を持ち、両方とも str 配列に文字列 (文字列) を格納します。
char a[3][10]={
"basic","pascal","c"};
配列には 3 つの行があり、各行に文字列が格納されます。
これは、配列の長さが割り当てられたコンテンツの長さよりも長い場合、システムが自動的に残りの位置に「\0」を埋め、配列に格納されるコンテンツが文字列になることも示しています。好き:
char s3[7]={
's', 't', 'r', 'i', 'n', 'g'};
文字配列の長さは 7 桁ですが、値を割り当てるときにユーザーが 6 桁のみを割り当てると、システムは自動的に 7 桁目を「\0」で埋めます。つまり、s3[7]='\0' となります。
3. 初期化時の長さの省略
char s1[ ]= "Good morning!";
このとき、s1配列の長さは14で、s1[13]='\0'となります。文字列は s1 配列に格納されます。
char s2[ ]={
's', 't', 'r', 'i', 'n', 'g'};
このとき、s2配列の長さは6です。配列には文字列の終わりのマーカーがありません。したがって、文字列として使用することはできません。
文字配列への参照
文字配列への参照は、文字配列の個々の要素への参照と文字配列全体への参照に分類できます。文字配列の個々の要素への参照は、整数配列および実数配列の場合と同じです。文字配列への全体的な参照は、主に入力と出力に現れます。
char c[ ]= "China";
printf("%s",c);
ここで、c は配列の名前であり、配列の最初のアドレスを表します。生産地は中国です。
char c[10];
scanf("%s",c);
入力が北京の場合、文字列「北京」が配列に格納されます。
配列の概要
配列は同じ型のデータの集合を表す集合であり、同じ型の変数が多数必要な場合に使用されます。1次元配列と多次元配列に分けられます。
まず注意すべきことは、配列の添字は境界を越えてはいけないということです。配列の添字は 0 から始まり、定義時や引用時に境界を越えることはできません。これはよくある間違いです。
2 番目の点は配列のアドレスです。アドレスは後続のポインタ参照で非常に重要です。配列名が配列の最初のアドレスを表し、2 つの配列の各行の最初のアドレスが何であるかを明確にする必要があります。次元配列。配列の要素のアドレスがコンピューター内でどのように割り当てられるかは、その後のポインターの学習に役立ちます。
構造タイプ
配列型は大規模なデータ処理に非常に便利で柔軟性がありますが、一定の制限もあります。つまり、同じ配列の要素はすべて同じ型のデータでなければなりません。さまざまなデータ型をまとめられるデータ型はありますか? 次に、構造体と結合があります。
構造体は複数のデータ項目から構成されており、構造体を構成する各データ項目を構造体メンバと呼びます。構造体の各メンバーのデータ型は異なる場合があります。構造型データを使用する前に、まず構造型を定義する必要があります。構造定義の一般的な形式は次のとおりです。
struct 结构体名
{
数据类型1 成员名1;
数据类型2 成员名2;
...
数据类型n 成员名n;
};
このうち、struct は C 言語のキーワードであり、構造体の型の定義を示します。最後のセミコロンは、構造体の型定義の終わりを示します。構造体のメンバーには、C 言語で許可されている任意のデータ型を使用できます。例えば:
struct bookcard
{
char num[10];
char mane[30];
char author[30];
char publisher[60];
float price;
int n;
};
注: 構造体タイプの定義は、そのタイプの形式のみを示します。システムはその構造体にメモリ空間を割り当てません。コンパイル システムは変数にメモリ空間を割り当てるだけです。そのため、構造体が占有する空間は、構造体が占有する空間と等しくなります。各構造体のメンバーと。構造体メンバーの型は、別の構造体型にすることもできます。
構造体型変数の定義
1. 定義された構造体タイプを使用して変数を定義する
この方法は、プログラム内の複数の関数が同じ構造体タイプの変数を定義する必要があり、構造体タイプを構造体名の形式でグローバル タイプとして定義する必要がある場合に使用する必要があります
。変数 有名な時計。
struct student
{
char num[8];name[20];sex;
int age;
float score;
};
void main()
{
struct student a;
...
}
f1()
{
struct student b;
...
}
struct Student型は関数外で定義されているためグローバル変数なので、main関数やf1関数内で構造体変数a、bを定義するのに利用できます。
2. 構造体型を定義しながら変数を定義する
一般的に外部変数を定義する場合に使用する方法ですが、この構造体型名を使用して各関数のローカル変数を定義することもできます。形式は次のとおりです:
struct 構造名
{メンバー定義テーブル;
}変数名テーブル;
struct student
{
char num[8];name[20];sex;
int age;
float score;
}st[30];
void main()
{
struct student s;
...
}
f1()
{
struct student x;
...
}
1 つの構造体学生型変数には 1 人の学生の情報しか記述できませんが、30 人の学生の情報を保存する必要がある場合は、構造体型配列を定義できます。このように外部構造体配列はグローバル型名を定義する際に定義されており、定義方法は他の型の配列定義と同様です。この配列の各要素は構造体型の変数です。これら 2 つの構造タイプを組み合わせて使用すると、データ処理がより汎用的になります。
3. 構造型変数を直接定義する
この方法は、プログラム内で特定の構造型変数を必要とする箇所が 1 か所だけの場合に使用できます。このメソッドでは構造体の型名は指定せず、
struct
{メンバ定義テーブル;
}変数名テーブル;という形式になります。
void main()
{
struct
{
char num[8],name[30],sex;
int age;
float score;
}st[30],a,b,c;
int i,j;
...
}
構造体変数の初期化
構造体変数を定義するときに、そのメンバーに初期値を割り当てることもできます。初期値テーブルは「{}」で囲み、テーブル内のデータはカンマ区切りで、構造体の型定義と同じメンバ数、同じ型にする必要があります。初期値の数が構造体のメンバーの数より少ない場合、初期値のないメンバーには値 0 が割り当てられます。初期値の数が構造体のメンバ数を超えるとコンパイルエラーとなります。
例: 構造体変数の初期化:
struct date
{
int year,month,day;};
struct student
{
char num[8],name[30],sex;
struct date birthday;
float score;
}a={
"40826011","Li ming","M",{
1991,2,9},87.5},
b={
"40826025","Zhang qiang","F",{
1990,5,12},85},c,d;
構造体の配列の初期化:
struct s
{
char num[8],name[30],sex;
float score;
}stu[3]={
{
"40826011","Li ming","M",87.5},
{
"40826025","Zhang qiang","F",85},
{
"40826032","Wang xinping","F",90}
};
構造体変数メンバの参照形式
構造体変数のメンバーを参照する一般的な形式は次のとおりです:
構造体変数名. メンバー名
ここで、「.」は最高レベルの操作を行うコンポーネント演算子です。たとえば、構造体変数の初期化の最初のコードでは、a のメンバーを a.num、a.name、a.sex、a.birthday、および a.score として表すことができます。a、b、c、d は同じ型の変数であり、a.num、b.num、c.num、d.num を使用して、同じ名前 num の各メンバーを区別できます。
構造体ポインター: struct Student *p;
例:
struct code
{
int n;
char c;
}a,*p=&a;
p は a を指す構造体ポインタで、変数 a のメンバを参照するには、
1.an, ac 変数名のコンポーネント演算によるメンバの選択、
2.(*p).n,(*p) の3 つの方法があります。 .c : ポインタ変数間接記憶演算子を使用して、ターゲット変数にアクセスします。
3.p->n,p->c: これは、構造体ポインタ変数が構造体のメンバを参照するために特別に使用される形式であり、2 番目の形式と同等です。フォーム。
ユニオンタイプ
共用体は、異なるデータ型の記憶構造を共有する構築型に似ています。つまり、共用体変数のすべてのメンバーが同じ記憶領域を占有します。これは、共用体が占めるスペースがそのメンバーが占める最大スペースと等しいことも示しています。このタイプのデータを使用する利点は、ストレージ領域を節約できることです。
共用体型定義の一般的な形式は次のとおりです。
union 共用体名
{
数据类型1 成员名1;
数据类型2 成员名2;
...
数据类型n 成员名n;
};
このうちunionはC言語のキーワードであり、共用体の型の定義を示します。最後のセミコロンは、共用体型定義の終わりを示します。共用体のメンバーには、C 言語で許可されている任意のデータ型を使用できます。例えば:
union utype
{
int i;
char ch;
long l;
char c[4];
};
共用体変数の定義
共用体型変数の定義形式は構造体変数の定義と同様です。
1.ユニオン ユニオン本体名 変数名テーブル;
2.ユニオン ユニオン本体名
{メンバ定義テーブル;
} 変数名テーブル;
3.ユニオン
{メンバ定義テーブル;
} 変数名テーブル;
共用体変数のメンバーへの参照
構造体変数型と同様に、共用体のメンバーへの参照にも 3 つの形式があります。
union u
{
char u1;
int u2;
}x,*p=&x;
参照形式は次のとおりです:
1.x.u1,x.u2;
2.(*p).u1,(*p).u2;
3.p->u1,p->u2;