まず課題をおさらいすると
というものでした。1.指定されたファイル内容を順番につなげて標準出力に出力する。
ファイル名が1つも指定されない場合は、標準入力から入力する。
2.オプションは -n, -h, -t の3種類とし、オプションの指定の順序に関係なく自由に組み合わせることが可能とする。
-nオプション: 各行の先頭に行番号を表示。
-hオプション: 出力開始行の指定。たとえば -h3 で3行目から出力する。
-tオプション: 出力終了行の指定。たとえば -t5 で5行目まで表示する。
※文字列の比較には以下に示すstrncmp関数を使うこと。
int strncmp(const char *s1, const char *s2, size_t n)
2つの文字列s1とs2で、最初のn文字だけを較べる。この関数は、s1がs2に較べて1)小さい、2)同じ、3)大きい場合に、
0よりも1)小さい、2)同じ、3)大きい整数を返す。
また、文字列から整数値を得るために、以下の関数を利用してもよい。
int atoi(const char *nptr)
atoi関数は,notrによって支持される文字列の初めの部分をint型整数に変換する。
3.エラー処理をすること。少なくとも、オプションが正しくない場合に、オプションの指定を知らせるようにする。
そして、自分が書いたコードはこれです。
#include
#include
#include
void doOneCat(const char* fileName,int* newLineFlag,
int* nowLine,int start,int end,int printLineFlag) {
FILE* fp=stdin;
int buffer;
if(fileName!=NULL) {
fp=fopen(fileName,"r");
if(fp==NULL) {
fprintf(stderr,"error: failed to open file \"%s\"\n",fileName);
exit(1);
}
}
while((buffer=fgetc(fp))!=EOF) {
if(*newLineFlag) {
if(printLineFlag && start : set first line to output.\n");
fprintf(stderr," -t : set last line to output.\n");
exit(1);
}
int main(int argc,char* argv[]) {
int argcCount;
int start=0,end=0;
int printLineFlag=0;
int fileCameFlag=0;
int nowLine=1;
int newLineFlag=1;
for(argcCount=1;argcCount<argc;argcCount++) {
if(argv[argcCount][0]=='-') {
if(argv[argcCount][1]==0) {
fileCameFlag=1;
doOneCat(NULL,&newLineFlag,&nowLine,start,end,printLineFlag);
} else {
if(fileCameFlag) {
fprintf(stderr,"error: option cannot appear after file name.\n");
exit(1);
}
if(strncmp(argv[argcCount],"-n",2)==0) {
if(argv[argcCount][2]==0) {
printLineFlag=1;
} else {
printUsage();
}
} else if(strncmp(argv[argcCount],"-h",2)==0) {
char* last;
start=strtod(&argv[argcCount][2],&last);
if(*last!=0)printUsage();
if(start<=0) {
fprintf(stderr,"error: start line must be positive.\n");
exit(1);
}
} else if(strncmp(argv[argcCount],"-t",2)==0) {
char* last;
end=strtod(&argv[argcCount][2],&last);
if(*last!=0)printUsage();
if(end<=0) {
fprintf(stderr,"error: end line must be positive.\n");
exit(1);
}
} else {
printUsage();
}
if(end<start && end!=0) {
fprintf(stderr,"error; start line cannot be larger than end line.\n");
exit(1);
}
}
} else {
fileCameFlag=1;
doOneCat(argv[argcCount],&newLineFlag,&nowLine,start,end,printLineFlag);
}
}
if(!fileCameFlag)doOneCat(NULL,&newLineFlag,&nowLine,start,end,printLineFlag);
return 0;
}
元のトピックの質問者のコードのような、バッファサイズの制限はありません!
また、「あまり褒められた実装ではない」実装(=同じコードのコピペ)を避けるため、出力動作を別関数に分ける工夫をしました。
やはりstrncmpを利用しなければならない縛りが謎ですが、条件なので仕方ないですね。
最後に改行がないファイルを入力に使うと、次のファイルが同じ行に繋がるのは仕様です。
(本物のcatもそうなっているようです)
感想、意見、改善点、バグ報告などありましたら、どしどしコメントを下さい。待ってます!