joho1-2017の日記

joho1-2017の日記

情報処理実習1の解説ブログです.皆さんが課題を解く時の助けになれば幸いです.

配列と文字列

第7回の授業では,5組は関数について勉強しました.
関数のまとめについては,本ブログの関数のページを確認してください.

6組の授業では,配列と文字列について勉強しました.
配列のまとめについては本ブログの第6回 データ型 配列のページを確認してください.

文字列
文字列も配列の1種です.char型で宣言する事で文字が並び,文字列となります.
文字列に関しては,文字数+ヌル文字が要素数になることに注意しましょう.
文字列操作関数については,講義ページやインターネットで調べてみましょう.

以上で講義の解説は終了です.以下,課題の考え方です.


5組
1.摂氏温度を華氏温度に変換する関数c2fをつくりなさい. 引数として実数1個,戻り値も実数とする.
main関数を作成し,関数を呼び出して正しく動作するかチェックすること.
(摂氏=Celsius度,華氏=Fahrenheit度の意味や変換方法は,各自で調べること.)

#include...

??? c2f(...)
{
    ....
    return ???;
}

int main(void)
{
    float T;  /* 温度を格納 */
    printf(...);
    scanf(...);
    
    printf("摂氏 %f 度は,華氏 %f 度です.\n", T, c2f(T) );
    return 0;
}

この課題のポイントは
 ①関数の型と引数
です.関数内にreturn文があるということは,返り値があるということです.また,printf()を見ると,関数c2f()は%fに対して代入していて,引数にはTを代入していますね.ということは,型と引数はこれに合わせると良いわけです.今回の課題において,①は全てに共通したポイントになるので,課題2以降ではポイントには書きません.

2.1からnまでの整数の和 ∑n を計算する関数 Sum を作成しなさい.

#include...
	
??? Sum(...)
{
    ....
    return ???;
}
	
int main(void)
{
    int n;
    printf(...);
    scanf(...);
	
    printf("1から %d までの和は %d です.\n", n, Sum(n) );
    return 0;
}

この課題のポイントは,
 ①関数内での引数の使用方法
です.①については,今回の課題は和の計算なので,おそらく繰り返し計算をすると思います.そして,その繰り返しの終点を関数Sum()の引数で指定しているわけです.つまり,繰り返し計算の終了判定に使えば良いわけですね.

3.キーボードから和暦(平成??年)の整数の数値を渡すと,西暦に変換して返す関数wa2seiを作りなさい.
キーボードからの入力および結果の画面への表示は全て main 関数内で行うこと.

実行例:
和暦を入力してください(平成):28
平成 28 年は,西暦2016年です.

この課題のポイントは,
 ①和暦から西暦への変換
です.このぐらいの問題であれば,ググッた方が早いと思います.そして,returnには西暦を返せば良いわけです.

4.整数を引数として,引数が素数かどうかを判定する関数 IsPrime() 関数を作成しなさい.
関数 IsPrime 内では,素数の判定のみ行い,画面表示などは全て main 関数内で行うこと.
戻り値の意味などは各自で設定して良いが,コメントとしてソースコード中に記述しておくこと.
(例えば,素数の場合の関数の戻り値は0,それ以外は1とする,など.)

#include...
	
??? IsPrime(...)
{
    ....
    return ???;
}
	
int main()
{
    int n;       /* 整数を格納 */
    printf(...);
    scanf(...);
	
    ....
}

この課題のポイントは,
 ①素数の判定
です.素数とは,条件「1とその数自身以外の数では割り切れない数」を満たす数のことですね.と言うことは,入力された数nを1からnまで割っていき,余りが0になる数をカウントしていき,上述の条件を満たす時,素数であることを示す返り値を与えれば良いわけです.

5.三つの実数を引数に取り,それらの中央値(メディアンという)を返す関数 median を作成せよ.
main関数を用いて確認すること.

#include...
	
??? median(...)
{
	....
	return ???;
}
	
int main()
{
    printf(...); scanf(...);	
    ....
}||<
>||
実行例:
a= 10.5
b= -3.9
c= 0.3
中央値は 0.3 です.

この課題のポイントは,
 ①中央値の判定
です.今までの条件処理を思い出せばさほど難しい判定ではないと思います.今回のように実数が3つと決まっているのならば,全ての大小関係を比較して,中央値を見つけるのが1番楽かと思います.

以上で5組の課題の考え方については終了です.


6組
1. 1次元配列を作り,その中にキーボードから入力した英文を格納します. 英文は複数の単語がスペースで区切られているものとします. この文から,単語を一つずつ抜き出して,別の1次元文字配列にコピーし,画面に表示しなさい. プログラム名を,学籍番号10桁-07-1.cppとする.
英文の格納はscanfを使います.ここではスペースも読み取りたいので,授業中に説明したスキャン集合指定子を使えばいいですね.格納された文字列を1文字ずつfor文で見ていき,それがスペースであるところまで別の文字配列に格納していきます.スペースかどうかの判断については,前回のデータ型の回を参考にしてください.

for(入力された文字列の先頭から終わりまで){
    if(スペースでなかったら){
        格納;
    }else if(...){
        ...;
        ...;
    }
}

2. 複数の単語からなる文を入力すると,各単語の先頭文字を大文字に変えて表示するプログラムを作成せよ.

//実行例
> here is meiji university.
Here Is Meiji University.

この問題を解く上でのポイントは,

1.どのようにスペースありで文字列を入力するか?
2.どのように単語の先頭の文字を判別するか?
3.どのように小文字を大文字に変換するか?

の3点かと思います.

まず,1.に関して,皆さんはキーボードからの何かを入力して処理を行う時には,「scanf」関数を利用していると思います.実際に試してみた人はお気づきかと思いますが,今まで通り,

char str[1024];
scanf(%s, str);

のように書くと,スペースありの文字列を入力するとその手前までで切れてしまうと思います.
これを回避するためには,スキャン集合指定子を利用しましょう.


次に,2.ですが,これに関しては,私は,「スペースの次の文字が単語の先頭である(文字列全体に一番最初の文字は必ず単語の先頭である).」という条件でどの文字が単語の先頭かを判別しました.

これをプログラムにすると,入力された文字列はstrという変数に格納されているので,

for(int i =0; str[i]!=0; i++){
    
}

この処理でstr内の文字1つ1つについて考えることができ,

for(int i =0; str[i]!=0; i++){
    if(i==0){
        文字列の最初だから,単語の最初
    }
    else{
        if(str[i-1]==' '){
            str[i]はスペースの次の文字だから単語の先頭である
        }
    }
}

というような処理で,単語の先頭の文字を見つけることが出来ます.

最後に,3.の小文字を大文字に変換することについてですが,これはアスキーコードをもとに考えることですぐに解決することが出来ます.
アスキーコードでは,大文字と小文字の間には「32」の数の違いがあるので,これを考慮すると,

char komoji_to_omoji(char c){
    if(小文字なら){
        return (c - 32);
    }else{
        return c;
    }
}

という関数で変換することが可能です.
これらを組み合わせれば,課題2は上手く動くプログラムが作成できると思います.

3. 1次元配列をつくり,その中にいろいろな文字列をキーボードから入力してください. 入力が終わったら入力された文字列が画面に表示されるようにして下さい. プログラム名を学籍番号10桁-07-3.cppとする.

今回の課題はこの3番から解き始めるといいと思います.全体像は以下のようになるかと思います.

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

void input(...)
{
	printf("Type a string: ");
	scanf(スペースも読み取れるように);
}

void disp(...)
{
	...;
}

int main()
{
	char str[512];

	input(str);
	disp(str);

	return 0;
}

4. 前のプログラムに機能を追加して,入力した文字をABC順に並べ替えてみよう. プログラム名を学籍番号10桁-07-4.cppとする.
ABC順は前回登場したASCIIコードに並び替えてください.ASCIIコード表においてA-zは連続した数値となっているので,数値の並びかえと同様に並び替えることができます.

//数字が格納された配列を小さい順に並び替える
int src[10] = { 3, 5, 2, 9, 1, 8, 4, 7, 6 };
int sorted[10];
for(...){
    sorted[i] = src[i];
}
for(...){
    for(...){
        if(sorted[i] < sorted[j]){
            ...;
            ...;
            ...;
        }
    }
}

以上で課題の解説は終わりです.
少しずつ難しい内容になってきているので,ついていけなくなってしまう前に,ブログでの質問やオフィスアワーを有効に活用しましょう.
次回は今までの内容のおさらいになります.わからない部分がある人はここでしっかり理解するようにしてください.
それでは課題提出頑張ってください.

Remove all ads