プログラミングC 平成27年度中間試験 平成27年11月20日 3限 注意事項 問題用紙は表紙を含めて両面刷り6枚(12ページ)である。解答用紙は片面刷り4枚である。試 験開始と共に問題用紙・解答用紙を確認し、乱丁・落丁などあれば直ちに申し出る事。 解答用紙の各ページそれぞれに学籍番号と氏名を記入すること。 解答時間は13:20~14:40の80分間とする。 解答開始の指示があるまで、表紙の注意を良く読む事。ただし中の問題を見てはならない。 途中退席は開始後40分 (14:00)まで認めない。 筆記具のみを机の上に置くことができる。 机の中には一切ものを入れてはならない。 携帯電話は電源を切り、鞄の中に入れておくこと。着信音が鳴った場合は不正とみなす。 演習室で受験する学生は、必ずワークステーションからログアウトし、ディスプレイの電源を消し ておかなければならない。 すべての不正行為に対して断固たる処置を行う。 なお、下例のように、実行例を表示する際にはコンピュータの表示は普通の文字、キーボードからの 入力は太字斜体にて表示する。 % ./a.out Enter your name -> Aizu Taro -1- 問題 1 以下のプログラムの出力を答えよ。 解答の際、Solaris か Mac のどちらかのシステムを想定し、解答欄の想定システムに○を付けて選択す ること。(選択していない場合は、システムによって出力が変わる問題の採点がされない) 。 プログラム #include <stdio.h> #include <string.h> int main() { char str1[16]= "Science"; char str2[] = "Engineering"; char *edu[] = {"Programming", "English", "Mathematics"}; char *p; int i; printf("(1) printf("(2) printf("(3) printf("(4) %d\n", %d\n", %d\n", %d\n", sizeof(str1)); sizeof(str2)); sizeof(edu)); sizeof(edu[0])); printf("(5) %d\n", strlen(str1)); printf("(6) %d\n", strlen(edu[0])); p = str1; printf("(7) %s\n", p+3); printf("(8) %c\n", *(p+1)); printf("(9) %c\n", *p+1); p=str2+5; printf("(10) %s\n",p); printf("(11) %c\n",p[4]); str1[3] = '\0'; printf("(12) %s\n",str1); } return 0; -2- 問題 2 問2-1 下記のプログラムの出力を解答せよ。 プログラム #include <stdio.h> int accm(int); int num; int main(){ int i,j=1; } num=1; for(i=0;i<4;++i){ j = accm(j); } return 0; int accm(int in){ static int s=0; int i=0; s+= in; i+= in; printf("in=%d, s=%d, i=%d, num=%d\n",in, s, i, num); num+= 2; } return in+1; 問2-2 上記のソースコードで使われている変数(num, main 中の i,j と accm 関数中の in,s,i)について、 以下の条件に該当する変数全てに○を付けなさい。なお、答えは1つとは限らない。 (1) 自動変数 (2) 静的変数 (3) 外部変数 (4) 関数の仮引数 (5) 生存期間が関数 accm の実行中のみである変数 (6) 関数内を実行中に accm から参照できる変数 -3- 問題 3 学籍番号と成績からなるファイルがある。以下は、このファイルをコマンドライン引数に指定して読み 込み、上位者 5 名を降順(大きい順)に並べ、表示するプログラムである。配列 list 内には、成績上 位者の要素番号が格納され、list[0]が最高点の人の要素番号、score[list[0]]がその点数を示すこ とになる。list の内容は、i 番目の人の成績と list 内の成績上位者の点数とを比較し、i 番目の成績 が大きい場合、ins_list 関数を利用し、list のその場所に i を挿入することで作成している。実行例 やプログラム中のコメントを参考に、下線部を埋めて完成させなさい。なお、データの最大数と表示す る上位者の人数はそれぞれマクロ MAX と NO で指定され、エラーメッセージや使用方法は標準エラー出 力に出力するものとする。また、同じ番号の下線部には同じ内容が入る。 実行例 % cat score.dat s27001 43 s27002 54 s27003 86 s27004 72 : : % ./a.out Usage : ./a.out datafile % ./a.out score.dat No.1 : s27012 91 No.2 : s27015 89 No.3 : s27003 86 No.4 : s27011 84 No.5 : s27007 83 % プログラム #include <stdio.h> #include <stdlib.h> #define MAX 300 #define NO 5 void ins_list(int *, int, int); int main(int argc, char *argv[]) { FILE *fp; char id[MAX][10]; /* 学籍番号 */ int score[MAX]; /* 点数 */ int list[NO]; /* 成績上位者の要素番号が入る(降順) */ int i,j,k,n; /* 一時変数(i,j,k)と読み込んだデータ数(n) */ /* データファイルが指定されているかチェック */ if (____(1)____) { fprintf(____(2)___, "Usage : ./a.out datafile\n"); exit(1); } -4- /* ファイルを開く */ fp=fopen(____(3)____,"r"); if (____(4)____) { fprintf(____(2)____, "file open error:%s\n", ____(3)____); exit(2); } /* データの読み込み */ for (i=0; i<MAX; i++) { if (fscanf(fp,"%s%d",________(5)________)==EOF) break; } n=i; /* 読み込んだデータの個数を設定 */ fclose(fp); /* 成績上位者リストの初期化 */ /* (初期値として0番目の人が上位者とされる) */ for (j=0; j<NO; j++) list[j]=0; /* main process */ for (i=1; i<n; i++ ) /* 1番目から処理を開始 */ { for (j=0; j<NO; j++) { k=list[j]; /* 上位者の要素番号 */ if (________(6)________) { /* 上位者リストの成績とを比較 */ ________(7)________; /* list 配列中の j 番目に i を挿入する */ break; } } } /* 成績上位者の表示 */ for (j=0; j<NO; j++) { k=list[j]; /* 上位者の要素番号 */ printf("No.%d : %s %3d\n",j+1, ________(8)________); } } return 0; /* list 配列の st 番目に index を挿入する関数 */ void ins_list(int *list, int st, int index) { int j; } /* 挿入するために st 以降の要素を後ろにずらす */ for (________(9)________ j--) { list[j] = ________(10)________; } list[st]=index; /* 挿入 */ -5- 問題 4 下記のプログラムの出力値を解答せよ。2 次元配列内は隙間なく格納されていることを保証する。 プログラム #include <stdio.h> #define NROW 3 #define NCOL 6 int main(){ int num1[10] = {5, 4, 3, 2, 1, 9, 8, 7, 6, 5}; int num2[NROW][NCOL] = {{2, 4, 6, 8, 10, 12}, {3, 2, 1, 3, 2, 1}, {1, 2, 3, 4, 5, 6}}; int *p, *q, i, s=0; p = &num1[4]; printf("(1) %d\n", *p); printf("(2) %d\n", *p++); printf("(3) %d\n", *(p-3)); printf("(4) %d\n", *(p+2)); p+=2; printf("(5) %d\n",*p); printf("(6) %d\n",*p+2); p = &num2[2][0]; printf("(7) %d\n", *(p+4)); printf("(8) %d\n", *(p-2*NCOL)); p = &num2[0][2]; printf("(9) %d\n", *(p+4)); printf("(10) %d\n", *++p); printf("(11) %d\n", *p+3); } p = num1; q = &num2[1][3]; for ( i=0; i<6; i++ ){ s += *p + *q; p++; q++; } printf("(12) %d\n", s); return 0; -6- 問題 5 標準入力から英単語を読み取り、単語を表示するプログラムを作成する。このプログラムは、英単語をす べて読み取った後、文字数が最も多い単語とその文字数を表示し、さらに最も長い単語以外のすべての 単語を表示する。この際、 入力される単語の数は 1024 単語以下 入力される単語は英小文字で構成されている 入力される単語は空白で区切られている 入力される単語の長さは 255 文字以内 最も長い単語が複数ある場合、最初に現れた単語を採用する Ctrl-d(または EOF)が入力されたら終了 とする。 実行例を参考にしながら空欄を埋め、このプログラムが目的の動作をするよう、下線部を埋めよ。 実行例 %./a.out a class of the students by the students for the students Ctrl-d Longest word: students Length: 8 a class of the by the for the %./a.out a class of the teachers by the teachers for the students Ctrl-d Longest word: teachers Length: 8 a class of the by the for the students プログラム #include <stdio.h> #include <string.h> #define MAXWORD 1024 #define MAXCHAR 256 int main(){ int char char int int int maxlen=0; /*単語の最大長*/ maxstr[MAXCHAR]; /*最大長の単語*/ words [MAXWORD][MAXCHAR]; /*標準入力から読み込んだ単語*/ len; /*調査する単語の長さ*/ wordno=0; /*読み込んだ単語の数*/ i; maxstr[0]=__(1)__; /*文字列を空にしておく*/ /* 標準入力から単語を読み込む */ while(scanf("%s",words[wordno])!=EOF){ ____(2)____; } -7- /*最長かつ最初に現れた単語を記録する */ for(i=0; i<wordno; ++i){ len = ____(3)____; /* len に i 番目の単語の長さを格納 */ if(len>maxlen){ ______(4)______; /* maxstr に i 番目の単語を格納 */ ______(5)______; } } /*最長かつ最初に現れた単語を表示*/ printf("Longest word: %s\n",maxstr); printf("Length: %d\n",maxlen); for(i=0; i<wordno; ++i){ /*最長かつ最初に現れた単語でなければ表示*/ if(______(6)______){ printf("%s ", words[i]); } } printf("\n"); } return 0; -8- 問題6 英文文章のテキストファイル spim.txt を読み、そのテキスト中の各母音と子音の出現数を表示するプロ グラムを作成する。母音とはアルファベットの[a, i, u, e, o]のことであり、子音とは母音以外のアル ファベットのことである。大文字小文字は区別しないこととする。この問題では引数を大文字から小文 字に変換して返す、ライブラリ関数 tolower()を使う。下線部を埋めプログラムを完成させよ。 実行例 % ./a.out a:14 i:14 u:7 e:15 o:12 Consonant:106 % [spim.txt] SPIM/SAL is a port, to the Apple Macintosh Personal Computer, of SPIM, a MIPS R2000/3000 simulator that was written by James Larus for instructional use at the University of Wisconsin Computer Sciences Department. プログラム #include #include #include #include <stdio.h> <ctype.h> <stdlib.h> <string.h> /* tolower のために include */ /* exit のために include */ /* strlen のために include */ #define MAX 1000 _____(1)_____; /* プロトタイプ宣言 */ char vowel[5] = {'a', 'i', 'u', 'e', 'o'}; /* a i u e o で初期化 */ int main(){ int i, vowelConsCnt[6] = {0, 0, 0, 0, 0, 0}; char c,words[MAX]; FILE *fp; /* a i u e o と子音の出現数 */ fp = fopen(_____(2)_____); if(fp == NULL){ printf("FileNotFound.\n"); exit(1); } for(i = 0; i < MAX; i++){ /* 1 文字づつ配列 words に格納する */ if(fscanf(_____(3)_____) == EOF) break; /* EOF になるまで 1 文字読む */ words[i] = tolower(c); /* 小文字に変換し、格納する */ } ___省略____ /* 文字列 words の最後尾を null 文字とする */ _____(4)_____; /* 関数 VowelCount の呼び出し */ -9- for(i = 0; i < 5; i++){ /* 結果を出力する */ printf(_____(5)_____); } printf("Consonant:%d\n",vowelConsCnt[5]); fclose(fp); return 0; } /* 母音かどうかを調べ、カウントする関数 第 1 引数: 調べる文字配列 第 2 引数: 各母音と子音の出現数(結果) 各母音の出現数は[0]が a, [1]が i, [2]が u, [3]が e, [4]が o, [5]が子音の出現数である。 */ void VowelCount(char* str, int* vowelConsCnt){ int i, j, cnt, flag; cnt = _____(6) _____; /* 文字配列の長さを求める*/ } for(i = 0; i < cnt; i++){ flag = 0; /* 母音かどうかを判定するフラグを初期化 */ for(j = 0; j < 5; j++){ /* 文字が母音かどうかを調べる */ if(_____(7)_____){ vowelConsCnt[j]++; flag = 1; } } if(_____(8)_____){ /* 母音でなかった時 */ if(_____(9)_____){ /* 文字がアルファベット小文字ならば */ vowelConsCnt[5]++; } } } - 10 - 問題 7 以下は、2人のプレイヤーで行う英単語のしりとりゲームのプログラムである。プレイヤー1、2がそ れぞれ交互に単語を入力するが、辞書に存在しない単語や既に入力済の単語、しりとりになっていない 単語については得点にならず、次のプレイヤーに入力権が移る。単語はすべて小文字で入力され、最初は apple から始まる。Ctrl+d が入力された時の得点に応じて勝敗が表示されるが、プログラムには複数の 間違いがあり、正しくコンパイル/実行ができない。 プログラム中のコメントも参考に、誤りを修正し、完成させなさい。ただし、変数宣言および表示文に は間違いがないものとする。なお、修正箇所は最小行数の変更とし、 「行番号 修正後の記述」のように 書くこと(行の追加は認めない) 。 (例: 「20行目 if (a==b) { 」 ) プログラム 1 : #include <stdio.h> 2 : #include <string.h> 3 : void dict_in(void); /* 辞書データの初期化(定義省略) */ 4 : /* 外部変数 dicts[][]に辞書データが入る*/ 5 : int dict_check(char *); /* 辞書にあるかチェック(定義省略) */ 6 : int word_check(char *); /* 入力済単語チェック */ 7 : int chain_check(char *); /* しりとりのチェック */ 8 : void next(int *, int *, int); /* 得点加算と次プレイヤ指定 */ 9 : 10 : char dicts[30000][30]; /* 辞書データ */ 11 : char words[100][30]={"apple"}; /* 入力済の単語 */ 12 : int dictno, wordno=1; /* dicts と words の実データ数 */ 13 : 14 : int main() 15 : { 16 : char str[128]; 17 : int i, player=0, score[2]={0,0}, point; 18 : /* player=0,1 でプレイヤー1、2を示す。score はそれぞれの累積得点 */ 19 : 20 : dict_in(); /* 辞書データの初期化 */ 21 : while(1) { 22 : point=0; /* 得点の初期値 */ 23 : printf("Player%d : %s に続く単語を入力して下さい: ",player+1,words[wordno-1]) 24 : if (scanf("%s",str)!=EOF) break; 25 : if (dict_check(str)==0) { printf("辞書には無い単語です\n"); 26 : } else if (word_check(str)==1) { printf("既に出た単語です\n"); 27 : } else if (chain_check(str)==1) { 28 : printf("正しい\n"); 29 : words[wordno]=str; /* 入力済単語に登録 */ 30 : wordno++; 31 : point=1; 32 : } else { 33 : printf("間違いです\n"); 34 : } 35 : next(player, score, point); /* 得点を加算し、次のプレイヤーにする */ 36 : } - 11 - 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : printf("\nPlayer1: %d 点, Player2: %d 点\n", score[0],score[1]); if (score[0]<=score[1]) printf("Player1 の勝ち\n"); else if (score[0]>score[1]) printf("Player2 の勝ち\n"); else printf("引き分け\n"); } return 0; /* 既に入力済のとき、1 を返す。それ以外は 0 */ int word_check(char *str) { int i; for (i=0; i<wordno; i++) { if (strcmp(str, words[i])==0) break; } if (i<wordno) return 1; return 0; } /* 点数加算と次のプレイヤーにする */ void next(int *player, int *score, int point) { score[player]+=point; player=(player+1)%2; } /* しりとりが正しければ 1、間違いなら 0 を返す */ int chain_check(char *str) { int k; k=strlen(words[wordno-1]); if (words[wordno-1]==str) return 1; return 0; } - 12 -
© Copyright 2024 ExpyDoc