#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define LINE_SIZE 256
#define CMD_SIZE 100
 
void temporary_save(FILE *txtfile , FILE *temp); 
void execmd(FILE *txt, FILE *temp, char *txtname, char *temp_cmd, int *p);
void display_all(FILE *txt);
void one_row_edit(FILE *original, FILE *temp, int row, char *original_name, int *p);
void save_end(int *p);
void not_save(FILE *txt, FILE *temp, char *txtname, int *p);
 
int main(int argc, char *argv[]){
 
	FILE *txtfile, *temp;
	int start = 0;
	int coe = 1;//終了条件(Condition Of End)
	int *p_coe = &coe;        //coeへのポインタ
	char cmd[CMD_SIZE];            //コマンド
	char temp_text[L_tmpnam];	//一時的ファイルのファイル名(編集前のデータ保存用)
	tmpnam(temp_text);	        //一時的ファイルのファイル名の決定
 
 
	//ファイルの引数を調べる。
	if(argc != 2){
		printf("引数にはファイルのパスを指定してください\n");
		exit(1);
	}
 
 
	//終了するまで無限ループ
	while(coe){
 
 
		//ファイルが開けるかどうかを調べる。
		if((txtfile = fopen(argv[1], "r")) == NULL){
			printf("ファイルを開くことが出来ません");
			exit(1);
		}
 
		//*を表示する
		if(start) printf("*");
		else{
			//変更せずに終了するときに使用する変更前のファイルの保存
			temp = fopen(temp_text, "w");
			temporary_save(txtfile,temp);
			temp = freopen(temp_text,"r",temp);              //w→rに切り替える
			txtfile = fopen(argv[1], "r");                  //もう一回txtfileと読み込んだファイルを結びつける。
			printf("ファイルを終わりまで読み込みました\n*");
			start++;
		}
 
		//コマンドを入力
		fgets(cmd, CMD_SIZE, stdin);
 
		//コマンドの実行
		execmd(txtfile, temp, argv[1], cmd, p_coe);
 
		//ファイルを閉じる
		fclose(txtfile);
	}
	fclose(temp);
	remove(temp_text);		//一時的ファイルを削除する
	return 0;
}
 
//一時的ファイルの保存
void temporary_save(FILE *txtfile,FILE *temp){
 
	int c;            /* 文字を読み込む */
 
	/* ファイルから EOFが現れるまで1字読み込む */
	while ((c = getc(txtfile)) != EOF) {
 
		fputc(c,temp);
 
	}
	/* この時点でtxtfileに結びつけられたファイルは最後まで読み込まれてしまったので閉じる */
	fclose(txtfile);
 
}
 
 
 
//機能はここに追加
void execmd(FILE *txt, FILE *temp, char *txtname, char *temp_cmd, int *p){
 
	if(strcmp(temp_cmd, "l\n") == 0 || strcmp(temp_cmd, "L\n") == 0) display_all(txt);               //すべて表示
	if(atoi(temp_cmd) != 0) one_row_edit(txt, temp, atoi(temp_cmd), txtname, p);                     //一行編集
	if(strcmp(temp_cmd, "e\n") == 0 || strcmp(temp_cmd, "E\n") == 0) save_end(p);                    //保存して終了
	if(strcmp(temp_cmd, "n\n") == 0 || strcmp(temp_cmd, "N\n") == 0) not_save(txt,temp,txtname,p);   //保存しないで終了
 
	return;
}
 
//以下は拡張した関数群
 
//すべての行を表示
void display_all(FILE *txt){
	char str[LINE_SIZE];       //行保存用の配列
	int i = 1;                 //行番号
 
	while(!feof(txt)){
		if(fgets(str, LINE_SIZE - 1, txt) == NULL) strcpy(str, "\n");
		if(ferror(txt)){
			printf("ファイルの読み込み失敗\n");
			break;
		}
 
		if(!feof(txt)) printf("%8d: %s", i, str);
		else{
			if(strcmp(str, "\n") != 0) printf("%8d: %s\n", i, str);
		}
		i++;
	}
 
	return;
}
 
//一行編集
void one_row_edit(FILE *original, FILE *temp, int row, char *original_name, int *p){
	FILE *shadow;                       //実際に行を追加していくファイル(あとで元ファイルと入れ替える)
	char shadow_name[L_tmpnam];         //一行編集時のデータ保存用
	tmpnam(shadow_name);                //一時的ファイルのファイル名の決定
	char str[LINE_SIZE];                //行保存用の配列
	char c;                             //shadow→original用
	int i;                              //for用の変数
 
	//rowが0以下のとき
	if(row <= 0){
		printf("行番号が不正です。\n");
		return;
	}
 
	shadow = fopen(shadow_name, "w");
 
	//目的の行の手前まで読み込み書き込む
	for(i = 1; i < row; i++){
		fgets(str, LINE_SIZE - 1, original);
		if(ferror(original)){
			printf("行読み込みエラー\n");
			fclose(shadow);
			remove(shadow_name);
			return;
		}
		if(feof(original)){
			printf("行番号が不正です。\n");
			fclose(shadow);
			remove(shadow_name);
			return;
		}
		fputs(str, shadow);
	}
 
	//行番号と行を表示
	fgets(str, LINE_SIZE - 1, original);
	if(feof(original)) printf("%8d: %s\n", row, str);
	else
		printf("%8d: %s", row, str);
 
	//新たな行の書き込み
	printf("%8d: ", row);
	fgets(str, LINE_SIZE - 1, stdin);
	fputs(str, shadow);
 
	//終わりまで読み込む(display_allと同じように)
	while(!feof(original)){
		if(fgets(str, LINE_SIZE - 1, original) == NULL) strcpy(str, "\n");
		if(ferror(original)){
			printf("行読み込みエラー\n");
			return;
		}
 
		if(!feof(original)) fputs(str, shadow);
		else{
			if(strcmp(str, "\n") != 0) fputs(str, shadow);
		}
	}
 
	//shadowをoriginalに置き換える
	/*fclose(original);
	fclose(shadow);
	if(remove(original_name) == -1){
		printf("ファイルの削除に失敗しました。終了します。\n");
		execmd(original, temp, original_name, "n\n", p);
		return;
	}
	if(rename(shadow_name, original_name) == -1){
		printf("ファイルのリネームに失敗しました。終了します。\n");
		execmd(original, temp, original_name, "n\n", p);
		return;
	}
 
	//main関数でfcloseをしているため、もう一度開く
	if((original = fopen(original_name, "r")) == NULL){
		printf("ファイルを開くことが出来ません");
		exit(1);
	}*/
 
	//shadow→original
	freopen(original_name, "w", original);
	freopen(shadow_name, "r", shadow);
	while(!feof(shadow)){
		c = fgetc(shadow);
		if(ferror(shadow)){
			fclose(shadow);
			printf("一行編集shadow→original読み込みエラー\n");
			execmd(original, temp, original_name, "n\n", p);
			return;
		}
		if(!feof(shadow)) fputc(c, original);
		if(ferror(original)){
			fclose(shadow);
			printf("一行編集shadow→original書き込みエラー\n");
			execmd(original, temp, original_name, "n\n", p);
			return;
		}
	}
 
	fclose(shadow);
	if(remove(shadow_name) == -1) printf("一行編集shadow削除エラー\n");
 
	return;
}
 
//セーブして終了
void save_end(int *p){
 
	*p = 0;
 
	return;
}
 
//セーブしないで終了
void not_save(FILE *txt, FILE *temp,char *txtname, int *p){
 
	int c;            /* 文字を読み込む */
 
	txt = freopen(txtname,"w",txt);		//読み込みから書き込みへ
 
	/* ファイルから EOFが現れるまで1字読み込む */
	while ((c = getc(temp)) != EOF) {	//最初に保存してた内容を読み込み
 
		fputc(c,txt);			//元のファイルに戻す
 
	}
	*p = 0;
 
	return;
}
最終更新:2007年07月12日 00:07