おぼえがき

過ちては則ち改むるにうんぬんかんぬん

int型およびchar型の配列について(C言語)

f:id:feci:20210810151051j:plain

C11

 

C11におけるint型およびchar型の配列について。

#include <stdio.h>
#include <string.h>

void main() {
  //①int型の配列の作り方
  int aa = { 5,4,3,2,1 };
  int i;

 for (i = 0i < 5i++) {
      printf("aa[%d]=%d\n"iaa[i]);
  }
  printf("\n");                          //ab[0]=5 ~中略~ ab[4]=1


//②めんどくさい配列の作り方
  int ab[5];
  ab[0= 5;
  ab[1= 4;
  ab[2= 3;
  ab[3= 2;
  ab[4= 1;

 for (i = 0i < 5i++) {
      printf("ab[%d]=%d\n"iab[i]);
  }
  printf("\n");                          //ab[0]=5 ~中略~ ab[4]=1


//③char型の配列の作り方
  char sa[4= { 'a''3','あ''\0' };  //char型配列の最後は必ず\0を入れる
  char sb 
= "あいうえお\0";            //初期化時にのみ可能な方法(最後の\0はあってもなくても可)
  char sc[100];                          //この方法しか思いつかなかった…

 printf("sa = %s\n"sa);               //a3・ ← なぜか平仮名は表示できない
  printf("sb = %s\n"sb);               //あいうえお ← なぜか平仮名を表示できる

 printf("9文字以下の文字列を入力してください。");
  scanf("%s"sc);                       //char型では変数の頭に&を付けない

 int ia = strlen(sc);                   //変数scの文字列の長さを整数で取得
  //printf("iaは%d\n", ia);              //変数iaの中身の確認用

 if (ia <= 9) {                         //入力された文字数が9個以下なら実行(末尾の\0はカウントしない)
      printf("sc = %s\n"sc);           //入力した9文字以下の文字列
  }
  else {
      printf("すみませんが10文字以上の入力はNGです。"); //エラーメッセージ
  }
}

配列とは、1つの変数内に複数の要素を代入することです。

 

例えばint型のaaaという変数があったとして、int aaa = 1234; であれば変数aaaは配列ではありません。

この場合のaaaは、1,234という1つの要素を代入した変数にすぎません。

 

ではもしこのaaaに aaa = {1, 2, 3, 4}; という値を代入した場合はどうなるでしょうか。

この場合のaaaは、1と2と3と4という4つの要素を代入されたint型の配列としてあつかわれます。

 

この1と2と3と4という要素にはそれぞれ、先頭から0++の管理番号が自動で付与されます。

この配列内の各要素の管理番号のことをインデックスといいます。

配列のインデックスは、変数名末尾のブラケット(角括弧)に整数として表されます。

 

 

さて、ここまでの説明は基本的にはint型の配列のお話です。

驚くべきことに、C言語には文字列をあつかえるデータ型が存在しません。

 

なのでC言語では、1文字だけをあつかえるchar型を配列にして使うことで、無理矢理に文字列を作っていきます。

 

上記プログラムの③では、char型の配列として文字列を作っています。

char型の配列を作る場合は、5文字ならインデックスに6、7文字ならインデックスに8と指定します。

 

なぜ代入したい文字列の数+1の値を入れるのかというと、char型の配列を作るときのルールとして、末尾には必ず '\0' を代入するという決まりがあるからです。

なのでもし「こんにちは」と入れたい場合は、char aaa[6] = {'こ', 'ん', 'に', 'ち', 'は', '\n'}; と書く必要があります。

 

 

ちなみにですが、いま作った「こんにちは」を代入したaaaをprintf関数で出力すると、文字化けして平仮名が表示されません。

なぜかは分かりませんが、C言語では日本語の文字列を代入する場合は、char aaa[] = "こんにちは"; と書かかないと日本語が表示されないようなのです。

 

ちなみにこのインデックスを指定せずに文字列をダブルクオーテーション記号で囲んで代入する方法は、変数宣言時にしか使えません。

変数を宣言したあとに別の行でその変数にこの方法で文字列を代入しようとすると、当然のようにErrorが出ます。

 

あとこの記述方法だと、文字列末尾の \n は書いても書かなくてもどっちでもいいです。

もともとこの記述方法の場合は自動で末尾に \n が代入されているようで、追加で手動で \n と記述した場合でも、その記述した \n はC言語くんが勝手にいい感じに処理してくれます。

 

 

あと、上記プログラムのようにscanf関数を使って変数に文字列を代入する場合は、int型のときのように返り値を代入する変数名の頭に & を付けてはいけません。

これはなぜかはよく分からないのですが、とにかくC言語ではそういうルールになっているらしいです。

 

 

あと上記③のプログラムではもともとは変数scの配列数は10でした。

その10を超えないために、if文で条件式に (ia <= 9) と指定しているんですね。

 

ただこれで sc[10]; の (ia <= 9) としてしまうと、困ったことにscanfで10文字以上を入力してEnterを押された瞬間にC言語くんがErrorを出します。

これはまあ当たり前の話で、10しか容量のない配列に10+\nの要素を無理やり突っ込んでるわけですから、C言語くんとしては 「困ったなあ(´·ω·`)」 って感じになりますよね。

 

しかしこれだと入力された時点でErrorの有無が決定してしまうので、if文で処理をコントロールすることができないんですよね。

「さてどうしようか」と迷った挙句、今の私の経験と知識量では変数scの容量をすごく大きくしてやるくらいしか解決策が思いつきませんでした。

 

こうすることで、scanfでのErrorが出る可能性は大きく減らせます。

じゃあこのあとで入力された文字数が9以下かどうかをif文で判断するわけですが、ここで必要となるのは変数scに現在代入されている要素の数です。

 

この要素の数をint型で取得できなければ、if文で9と比較することができません。

じゃあどうやって文字列の数を整数で取得するのかなんですが、ここで私はstrlen関数を使うことにしました。

 

strlen関数を使うと、パラメータに指定した文字列の数をint型で返してくれます。

その値を変数iaに代入することで、if文で9文字以下の場合の処理と、10文字以上の場合の処理を作ることが可能になりました。

 

 

ちなみにstrlen関数と似たような関数にstrnlen関数というのがありますが、今回はなぜがstrnlen関数を使うとC言語くんがErrorを出してしまい、この関数を使うことができませんでした。

 

あとこのstrlen関数やstrnlen関数を使うには string.hinclude する必要があります。

string.hをincludeしてないと、これらの関数は実行することはできません。

 

 

最後に、配列の要素数を整数で取得する方法としては下記のようなものもあるらしいです。

 

int aaa = sizeof(a) / sizeof(int);

 

 

しかし私の場合はなぜかこの方法では、char型配列の要素の数を正常に取得することはできませんでした。

何文字入力してもなぜか固定で25という整数が代入されてしまうんですよねえ。

 

もしかしてこの方法での要素数の取得は、char型の配列には使えないのでしょうか?

もしかするとそうなのかもしれませんね。

 

 

以上です。