the ド田舎エンジニア

東京とは名ばかり 八王子市は尾崎 幸一朗(通称:サチロー)による気まぐれブログです

久しぶりのC言語 その4

こんばんは。
サチローこと幸一朗です。


C言語の方に戻って参りました。
さて、前回は第一関門の『配列』『ポインタ』について軽く触れていきました。


①配列を用いて以下を標準出力してください。
「1 5 103 65 33」

int array[5] = { 1, 5, 103, 65, 33 };

for (int i = 0; i < 5; i++) {
  printf("%d ", array[i]);
}
printf("\n");

以下の方法を取った方が修正範囲が少なくて済みます。
運用上はこのように使用します。

①文字定数を使用する

#define SIZE (5)

int array[SIZE] = { 1, 5, 103, 65, 33 };

for (int i = 0; i < SIZE; i++) {
  printf("%d ", array[i]);
}
printf("\n");

②sizeofで配列の要素数を取得する

int size = sizeof(array) / sizeof(array[0]);

②は、配列全体のサイズ ÷ 1要素のサイズから、配列全体の要素数を割り出しています。


②標準入力から文字列を得てください。その文字列において、文字「a」を検出した場合は「hit」、全く検出しなかった場合は「no hit」を1度だけ標準出力してください。

char str[128 + 1] = { '\0' };
int size = 0;

fgets(str, sizeof(str), stdin);

size = strlen(str);
for (int i = 0; i < size; i++) {
  if (str[i] == 'a') {
    printf("hit\n");
    break;
  }
}

if (i == size) {
  printf("no hit\n");
}

ベタっと書くとこんな具合ですが、普通はstrchrを使うべきでしょう。

char *p = strchr(str, 'a');
if (p) {
  /* p == 'a'を検出したaddress */
  printf("hit\n");
} else {
  /* p == NULL */
  printf("no hit\n");
}

③標準入力から得た文字列を反転して標準出力してください。
標準入力までは②と変わらないので省略。
forの部分を修正するのみでできます。

int size = strlen(str);
for (i = size - 1; i >= 0; i--) {
  printf("%c", str[i]);
}

注意すべきは、size=文字の長さなので、配列の添え字に使用する場合の最大値はsize - 1となること。

char str[128 + 1] = "abcde";

int size = strlen(str);
/*
 sizeは「5」だが、'e'を参照する場合はstr[4]
*/

例題の場合は、最後尾に'\0'が入るが、入っていない場合はアクセス違反となり落ちる。
「セグメンテーション違反」とか、「segmentation fault」、「例外が発生しました」とか表示される。

④変数「i」を宣言し、そのアドレスを標準出力してください。

int i = 0;

printf("%p\n", &i);


⑤変数「i」のアドレスをポインタ変数「p」に格納し、ポインタ変数を用いて変数「i」のアドレスを標準出力してください。
④のiのアドレスを変数に格納するだけ。
注意すべきは、ポインタ変数と、そこにアドレスを代入する変数の型を合わせること。

int i = 0;
int *p = &i;

printf("%p\n", p);

⑥「⑤」で使用したポインタ変数「p」のアドレスをポインタ変数「pp」に格納し、ポインタ変数「p」のアドレスを標準出力してください。
⑤の続き。

int i = 0;
int *p = &i;
int **pp = &p;

printf("%p\n", *pp);

意外と長くなってしまいましたね。
実際にコードを組んで、中身を標準出力し、中でどういった動きになっているのかを実際に見た方が理解しやすいと思います。


次回は関数について触れていこうかと思います。

長々と閲覧頂きありがとうございます。