以下の課題を C, C++, Java のどれかの言語を使って作りなさい。
注意: Windows の API は使用しないで作って下さい。
レポート締切日: 2006年11月29日20:00
提出先: レポートボックス
ファイルを読み込み、各行が逆順に出るようなプログラムを書きなさい。 作成したプログラムに対して、空の入力と、作成したプログラム本体のソース コードを入力し、出力結果を報告しなさい。 なお、ファイルの読み込み、出力は標準入出力が望ましい。 また、絶対に、一行の文字数や、行数の制限を行わない事。 同じファイルを二回以上オープンしない事。 但し、メモリに異常が発生した場合は、検知し、確実に異常終了させる事。
一文字の処理に、文字列の文字数に比例した時間かかったり、一行の処理に 全体の行数分の時間がかかるようなプログラムは大幅に減点します。
行の入力には getline を使うのが簡単です。 坂本は 18 行で作りました。
行の入力には java.io.BufferedReader クラスを使うと便利です。 System.in を使って InputStreamReader オブジェクトを作ります。 また、入力メソッドは java.lang.IOException 例外を投げますが、この処理は行 わず、 main メソッドの定義時に throws IOException を指定すると簡単です。 Exception を catch するだけしておいて、利用者にはなにも起きてないよう な振舞いをするプログラムを作るのは止めましょう。 坂本は 17 行で作りました。
行の入力を得るため、制限のない文字列を表現する線形リストを作る必要があ ります。 これはキューのように振舞いますが、読み出しは常に先頭からで、文字の追 加は常に最後尾になります。 このような入力をスタックに貯めていきます。 したがって、講義資料にあるように行自体をグローバル変数で作るのはまずい です。 そのため、行の先頭を指すポインタと、最後を指すポインタの組からなる構造 体を作り、この構造体を行と同一します。 そして、追加、表示などの関数はこの構造体へのポインタに対して作る事にし ます。 なお、行だけでもそれなりに複雑になりますので、別ファイルに分け、単独で テストした方が良いと思われます。
坂本は 3 ファイル、 144 行で作りました。但し、さらに 21 行のテスト用ファ イルも作っています。
#include <stdio.h> int main(void){ printf("Hello World\n"); return 0; }
} return 0; printf("Hello World\n"); int main(void){ #include <stdio.h>
(2006/12/20) 設問の条件を緩くするよう、注意を追記しました。
(2006/12/18) 実行例を訂正しました。
(2006/12/8) Java 1.4 に関して追記しました。
レポート締切日: 2007年1月10日20:00 但し 4 年生以上は冬休み中にやりとりできる e-mail アドレスを表紙に記入して 2006年12月20日 20:00
提出先: レポートボックス
ファイルを読み込み、英字のみか、先頭が英字で二文字目以降が英字または数 字である文字列を抽出し、文字列の長さが長い順に並べ、その文字列の頻度と 共に表示するプログラムを作成したい。 但し、文字列の長さが同じものに関しての順序は任意で良い。 以下の設問にしたがって回答しなさい。
#include <stdio.h>
#include <ctype.h>
int main(void){
int c0;
char c1;
c1='\0';
b='\0';
while((c0=getchar())!=EOF){
if((!isalnum(c1))&&isalnum(c0)){
printf("\n");
}
if(isalnum(c0)){
printf("%c",c0);
}
c1=c0;
}
return 0;
}
getchar:1 include:2 isalnum:3 printf:2 return:1 stdio:1 while:1 ctype:1 char:1 main:1 void:1 EOF:1 int:2 if:2 c1:4 c0:6 h:2 n:1 c:1
ファイルを読み込み、英字のみか、先頭が英字で二文字目以降が英字または数 字である文字列を出力するプログラムを作りなさい。
include stdio h include ctype h int main void int c0 char c1 c1 while c0 getchar EOF if isalnum c1 isalnum c0 printf n if isalnum c0 printf c c0 c1 c0 return
int cmp(char *s1, char *s2);
これを strcmp と同じ仕様となるようにします。
但し、文字列が長い順に並ぶようにするため、次のようにします。
s1 が s2 に較べて 1)短い、2)等しい、3)長い場合に、ゼロよりも 1)大きい、
2)等 しい、3)小さい整数を返すようにします。
但し、同じ長さの文字列だった場合、任意の順序を考え、真に等しい場合以外
は 0 以外の値を返すようにします。
class Cmp implements java.util.Comparator<String> {
public int compare(String s1, String s2){
// ここは自分で書く
}
}
この compare メソッドは C 言語の場合と同様の値を出力するようにします。
class Cmp implements java.util.Comparator {
public int compare(Object s1, Object s2){
// ここは自分で書く
}
}
この compare メソッドは C 言語の場合と同様の値を出力するようにします。
class Cmp : public std::binary_function<std::string,std::string,bool> {
public:
bool operator()(const std::string& s1, const std::string& s2){
// ここは自分で書く
}
};
なお、詳しい解説とテスト方法はこちら
ファイルの終端が改行の直後にあることを仮定しても構いません (販売するようなレベルのソフトウェアでは問題ですが)。
ファイルを二回以上 open しないこと。 0 回または 1 回で済ませて下さい。 また最適さを追求しすぎる必要はないですが、余りにも効率が悪すぎる手法を 使用した場合(バブルソートを使うなど)、講義の内容を理解していないと見な しますので、ご注意下さい。
C++ を使う人は次がヒントになるかも知れません。
#include <iostream>
#include <locale>
using std::isalpha;
using std::isalnum;
int main(void){
std::locale loc;
std::cout << isalpha('2',loc)
<< isalpha('a',loc)
<< isalpha('#',loc)
<<std::endl;
std::cout << isalnum('2',loc)
<< isalnum('a',loc)
<< isalnum('#',loc)
<<std::endl;
return 0;
}
古い gcc を使っていると locale が入ってないため、上は動きません。 新しい mingw32 にバージョンアップを勧めますが、古い gcc のまま動かした い場合は下記のようにして下さい。 但し、結果は上とは異なります。
#include <iostream>
#include <cctype>
using std::isalpha;
using std::isalnum;
int main(void){
std::cout << isalpha('2')
<< isalpha('a')
<< isalpha('#')
<<std::endl;
std::cout << isalnum('2')
<< isalnum('a')
<< isalnum('#')
<<std::endl;
return 0;
}
坂本が解答を作成した時の行数を示します。
言語 | 行数 |
---|---|
C | 146 |
C++ | 95 |
Java 5 | 56 |
Java 1.4 | 75 |
なお、写したと思われるほど酷似したレポートが複数提出された場合、原著が どれかの調査を行わず、抽選で一通のレポートのみを評価 の対象とし、他は提出済みの不合格レポートとして再提出は課しません。 自分で意図せずに他人にコピーされてしまった場合も同様ですので、レポート の取り扱いについては十分に注意して下さい。