sasasa_999
@sasasa_999 (sawada rie)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

C言語の課題がわからないです。

Q&A

大学の課題でプログラム作成の課題を出されたのですが、わからず進んでいません。
ご教授いただけると幸いです。

課題内容

添付のプログラムをもとに,
以下の仕様のプログラムを作成せよ.

入力した文字列を以下の4種類に分けた文字列を作成する関数を作成し,
実行結果とともに提出せよ.

種類
1.アルファベット大文字
2.アルファベット小文字
3.数字文字
4.それ以外の文字

添付資料

//内容:文字列から,アルファベットを分離する関数と
//     その使用方法など.
#include <stdio.h>
#include <string.h>

#define LEN 101

int Alp(const char str[], char alp[]);

int main(void) {
    char str[LEN], alp[LEN];
    int len;

    printf("文字列:");
    scanf("%s", str);

    len = Alp(str, alp);

    printf("%s[%d] -> %s[%lu]\n", str, len, alp, strlen(alp));

    return (0);
}

//関数名 Alp
//ヘッダ なし(stdio.h)
//形 式 int Alp(const char s[], char a[]);
//引 数 文字列,アルファベットだけの文字列
//返却値 文字列sの長さ(整数方)
//解 説 文字列sのアルファベットだけを,文字列aへコピーする.
int Alp(const char s[], char a[]) {
    int i, j = 0;

    for (i = 0; s[i] != '\0'; i++) {
        if (('a' <= s[i] && s[i] <= 'z') || ('A' <= s[i] && s[i] <= 'Z')) {
            a[j++] = s[i];
        }
    }
    a[j] = '\0';

    return (i);
}

/* 実行結果

*/
0

6Answer

はっきり言いますと、学校で聞くべきだと思います。
学校の講師は、授業内容の復習や理解度の確認のために課題を課しているからです。第三者が迂闊に答えを教えてしまうと、カリキュラムの妨害にもなりかねませんし、おそらくあなたの為になりません。理解しないまま、今後更に授業内容は難しくなっていく事でしょう。

具体的に、何が分からないのかを明確にしてください。
各文字の判定方法?それとも、if文や論理演算子の意味が分からない?
(後者だと、この課題以前にC言語の初歩からの復習です)

とりあえず、マルチバイト文字やそういったものを考慮しろとは書かれていないので、文字は全てASCIIコードであるという前提で話をします。

ASCIIコード表

まず、文字は数値で表す事ができ、各数値に対してどの文字が割り当てられているかをASCIIコード表で確認する事が出来ます。

関数Alpが、課題を解くためのヒントになっていると思われますが、
何故Alpがアルファベットだけをコピーする動作になるのかは判りますか?

if (('a' <= s[i] && s[i] <= 'z') || ('A' <= s[i] && s[i] <= 'Z'))

上記はAlpの文字判定を行っている箇所ですが、ASCIIコード表を見ると分かるように、a~z、A-Zはコード上で連続して並んでいます。なので、文字がその範囲内にあるか比較判定すれば、アルファベットと見做せる訳です。

アルファベット大文字小文字を判定するのも、数値を判定するのも、あとは同様に範囲を変えて比較判定すれば、同じようなやり方で出来る筈です。

4Like

charの配列の変数を4つ作り、forで回した入力をifで分岐させて一文字づつ対応した配列に入れましょう。
ifの条件はサンプルにある通り、小文字ならa以上z以下のように、数字も大文字も同じように判定できます。

このくらいの課題ですと伝えるためにコードを書くとそのまま答えになってしまいます。
まだわからなければ、何が分からないのかもう少し細分化してみましょう。

1Like

This answer has been deleted for violation of our Terms of Service.

学生さん、がんばってくださいませ。

「どこから手に付けたらいいのか分からない」場合、
「何が分かってて、何が分からないか」をリストアップするといいです。

元々のテストプログラムでわかる事。

  • 元となる文字列を受けつける。
  • アルファベットの小文字、大文字だけを抽出した文字列を書き出す

今回要望されていることは?と考えるとこんな感じです。

  • 元となる文字列を受けつける。★使いまわせる
  • 4種類の文字列を書き出す
    • アルファベット小文字だけ ★やや使いまわせる
    • アルファベット大文字だけ ★やや使いまわせる
    • 数字だけ ☆新しいロジックが必要
    • どれにも該当しない ☆同上

<補足>

あとは、「最終的な結論」ではなく、小さいゴールをこなしていくといいと思います。

例えば、以下のステップに分けて試すといいと思います。

  • サンプルコードを動かす
  • 「アルファベット大文字」だけ抽出に改造
  • 「アルファベット小文字」だけ抽出に改造
  • 「アルファベット大文字と、小文字」を抽出に改造
  • 「数字」だけ抽出に改造
  • 「アルファベット大文字と小文字、数字」を抽出に改造
  • 「アルファベット大文字と小文字、数字、それ以外」を抽出に改造

</補足>

どうしても分からない場合には下記を参考ください。ただし、コンパイルもしてないので動かないと思いますが。

修正イメージ(クリックで展開する)
/**
 * [in] str[]  入力文字列
 * [out] ALP[] アルファベット大文字のみを抽出した文字列
 * [out] alp[] アルファベット小文字のみを抽出した文字列
 * [out] num[] 数字のみを抽出した文字列
 * [out] oth[] それ以外を抽出した文字列
 */

int ALPalpNumOth(const char str[], char ALP[], char alp[], char num[], char oth[] );

int main(void) {
    char str[LEN], ALP[LEN], alp[LEN], num[LEN], oth[LEN] ;
    int len;

    printf("文字列:");
    scanf("%s", str);

    len = ALPalpNumOth(str, ALP, alp, num, oth);

    printf("%s[%d] -> %s[%lu] %s[%lu] %s[%lu] %s[%lu]\n",
        str, len, 
        ALP, strlen(ALP),
        alp, strlen(alp),
        num, strlen(num),
        oth, strlen(oth) );

    return 0;
}


int ALPalpNumOth(const char str[], char ALP[], char alp[], char num[], char oth[] ){
    int i;

    int j_ALP = 0;
    int j_alp = 0;
    int j_num = 0;
    int j_oth = 0;

    for (i = 0; s[i] != '\0'; i++) {
        if ('A' <= s[i] && s[i] <= 'Z') { // アルファベット大文字だけ
            ALP[j_ALP++] = s[i];
        }
        else if ('a' <= s[i] && s[i] <= 'z') { // アルファベット小文字だけ
            alp[j_alp++] = s[i];
        }
        else if ('0' <= s[i] && s[i] <= '9') { // 数字だけ
            num[j_num++] = s[i];
        }
        else { // どれにも属さない
            oth[j_oth++] = s[i];
        }
    }

    /* 文字列の終端文字を追加 */
    ALP[j_ALP] = '\0';
    alp[j_alp] = '\0';
    num[j_num] = '\0';
    oth[j_oth] = '\0';

    return i;
}
0Like

添付資料

  • 文字列長をint型で扱ってますがプログラム中で使用してるstrlen()に合わせてsize_tを使用した方が良いでしょう。printf()でのsize_tの書式はluではなくてzuなのでそこも修正しましょう。
  • C言語では'a'~'z'や'A'~'Z'の文字コードが連続することを保証しません。標準ライブラリにアルファベット文字であるかの判定を行うisalpha()が用意されているのでこれを使うべきでしょう。

ちょっと気になったので直してみました。

//内容:文字列から,アルファベットを分離する関数と
//     その使用方法など.
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define LEN 101

size_t Alp(const char str[], char alp[]);

int main(void) {
    char str[LEN], alp[LEN];
    size_t len;

    printf("文字列:");
    scanf("%s", str);

    len = Alp(str, alp);

    printf("%s[%zu] -> %s[%zu]\n", str, len, alp, strlen(alp));

    return 0;
}

//関数名 Alp
//ヘッダ なし(stdio.h)
//形 式 size_t Alp(const char s[], char a[]);
//引 数 文字列,アルファベットだけの文字列
//返却値 文字列sの長さ(size_t型)
//解 説 文字列sのアルファベットだけを,文字列aへコピーする.
size_t Alp(const char s[], char a[]) {
    size_t i, j = 0;

    for (i = 0; s[i] != '\0'; i++) {
        if (isalpha(s[i])) {
            a[j++] = s[i];
        }
    }
    a[j] = '\0';

    return i;
}

/* 実行結果

*/
0Like

This answer has been deleted for violation of our Terms of Service.

Your answer might help someone💌