第6章 演習問題 解答例

6.1 標準入出力関数

a6-1-1.c

'.'を入力するまで、文字の入出力を繰り返すプログラムを作成してください。

/* a6-1-1.c */
#include <stdio.h>

int main(void)
{
    int c;

    while ((c = getchar()) != '.') {
        putchar(c);
    }

    return 0;
}

[Back]

a6-1-2.c

「 Ctrl+Z」キーを押すまで、入力した数字それぞれの個数を数えるプログラムを作成してください。

/* a6-1-2.c */
#include <stdio.h>

int main(void)
{
    int c, counter[10] = {0};

    printf("数字を入力してください。(終了条件:Ctrl+Z)\n");
    while ((c = getchar()) != EOF) {
        // 数字を数値に変換
        int n = c - '0';
        // 配列を超えないようにチェック
        if (n >= 0 && n <= 9) {
            // 数を数える
            counter[n]++;
        }
    }
    printf("\n入力した数字の個数\n");
    for (int i = 0; i < 10; i++) {
        printf("%d : %d個入力\t", i, counter[i]);
    }

    return 0;
}

10進数字は、'0'から'9'までが順に1ずつ増えるように文字コード化されることがANSIで定められています。そのため、'0'を引くと10進数値に変換することができます。a6-1-2.cでは、この変換した10進数値を配列の添字にし、入力した数字の個数を数えています。

[Back]

a6-1-3.c

「Ctrl+Z」キーが押されるまで文字列を入力し、入力文字列のスペースの箇所で改行して出力するプログラムを作成してください。

/* a6-1-3.c */
#include <stdio.h>

int main(void)
{
    char str[100];

    puts("文字列を入力してください。(終了条件:Ctrl+Z)");
    while (fgets(str, 100, stdin) != NULL) {
        puts("入力文字列をスペースで改行して出力します。");
        for (int i = 0; str[i] != '\0'; i++) {
            // スペースで改行
            if (str[i] == ' ') {
                putchar('\n');
            }
            // スペース以外はそのまま表示
            else {
                putchar(str[i]);
            }
        }
    }

    return 0;
}

[Back]

6.2 文字列操作関数

a6-2-1.c

文字列を3つ入力し、いちばん長い文字列を表示するプログラムを作成してください。

/* a6-2-1.c */
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str1[100], str2[100], str3[100];
    size_t len1, len2, len3;

    printf("文字列を3つ入力してください。\n");
    scanf("%99s%99s%99s", str1, str2, str3);

    len1 = strlen(str1);
    len2 = strlen(str2);
    len3 = strlen(str3);

    if (len1 >= len2 && len1 >= len3) {
        printf("いちばん長い文字列は\"%s\"です。\n", str1);
    }
    else if (len2 >= len1 && len2 >= len3) {
        printf("いちばん長い文字列は\"%s\"です。\n", str2);
    }
    else {
        printf("いちばん長い文字列は\"%s\"です。\n", str3);
    }

    return 0;
}

[Back]

a6-2-2.c

入力した文字列を文字型配列に指定文字数分コピーするプログラムを作成してください。このとき、指定文字数が文字型配列の大きさを超えないようにしてください。

/* a6-2-2.c */
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str_a[20] = "", str_b[100];
    int n;

    printf("文字列を入力してください。> ");
    scanf("%99s", str_b);
    printf("コピー文字数を入力してください。> ");
    scanf("%d", &n);
    if (n < (int)sizeof(str_a)) {
        strncpy(str_a, str_b, n);
        printf("コピー文字列 = %s\n", str_a);
    }
    else {
        printf("コピーできる文字数は%zu文字未満です。\n", sizeof(str_a));
    }

    return 0;
}

文字列のコピーや連結を行う場合には、配列の大きさを超えないように注意してください。

[Back]

a6-2-3.c

文字列Bに入力された文字列を、20文字ちょうどになるまで、文字列Aに連結するプログラムを作成してください。

/* a6-2-3.c */
#include <stdio.h>
#include <string.h>

#define LEN 20

int main(void)
{
    char str_a[LEN+1] = "";
    char str_b[LEN+1];

    while(strlen(str_a) < LEN) {
        printf("文字列を入力してください。> ");
        scanf("%20s", str_b);
        strncat(str_a, str_b, LEN - strlen(str_a));
        printf("文字列A = %s\n", str_a);
    }
    printf("文字列Aの長さ = %zu\n", strlen(str_a));

    return 0;
}

strncat関数は、文字列の長さが指定した文字数よりも小さい場合には、文字列分だけ連結します。そのため、
  strncat(str_a, str_b, LEN - strlen(str_a));
でstr_bの長さが「LEN - strlen(str_a)」よりも小さい場合には、str_bを文字列分だけ、つまり、すべて連結します。一方、大きい場合には「LEN - strlen(str_a)」だけ連結します。

[Back]

a6-2-4.c

文字列を5回入力して、いちばん大きな文字列を求めるプログラムを作成してください。

/* a6-2-4.c */
#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[100], max[100] = "";

    for (int i = 1; i <= 5; i++) {
        printf("文字列を入力してください。> ");
        scanf("%99s", str);
        if (strcmp(max, str) < 0) {
            strcpy(max, str);
        }
    }
    printf("いちばん大きな文字列は\"%s\"です。\n", max);

    return 0;
}

[Back]

6.3 文字操作関数

a6-3-1.c

ASCIIのうち印字の可能な文字を表示するプログラムを作成してください。なお、その際、英数字以外の文字は[]で囲んでください。

/* a6-3-1.c */
#include <stdio.h>
#include <ctype.h>

int main(void)
{
    for (int ch = 0; ch <= 127; ch++) {
        if (isprint(ch)) {
            if (isalnum(ch)) {
                printf("%c", ch);
            }
            else {
                printf("[%c]", ch);
            }
        }
    }

    return 0;
}

[Back]

a6-3-2.c

入力した文字列の中に英大文字がいくつ入っているか調べるプログラムを作成してください。

/* a6-3-2.c */
#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char str[100];

    printf("文字列を入力してください。> ");
    scanf("%99s", str);

    int count = 0;
    for (int i = 0; str[i] != '\0'; i++) {
        if (isupper(str[i])) {
            count++;
        }
    }
    printf("%sに大文字は%d個あります。\n", str, count);

    return 0;
}

[Back]

a6-3-3.c

入力した文字列の大文字は小文字に、小文字は大文字に変換するプログラムを作成してください。

/* a6-3-3.c */
#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char str[100];

    printf("文字列を入力してください。> ");
    scanf("%99s", str);

    for (int i = 0; str[i] != '\0'; i++) {
        if (islower(str[i])) {
            str[i] = toupper(str[i]);
        }
        else if (isupper(str[i])) {
            str[i] = tolower(str[i]);
        }
    }
    printf("変換文字列 = %s\n", str);

    return 0;
}

[Back]

6.4 数学関数

a6-4-1.c

直角三角形の辺aとbを入力し、辺cの長さを求めるプログラムを作成してください。

/* a6-4-1.c */
#include <stdio.h>
#include <math.h>

int main(void)
{
    double a, b, c;

    printf("辺a > ");
    scanf("%lf", &a);
    printf("辺b > ");
    scanf("%lf", &b);

    c = sqrt(a * a + b * b);
    printf("辺c = %f\n", c);

    return 0;
}

[Back]

a6-4-2.c

半径を入力し、球の体積を求めるプログラムを作成してください。

/* a6-4-2.c */
#include <stdio.h>
#include <math.h>

#define MPI 3.14159  //π

int main(void)
{
    double r, volume;

    printf("半径を入力してください。> ");
    scanf("%lf", &r);

    volume = 4.0 / 3.0 * MPI * pow(r, 3.0);

    printf("半径%fの球の体積は%fです。\n", r, volume);

    return 0;
}

[Back]

a6-4-3.c

三角形ABC において、辺b、辺c、角度A を入力し、辺a を求めるプログラムを作成してください。

/* a6-4-3.c */
#include <stdio.h>
#include <math.h>

#define MPI 3.14159  // π

int main(void)
{
    double a, b, c, angleA;

    printf("辺b > ");
    scanf("%lf", &b);
    printf("辺c > ");
    scanf("%lf", &c);
    printf("角度A > ");
    scanf("%lf", &angleA);

    a = sqrt(b * b + c * c - 2 * b * c * cos(angleA * MPI / 180.0));

    printf("a ≒ %f\n", a);

    return 0;
}

[Back]

6.5 一般ユーティリティ関数

a6-5-1.c

"end"が入力されるまでテストの点数を繰り返し入力し、0点から100点まで10点刻みで人数を調べるプログラムを作成してください。

/* a6-5-1.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    char str[20];
    int ten;
    int ninzuu[11] = {0};   // 人数を数える配列

    printf("点数を入力してください。(終了条件:\"end\")\n");
    while (1) {
        printf("> ");
        scanf("%19s", str);
        if (!strcmp(str, "end"))
            break;
        ten = atoi(str);
        if(ten >= 0 && ten <= 100) {
            ninzuu[ten/10]++;
        }
    }
    printf("100点は\t\t%3d人\n", ninzuu[10]);
    for (int i = 9; i >= 0; i--) {
        printf("%2d〜%2d点は\t%3d人\n", i*10, i*10+9, ninzuu[i]);
    }

    return 0;
}

ninzuu[ten/10]とすると、
 ninzuu[0]は0点〜9点、
 ninzuu[1]は10点〜19点、
 ninzuu[2]は20点〜29点、
  :      :
 ninzuu[9]は90点〜99点、
 ninzuu[10]は100点、
の人数を数えることができます。

[Back]

a6-5-2.c

コンピュータが出題する計算に答えるプログラムを作成してください。演算は2値a、bの加算、減算、剰余算とし、a、bは1〜100までの整数値でかつ(a >= b)の関係にあるものとしてください。

/* a6-5-2.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int a, b, c, result;

    srand((unsigned)time(NULL));

    a = rand() % 100 + 1;
    b = rand() % 100 + 1;
    if (a < b) {
        c = a;
        a = b;
        b = c;
    }

    switch (rand() % 3) {
        case 0:
            c = a + b;
            printf("%d + %d の結果は? > ", a, b);
            break;
        case 1:
            c = a - b;
            printf("%d - %d の結果は? > ", a, b);
            break;
        default:
            c = a % b;
            printf("%d %% %d の結果は? > ", a, b);
            break;
    }
    scanf("%d", &result);
    if (result == c) {
        printf("正解です。\n");
    }
    else {
        printf("不正解です。答えは%dです。\n", c);
    }

    return 0;
}

[Back]

a6-5-3.c

コンピュータとじゃんけんをするプログラムを作成してください。このとき、勝敗は2次元配列に格納した結果から得るようにしてください。

/* a6-5-3.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
/* 判定 0:あいこ 1:ユーザーの勝ち 2:ユーザーの負け */
    int table[3][3] = {
/* コンピュータ      グー チョキ パー */
/* ユーザー グー   */  {0,   1,    2},
/*          チョキ */  {2,   0,    1},
/*          パー   */  {1,   2,    0} };
    char ken[3][8] = {"グー", "チョキ", "パー"};
    char judge[3][14] = {"あいこ", "あなたの勝ち", "あなたの負け"};
    int user, computer;

    srand((unsigned)time(NULL));

    do {
        printf("じゃん、けん、ぽん!(1:グー 2:チョキ 3:パー) > ");
        scanf("%d", &user);
    } while (user < 1 || user > 3);
    user--;
    printf("あなたは%s\n", ken[user]);

    computer = rand() % 3;
    printf("コンピュータは%s\n", ken[computer]);

    printf("%sです。\n", judge[table[user][computer]]);

    return 0;
}
0:あいこ 1:ユーザーの勝ち 2:ユーザーの負け
と仮定すると、次のような2次元配列を使って勝敗を判定することができます。
コンピュータグーチョキパー
[0][1][2]
ユーザーグー[0]012
チョキ[1]201
パー[2]120

[Back]


Copyright© 2021 Tomoko Sugawara. All Rights Reserved.