ファイルの入出力2 †UNIX上でテキストファイルのコピーを行う実験プログラム。 制約 †コピーするのに1行単位、または1文字単位で読書きするような方法をとらず、必ず1処理で終わらせること。 #include <stdio.h> /* */ #include <sys/stat.h> /* for stat() */ /*#include <sys/types.h> for stat() */ /*#include <unistd.h> for stat() * 環境によってない場合がある*/ #include <string.h> /* for strchr() */ #include <stdlib.h> /* for malloc() */ /* */ #define MAX_F_NAME 40 /* */ #define INDEX_OK 0 /* */ #define RET_OK 0 /* */ #define RET_NG -1 /* */ #define FILE_NG -2 /* */ /* */ int main(void) /* */ { /* */ FILE *fin; /* 入力元ファイルポインタ */ FILE *fout; /* 出力先ファイルポインタ */ int index = INDEX_OK; /* 異常判定 */ int rtnCode = RET_OK; /* リターンコード */ char fileName[MAX_F_NAME] = ""; /* ファイル名 */ char *desk; /* メモリ作業領域 */ char ans[3] = ""; /* 継続判定 */ char spew = '\0'; /* stdin吐出し */ struct stat st; /* for stat() */ /* */ while(1) /* 無限ループ */ { /* */ printf("コピー元ファイル名 > "); /* 画面表示 */ fgets(fileName, MAX_F_NAME, stdin); /* 入力元ファイル名の取得 */ if(!strchr(fileName, '\n')) /* 入力判定 */ { /* 入力が長すぎる */ while(spew != '\n') /* stdin吐出し */ { /* */ spew = fgetc(stdin); /* */ } /* */ spew = '\0'; /* */ } /* */ /* */ fileName[strlen(fileName) - 1] = '\0'; /* 末尾改行の処理 */ index = stat(fileName, &st); /* システム情報取得 */ if(INDEX_OK != index) /* 異常処理 */ { /* */ printf("statまたは入力のエラー\n"); /* 画面表示 */ rtnCode = RET_NG; /* リターンコードにエラー設定 */ break; /* 処理終了 */ } /* */ /* */ desk = (char*)malloc(st.st_size); /* 作業領域の確保 */ if(NULL == desk) /* 異常処理 */ { /* */ printf("mallocでエラー\n"); /* 画面表示 */ rtnCode = RET_NG; /* リターンコードにエラー設定 */ break; /* 処理終了 */ } /* */ /* free(desk);*/ /* * freeするタイミング? */ /* */ fin = fopen(fileName, "rb"); /* 入力元ファイルオープン(バイナリ) */ if(NULL == fin) /* 異常処理 */ { /* */ printf("fopenでエラー(入力元)\n"); /* 画面表示 */ rtnCode = FILE_NG; /* リターンコードにファイルエラー設定 */ break; /* 処理終了 */ } /* */ /* */ /* fgets(desk, st.st_size, fin); * バイナリモードなら一発可能?不可能! */ fread(desk, sizeof(char), st.st_size, fin); /* これならいける! */ fclose(fin); /* 入力元ファイルクローズ */ /* free(desk);*/ /* * freeするタイミング? */ /* */ printf("コピー先ファイル名 > "); /* 画面表示 */ fgets(fileName, MAX_F_NAME, stdin); /* 出力先ファイル名の取得 */ if(!strchr(fileName, '\n')) /* 入力判定 */ { /* 入力が長すぎる */ while(spew != '\n') /* stdin吐出し */ { /* */ spew = fgetc(stdin); /* */ } /* */ spew = '\0'; /* */ } /* */ /* */ fileName[strlen(fileName) - 1] = '\0'; /* 末尾改行の処理 */ fout = fopen(fileName, "ab"); /* 出力先ファイルオープン(バイナリ) */ if(NULL == fout) /* 異常処理 */ { /* */ printf("fopenでエラー(出力先)\n"); /* 画面表示 */ rtnCode = FILE_NG; /* リターンコードにファイルエラー設定 */ break; /* 処理終了 */ } /* */ /* */ /* fputs(desk, fout); * バイナリモードなら一発可能?不可能! */ fwrite(desk, sizeof(char), st.st_size, fout); /* これならいける! */ fclose(fout); /* 出力先ファイルクローズ */ free(desk); /* * freeするタイミング? */ /* */ printf("コピー成功したかも。まだやる?[Y/n] > "); /* 画面表示 */ fgets(ans, 2, stdin); /* 継続判定の取得 */ if(!strchr(ans, '\n')) /* 入力判定 */ { /* 入力が長すぎる */ while(spew != '\n') /* stdin吐出し */ { /* */ spew = fgetc(stdin); /* */ } /* */ spew = '\0'; /* */ } /* */ /* */ if((ans[0] == 'n' || ans[0] == 'N') && (ans[1] == '\n')) /* 継続判定 */ { /* 継続判定はnかN1文字 */ printf("正常終了\n"); /* 画面表示 */ break; /* 処理終了 */ } /* */ } /* */ /* */ return (rtnCode); /* */ } 修正履歴 †Borlandには"unistd.h", "getopt.h"が存在しないため、Maximaの中から強引に入手した。(実は必要なし?) 課題 †
|