情報処理4レポート課題(8)

更新:2008年11月10日


  1. 次のプログラムは「1行に国名と地域名が記述されているテキストファイルから、 国名と地域名を独立に文字型配列に格納して画面表示します。
    file_fgets_sscanf_buffer.c
    #include<stdio.h>
    #include<stdlib.h>
    
    #define BUF_SIZE	1024
    #define NATION_SIZE	20
    #define REGION_SIZE	20
    
    int main(void){
    	FILE *fp;
    	char *ch_fgets;
    	int ch_sscanf;
    	char region[REGION_SIZE], nation[NATION_SIZE];
    	char buf[BUF_SIZE];
    
    	fp=fopen("for_file5.5.1buffer.txt", "r");
    	if(fp==NULL){
    		printf("Can't Open File\n");
    		exit(1);
    	}
    	while(1){
    		ch_fgets=fgets(buf, BUF_SIZE, fp);
    		if(ch_fgets==NULL){
    			break;
    		}
    		ch_sscanf=sscanf(buf, "%s%s", 
    			nation, region);
    		if(ch_sscanf!=2){
    			printf("Read Error\n");
    			break;
    		}
    		printf("%s\t%s\n", nation, region);
    	}
    	fclose(fp);
    	return 0;
    }
    
    for_file5.5.1buffer.txt
    Algeria	Africa
    Argentina	Latin-America
    Australia	Oceanea
    Austria	Europe
    Bangladesh	Asia
    Belgium	Europe
    Bolivia	Latin-America
    Brazil	Latin-America
    Bulgaria	Europe
    Burkina-Faso	Africa
    Cameroon	Africa
    Canada	North-Americal
    Chile	Latin-America
    China	Asia
    Colombia	Latin-America
    Cote-d'Ivoire	Africa
    Denmark	Europe
    Ecuador	Latin-America
    Egypt	Africa
    Ethiopia	Africa
    Finland	Europe
    France	Europe
    Germany	Europe
    Ghana	Africa
    Greece	Europe
    Guatemala	Latin-America
    Hungary	Europe
    India	Asia
    Indonesia	Asia
    Iran	Asia
    Ireland	Europe
    Israel	Asia
    Italy	Europe
    Japan	Asia
    Kazakstan	Asia
    Kenya	Africa
    Korea(South)	Asia
    Kuwait	Asia
    Madagascar	Africa
    Malawi	Africa
    Malaysia	Asia
    Mali	Africa
    Mexico	Latin-America
    Morocco	Africa
    Mozambique	Africa
    Nepal	Asia
    Netherland	Europe
    New-Zealand	Oceanea
    Niger	Africa
    Nigeria	Africa
    Norway	Europe
    Pakistan	Asia
    Peru	Latin-America
    Philippines	Asia
    Poland	Europe
    Portugal	Europe
    Rumania	Europe
    Russia	Europe
    Singapore	Asia
    South-Africa	Africa
    Saudi-Arabia	Asia
    Spain	Europe
    Sri-Lanka	Asia
    Sweden	Europe
    Switzerland	Europe
    Tanzania	Africa
    Thailand	Asia
    Tunisia	Africa
    Turly	Asia
    Uganda	Africa
    Ukraine	Europe
    U.K.	Europe
    U.S.A.	North-America
    Venezuela	Latin-America
    Vietnam	Asia
    Yemen	Asia
    Zambia	Africa
    Zimbabwe	Africa
    
    本来、文字型配列の大きさは十分に確保しておく必要がありますが、 十分に確保できていなくてもコンパイルエラーになりませんし、 実行時に必ずエラーになる訳でもなく、 密かに不思議な挙動を示している場合があり、 誤りが見つけにくくなります。 ここでは、 十分に確保できていない場合にどのような挙動を示すかを確認します。
    1. 国名用の要素数を減らしていって画面表示に異常を来すことを確認してください。
    2. 次の文章の(a)から(c)までに適切な問言を挿入して下さい:

      for_file5.5.1buffer.txtの1列目,すなわち, nationに格納される国名の最大長は(a)なので, 終端文字を含めて(b)個の要素が確保されていれば 正常に動作するはずです.

      逆にいえば,nationの要素数を(c)以下にしたら 何か不具合があってもおかしくありません.

    3. 国名用の要素数を変化させていったときに, nationとregionの先頭アドレス,その差がどうなるかについて, 次の表を埋めて下さい.
      国名用の要素数regionの先頭アドレスnationの先頭アドレスregionの先頭アドレスとnationの先頭アドレスとの差
       1   
       2   
       3   
       4   
       5   
       6   
       7   
       8   
       9   
       10   
       11   
       12   
       13   
       14   
       15   
       16   
       17   
    4. 次の(a)から(z)および(alpha)から(zeta)までに適切な問言を挿入して下さい.

      nationの要素数を2に設定し,AlgeriaとAfricaを読み込んだ場合の動作を説明します. sscanf関数によってあるアドレスから順に 文字(a),(b),(c),(d),(e),(f),(g),(h)が格納されていき, nationから(i)バイト後ろから 文字(j),(k),(l),(m),(n),(o),(p)が格納されていきます. よって, 文字(q),(r),(s),(t),(u),(v)が格納された場所に 文字(w),(x),(y),(z),(alpha),(beta)が上書きされたことになります. printf関数でnationを画面表示する際には, nation[(gamma)]に格納されている文字(delta)から文字(epsilon)の直前までの 文字列(zeta)が表示されることになります.

    5. 異常表示の原因を説明してください。 (ヒント: (0)sscanf関数の%s変換は文字列を格納するもので、 先頭文字から区切り文字(空白文字や改行)の直前までを、 指定されたアドレスから順次格納していきます。 このときsscanf関数は、格納先である文字型配列の要素数が幾つかを一切気にしていません。 (1)printf関数の%s表示は文字列を表示するもので、 指定された文字列の先頭(アドレス)から終端文字の直前までをそれぞれ文字として表示しようとします。(2)文字型配列も配列の一種で、要素数分の領域がメモリ内に連続して確保されます。)
    6. このような誤りを完全に防ぐためには、 sscanf関数を用いて入力する文字型配列の要素数をどのように決めれば良いかを 考察してください。

    提出内容は問題本文・解答・考察・感想・作業時間です。

    提出先アドレスを誤らないように気をつけて下さい。

    Subjectは半角英数・アンダースコア・空白のみで構成し、 学番・氏名・第8回レポート課題であることが分かるように。

    問題1-1,1-2,1-3については,11月11日24:00までに 受信履歴に掲載されるようにして下さい。

    問題1-4,1-5,1-6については,11月17日24:00までに 受信履歴に掲載されるようにして下さい。


    何かありましたら、 まで。