プログラミングC:配列と文字列

この記事はシリーズの一部です – どのようにプログラミングするには:Cプログラミング

序文

前回の記事では、与えられた変数宣言を構成できる基本的なデータ型について説明しました。この記事では、別の角度から変数の宣言を行います。いくつかの変数は複数の値を保持できます。これらの値は、最初から最後まで順番に指定されます。文字列を示す数値の列である「文字列」について議論したときには、これらの要素のいくつかに触れてきました。一連の値を保持できる変数は通常配列</ strong>と呼ばれ、はい、Cがサポートします。

配列は、インデックスを使用して1つの識別子の下でアクセスできる一連の個々の変数です。つまり、私は3つの文字の配列を持っています。 char myArray[3] = {6, 7, 8};   私は入力して最初のcharにアクセスできます  myArray[0] , 2番目の文字列も入力して  myArray[1] , 等々。 あなたが見ることができるように、myArrayは識別子であり、0または6がインデックスにあります。 この場合、最初の式は値1を返し、2番目の式は値7を返します。配列のインデックス付けは、1ではなくCでゼロから開始します。

配列は配列で構成することもでき、この意味では多次元配列と呼ばれます。 配列の追加の「レイヤー」は、次元と呼ばれます。 たとえば、次のような2次元配列を持つことができます。

このような配列には、最初の配列の位置、つまり配列の配列を指定し、次に2番目の内部配列のインデックスを指定します。 たとえば、上記の番号3にアクセスするには、[2] [2]と書くか、上の6にアクセスするには[1] [2]と書いてください。 配列7の先頭には、[0] [0]と書いてください。

配列内の各値は、他のすべての値とは別の変数です。 配列の特定の場所に新しい値を割り当てることができます。 my2DArray[0][2] = 12;  最初の配列は次のようになります {7, 8, 12} .

ご覧のように、配列は単純に1つの変数名の下に集められた一連の値です。 Cでは最も一般的な配列は文字列と呼ばれます。 以前の記事の文字列について説明しました。 これは完全に説明されています。 Cでは文字列は単なる一連の数値で、通常はcharsとして格納され、エンコーディングの文字または文字(通常はASCII)を示します。 それらはヌルで終了します。つまり、ヌル値(0)に達するまで文字列が継続しているとみなされます。

注意:Cは配列の境界をチェックしないことを覚えておくことが重要です。 つまり、Cコンパイラは通常、存在しない配列要素を参照しているかどうかをチェックしません。 誤ってメモリの一部に書き込まないように、定義した配列要素のみを参照することはあなた次第です。

一次元配列

Cでは、配列を定義すると、実際には、一連の値をメモリに格納しておきたいということを示しています。 これは、メモリ内に連続して格納され、最下位の位置がより低いメモリアドレスを有し、最後の位置が最も高いメモリアドレスを有するものとして知られている。 メモリ内の配列内の各要素はお互いに「次の」要素です。 これはCの要件であるため、一般的には(C99の場合を除いて)、配列を初めて定義するときに配列がどのように「大きく」なるかを判断または宣言する必要があります。 このようにして、Cコンパイラは、値を格納するためにクリアしてメモリに格納する必要がある領域を判断できます。

これを行う通常の方法は、配列を宣言するときに直ちに行われます。 配列は単純に配列に拡張された通常の変数なので、それを宣言することは通常の変数を宣言することとあまり変わらない。 基本的な1次元配列のパターンは、次のようになります(例を参照)。

C89では、配列のサイズは明示的にリテラル(この場合は変数ではない)で宣言しなければならず、コンパイラのためにそのサイズを設定する必要があります。 C99では、変数をサイズインジケータとして使用することができます。これにより、配列が割り当てられ、コンパイル後に決定されます。これは、プログラムが実行される(実行時)ことを意味します。

配列内の要素にアクセスするには、番号0から始まる2つの角括弧の間に数値を配置します。上のmyNameの最初の要素にアクセスするには、 myName[0] , 私が書いた2番目の要素 myName[1] , 等々。  ここでも注意してください! 配列を宣言するときは、要素の数を1から数えて指定する必要があります。これは、myArray [5]が0で始まり4で終了し、myName [6]が0で始まり5で終了するということです。

配列はメモリ内で連続しているので、メモリがどれくらいの量を占めるかを計算する必要があることがあります。 最初に決定する必要があるのは、配列を構成するデータ型の大きさです。 たとえば、charの場合、各要素は1バイトを占有します。 もしそれが短いintだとしても、各要素は2バイト、つまり16ビットを占有します。 1つの要素が占めるスペースを確保したら、配列の要素数で単純にその量を掛けて、配列のメモリーフットプリントに到達させます。 したがって、myNameは6バイト、someNumbersは92バイトに相当する(23 x 4バイト)です。 この方法は、以下の数学的テンプレートに分解することができます。

多次元配列

上に書いたように、配列は複数の「次元」を持つことができます。私はこれが幾分混乱を招くと思います。なぜなら、アレイはそれが「多次元」になる特別な品質ではないからです。これはすべて、配列がそれ以上の配列を含むことができるということです。つまり、1つの配列の各要素には固定サイズの別の配列を含めることができ、THAT配列の各要素には固定サイズなどの別の配列を含めることができます。「次元」とは実際には、の組み込み配列が移動します。

例えば、2次元配列は単純に配列の配列です。 3次元配列は、単純に配列の配列の配列になります。 Cでは、配列は一般的に固定サイズに初期化されなければならないので、宣言でこれらの配列の大きさを指定します。追加の配列を追加するたびに、配列定義に追加する「インデックスブラケット」が必要です。上の序文で見たように、2次元配列、例えば2の5配列の配列を指定します:

その宣言をこのテンプレートに沸かせることができます:

しかし、このテンプレートでは、Nの大きさがNになると、配列には「次元数」があります。 与えられた多次元配列のサイズを決定することが重要になります。 上記の元の方程式を単純に拡大したものです。 あなたは余分な次元の与えられたサイズを方程式の最後に掛けます:

多次元配列をさらに把握できる方法の1つは、2次元配列を調べることです。 あたかも「最初の」配列の各要素をスタックにレイアウトしているかのように想像してください。 これは、スタックの行番号が最初の要素になり、次の図のように2番目のインデックスがその特定の行の列として機能する正方形を作成し始めます。

配列の初期化

Cの素晴らしい点は、配列の内容を宣言されたときに同時に指定できることです。 私がそれを定義する時に特定の値を持つように変数を宣言することができるように、

配列を定義したときに特定の値を持つように宣言することもできます(この記事の前半の例を見てください)。 これを行うには、一連の値を指定する必要があります。 このシーケンスは文字列にすることができますが、文字列の外側にはコンマで区切られた一連の値が代わりに中括弧で囲まれています。 これらの値はリテラルでなければならず、実際に型付きの値であり、変数自体ではありません(下記の注を参照)。 シーケンス内の値は、配列によって与えられたデータ型と互換性がなければならない(MUST)。 配列の最初の値を配列の最初の要素に挿入し、配列の2番目の値を配列の2番目の要素に挿入するなどの方法で配列を構築します。 それはこのテンプレートと例に縮小することができます:

このインスタンスでは、myNumbers [0]は1になり、myNumbers [4]は5になります。

注意:上級ユーザーの方は、C99では、ローカル配列の値シーケンスで非リテラルを使用できることに注意してください。 C89では、すべてのイニシャライザ値をリテラル

多次元配列は、値のリストを使用して同様に初期化されます。 たとえば、この配列は、配列セットの0インデックスに数値を保持し、配列セットの1インデックスにその数値を2倍します。

しかし、多次元配列では、初期化時に行うことができ、サブ集合グループ化と呼ばれる素晴らしいことがあります。 つまり、より大きな配列のより小さな配列の定義の周りに中括弧を指定するだけです。 それは次のようになります:

サブグループ化の唯一の利点は、サブリスト内に配列を満たすのに十分な値を指定しないと、残りの配列値がすべて自動的にゼロに設定されることです。

Cの文字列では、 "something like this" ,ヌル値で終了する1次元のchar型配列です(ここではnullはゼロです)。 これは、C言語の文字列の唯一の「公式」形式であり、文字列がこれらの形式になることを期待するすべての標準ライブラリ関数です。 一部のライブラリは独自の文字列形式を実装していますが、これらの形式は標準ライブラリではサポートされていません。

配列の初期化では、単純に値リストを超えて文字列が短くなります。 文字列の配列をリテラル文字列表現に直接代入することができます(これは、引用符で囲んだ文字列です)。 だから、あなたはこのようなことをするかもしれません:

これは次のようになります。

見て分かるように、これはもっと手軽ですが、まだ最も簡単な初期化手法はありません。 その美しいものは、unsized array initializationと呼ばれています。 これはコード内で多くの文字列を手作業で指定しているときに非常に便利です。 上記のように、エラーメッセージを格納するために配列のサイズを手動で設定する必要がありました。 しかし、エラーメッセージが変更されたらどうなりますか? 単語を追加したり、ピリオドを削除したりすると、文字列に何文字含まれているかを数えて、配列宣言で正確に指定する必要があります。 しかし、もし私たちがしなければどうですか? そうです、私たちはしません。 実際には次のように書くことができます:

そして、Cコンパイラは、指定された文字列リテラルに対応するために配列が必要とした要素の数を自動的に決定します。 これは文字列ではなく、配列の初期化でも機能します。 ただし、多次元配列でも機能しますが、複数の次元を持つ配列を扱う場合は、残りの次元のサイズを指定する必要があります。 それは次のようになります。

指定された初期化子

C99では、配列の内容を決定する際にいくつかのオプションがあります。 場合によっては、最初に配列を定義するときに配列の特定のインデックスのみを設定したい場合もあります。 これは、指定された初期化子を使用して実行できます。 これは、以下の形式をとります:

ここで、indexは初期化したいインデックスであり、値は望む値です。 例えば、10要素の配列の要素5と要素7を初期化するには、次のように記述します。

これは、まばらな配列を扱うときに便利です。 これはC99のみの機能なので、コンパイラでCのバージョンを確認してください。

C99の可変長配列

C89では、配列の次元は5または7などの数値リテラルを使用して宣言されなければなりません。C99では、宣言時に配列のサイズを決定するために変数または他の識別子を使用できます。 これは先進的な話題なので、私はそれを最後に取り上げています。 有効な式が次元で宣言された配列は、特に実行時にしか認識されない場合は、可変長配列と呼ばれます。 サイズを変更できる動的配列と混同しないでください。 そのような宣言には限界がありますが、ブロックまたはプロトタイプのスコープ内の配列(高度なトピック)でのみ行うことができます。

結論

単一の値変数は素晴らしいものであり、問​​題のホスト全体を解決することができますが、時には一連の値を知る必要がある場合もあります。これは、Cが文字を表す単純な一連の1バイトの数値として見える文字列に特に便利です。それぞれの文字を別々の変数に文字列で格納すると、それはひどく混乱します。

しかし、値のシーケンスはそれを超えることができます。例えば、多次元配列です。たぶん私たちはエラーシステムをセットアップしており、一連のエラーメッセージをシーケンスに格納する必要があります。これは、配列、または配列の配列です。あるいは、マップ上の高さの2次元プロットを見て、プログラマが容易に処理して理解できる方法でそれらをコンピュータに取り入れる必要があるかもしれません。

メモリ管理に着手してバッファの割り当てを開始するときには、値のシーケンスがさらに重要な役割を果たします。バッファがなければ、異なる入力ストリームからファイルを読み込むことはできず、他のデバイスやプログラムに情報を出力することもできません。

配列は、私たちの問題を創造的に解決する豊かな機会を与えてくれます。私は、この記事の中でより多くの機能を身につけたいと思っています。最初は混乱することがありますが、特に多次元配列ですが、単純なシーケンス(シーケンスのシーケンスの…)です。読んでくれてありがとう!

この記事はシリーズの一部です – どのようにプログラミングするには:Cプログラミング

この記事を読んでいただければ、パトリオンのサポートを検討することもできます。

しかし、毎月の約束が少しでもあれば、私はそれを得る、あなたは私にコーヒーを買うことを考えるかもしれない。

photo credit: NBStwo Beale Street 2008 via photopin (license)

あわせて読みたい

コメントを残す

%d人のブロガーが「いいね」をつけました。