カテゴリ:13.実際にやってみる > 13.2 C言語ではこうなります

配列を作ると、メモリにアドレスが確保されます。その様子をプログラムで実行します。
#include <stdio.h>
void main() {
    int A[100];  // 配列変数Aを定義。保存可能個数は100個でA[1]-A[100]を使用可能。
    int k;// 整数型の変数kを定義
    // kを1から100まで、1ずつ増やす(k++)
    for (k = 1; k <= 100; k++) {
        A[k] = k; 
        printf("A[%d]_add:%p\n",k,&A[k]); //A[k]のアドレスを表示
    }
}

結果は、以下のようになります。

c:\work>pg1.exe
A[1]_add:0028FDA0
A[2]_add:0028FDA4
A[3]_add:0028FDA8
A[4]_add:0028FDAC
A[5]_add:0028FDB0
A[6]_add:0028FDB4
A[7]_add:0028FDB8
・・・・
続きを読む

■H25春
問7 配列Aに対して次の手続を実行して,2≦k≦100である素数kだけを全て出力したい。a,b,cに入るループの初期値,終値,増分として,適切な組合せはどれか。

for k = 2 to 100 step 1:
  A[k] = 1;
for m = 2 to 10 step 1:
    for k =[   a   ] to [   b   ] step [   c   ]:
   A[k] = 0;
for k = 2 to 100 step 1:
  if A[k]≠0:
   print k;

H25h-問7
【正解】イ
実際のプログラムの例は以下
#include<stdio.h>   // stdio.h(標準入出力を行うための関数が定義されたファイル)を読み込む
// main関数。引数は取らない。処理後に値を返さない
void main() {
    int A[101];    // 配列変数Aを定義。保存可能個数は101個でA[0]-A[100]を使用可能。
    int k, m;  // 整数型の変数kとmを定義
    // kを2から100まで、1ずつ増やす(k++)
    for (k = 2; k <= 100; k++) {
        A[k] = 1;  // A[2]-A[100]をすべて1にしている
    }
    // 2の倍数-10の倍数をリストから消していく
    for (m = 2; m <= 10; m++) { // mを2から10まで1ずつ増やす
        for (k = 2*m; k <= 100; k += m) {
            // kを2mから100までmずつ増やす
            // つまりkは2m, 3m, 4m,・・・と変化
            A[k] = 0;  // kはmの倍数=素数ではないから0にする
        }
    }
    for (k = 2; k <= 100; k++) { // kを2から100まで1ずつ増やす
        if (A[k] != 0) {  // A[k]が0でない、つまりkが素数なら
            printf("%d,", k);  // kを表示
        }
    }
}
【処理の解説】
・エラトステネスのふるい法を使って素数を求めています。
・変数Aは、0か1の値になるが、A[k]=0なら非素数、A[k]=1なら素数(処理の途中では「素数の可能性」)
・まず2から100をすべて素数かもしれないリストに入れる
   (k=2-100についてA[k] = 1)
素数とは「約数として自分と1だけもつ」ことから、「何かの倍数であれば素数ではない」という考えで、倍数をすべて消していく。具体的にはA[k] = 0

与えられたa,bは正の整数です。a,bの最大公約数を求めます。
フローチャートは、情報処理技術者試験(H29春AP問6)にあります。

終了時にxに格納されているものが、最大公約数です。
※mod(x,y)はxをyで割った余りです。
H29h-問6
たとえば、以下の数字で考えます。
x=20、y=25

■ループ1:t=20、x=25、y=20
■ループ2:t=5、x=20、y=5
■ループ3:t=0、x=5、y=0 ←ループ終了

終了時にはxに、a(20)とb(25)の最大公約数である5が入ります。

プログラム
実際にCでプログラムを書いてみると、以下のようになります。
#include <stdio.h>

//mod関数("x"を"y"で割った余りを計算する)
int mod(int x, int y)
{
 //"%"は余りを計算する演算子
 return x%y;  //"x"を"y"で割った余りを返す
}

//main関数
void main(){
 int x, y;
 int t;   // 余りを入れる

 //標準入力からxとyの値を取得
 printf("整数aを入力してください:");
 scanf("%d", &x);
 printf("整数bを入力してください:");
 scanf("%d", &y);

 //while文で"y"が0以外の場合はループ1を実施
 while(y!=0){
  t = mod(x, y);  //定義したmod関数の戻り値を"t"に代入
  x = y;  //"y"の値を"x"に代入
  y = t;  //"t"の値を"y"に代入
 }

 printf("x=%dです\n", x);
}

プログラム(xとyの入力チェックを含めた少し詳細なもの)
#include <stdio.h>

int mod(int x, int y)
{
 return x%y;
}

void main(){
 int x, y;
 int t;

 printf("input x:");
 if(scanf("%d", &x)!=1){  //数値の取得に失敗した場合
  printf("入力エラー\n");
  return;  //プログラムの途中終了
 }

 if(x<=0){  //xが正の整数で無い場合
  printf("数値が不正です\n");   //プログラムの途中終了
  return;
 }

 printf("input y:");

 if(scanf("%d", &y)!=1){
  printf("入力エラー\n");
  return;
 }

 if(y<=0){
  printf("数値が不正です\n");
  return;
 }

 while(y!=0){
  t = mod(x, y);
  x = y;
  y = t;
 }

 printf("x=%dです\n", x);

}

fact(n)は,非負の整数nに対してnの階乗を返す。
たとえば、fact(4)=4×3×2×1=24 です。これを求めるプログラムを書いてみます。

1.再帰的に書く場合
#include <stdio.h>

//fact関数
int fact(int n)
{
 if(n==0){  //"n"が0の場合
  return 1;  //1を返す
 }
 else{//"n"が0以外の場合
  //"n-1"を引数としてfact関数の再帰呼び出し
  return n*fact(n-1);  //"n"と戻り値の積を返す
 }
}

//main関数
void main(){
 int n;  //"n"をint型変数で定義
 //標準入力からnの値を取得
 printf("nの値を入力してください:");
 scanf("%d", &n);   //scanfを利用して整数入力させ、nに入れる

 //fact関数を階乗の結果を呼び出して表示する
 printf("fact(n)=%dです\n", fact(n));
}
ああ

2.再帰的に書かない場合
#include <stdio.h>

void main(){
 int n; //ある整数n
 int fact = 1; //nの階乗。最初は1とする
 int i; //ループに使う値
 
 // 標準入力からnの値を取得
 printf("nの値を入力してください:");
 scanf("%d", &n);   //scanfを利用して整数入力させ、nに入れる
  
 //階乗の計算。iを1から順にnになるまで掛け算する
 for(i=1; i<=n; ++i) {
     fact = fact * i;
  }; 

 //結果を表示する
 printf("%dの階乗は、%dです\n",n,fact);
}
 

if文とelseを使って、条件分岐をする。

◆シンプルにプログラムを書いてみた。
正の整数を入力してもらう。xが0以下の場合はエラーとして強制終了する。
#include <stdio.h>

void main(){
 int x;

 printf("正の整数xの値を入力してください:");
 scanf("%d", &x);   //scanfを利用して整数入力させ、xに入れる

 if(x<=0){  // "x"が0以下の場合
  printf("正の整数ではありません\n");
  return;  //プログラムの途中終了
 }
 else{
  printf("入力された値は%dです。\n", x); 
 } 
}

※今回の場合、else {}でくくらなくてもいい。

scanf(スキャンエフ)を使って、キーボード入力。この場合は、整数値をxに入れる
 scanf("%d",&x);

◆1.シンプルにプログラムを書いてみた。
整数入力としてxに値を入れて、それを表示する
#include <stdio.h>

void main(){
 int x;
 printf("xの値を入力してください:");
 scanf("%d", &x);   //scanfを利用して整数入力させ、xに入れる
        //%dは整数の場合で、%fは浮動小数点、%cは文字などと決められている
 printf("入力された値は%dです。\n", x);   // "\n" は改行コード。%dにxの値が入る。
}

※戻り値がなく、単に表示するだけなのでvoidを使っている。
※実行してきちんと動くと、うれしい。

◆2.数字が入力されているかをチェック
文字ではなく数字が入力されているかのチェックし、数字ではない場合には「入力エラーです」と表示する場合は次のようになります。
#include <stdio.h>

void main(){
 int x;
 printf("xの値を入力してください:");

// 文字ではなく数字が入力されたかのチェック。scanfは取得に成功したデータの数を返す。よって、値が1でなければエラー
if(scanf("%d", &x)!=1){ //数値の取得に失敗した場合
  printf("入力エラーです\n");
  return;  //プログラムの途中終了  
 }
 
 printf("入力された値は%dです。\n", x);  
}


プログラムを書いてみた。
printfを使って、「こんちくは」と表示する

#include<stdio.h>

void main(){

 printf("こんちくは");

}

戻り値がなく、単に表示するだけなのvoidを使っている。
※実行してきちんと動くと、うれしい。

H18春FE午前
問12 空の状態のキューとスタックの二つのデータ構造がある。次の手続を順に実行した場合,変数xに代入されるデータはどれか。ここで,
データyをスタックに挿入することをpush(y),
スタックからデータを取り出すことをpop(),
データyをキューに挿入することをenq(y),
キューからデータを取り出すことをdeq() ,
とそれぞれ表す。

push(a)
push(b)
enq(pop())
enq(c)
push(d)
push(deq())
x←pop()

ア a  イ b  ウ c  エ d
正解は、イのbです。

実行結果を先に書きます。実際のプログラムは後半に記載します。
c:\pg>stack.exe
初期状態
スタックの状態:
キューの状態:

push(a) データ a をスタック(の最後)に挿入
スタックの状態:[a]
キューの状態:

push(b) データ b をスタック(の最後)に挿入
スタックの状態:[a][b]
キューの状態:

enq(pop()) スタック(の最後)からデータを取り出して、それをキュー(の最後)に挿

スタックの状態:[a]
キューの状態:[b]

enq(c) データ c をキュー(の最後)に挿入
スタックの状態:[a]
キューの状態:[b][c]

push(d) データ d をスタック(の最後)に挿入
スタックの状態:[a][d]
キューの状態:[b][c]

push(deq()) キュー(の先頭)からデータを取り出して、スタック(の最後)に挿入
スタックの状態:[a][d][b]
キューの状態:[c]

x = pop() スタック(の最後)からデータを取り出したデータを x とする
x の値: b
スタックの状態:[a][d]
キューの状態:[c]
続きを読む

↑このページのトップヘ