明解C言語中級編 9章の自由課題7を解いてみた

こんばんにゃ。

課題9-8はこの先構造体をちょっとやってからその練習に使おうと思うので、9章はこれで終わりになります。

問題:List9-7 簡易Copyコマンドは上書き確認しないので、確認するように修正しなさい。

そーす

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define BSIZE 128

int
main(int argc, char *argv[])
{
   int n, x;
   FILE *src=NULL, *dst=NULL;
   unsigned char buf[BSIZE];
   long pos, sz;
   struct stat stat_buf;

   if(argc != 3){
     fprintf(stderr, "パラメタが不正\n");
     fprintf(stderr, "bcopy コピー元ファイル名 コピー先ファイル名\n");
   }else{
     if((src = fopen(*++argv, "rb")) == NULL){
       fprintf(stderr, "ファイル%sがオープンできない\n", *argv);
       return 1;
     }else if((dst = fopen(*++argv, "ab")) == NULL){
       fprintf(stderr, "ファイル%sがオープンできない\n", *argv);
       fclose(src);
       return 1;
     }else{
       stat(*argv, &stat_buf);
     //              printf("%sは %d\n", *argv, stat_buf.st_size);  //Debugファイルサイズ確認
       if(stat_buf.st_size > 0){
         printf("ファイル%sはすでに存在します。上書きしていいの? 1:yes 2:no -> ", *argv);
         scanf("%d",&x);
         switch(x){
         case 1:
           remove(*argv);  //追記になるのでいったん削除
           dst = fopen(*argv, "wb"); //開きなおし
           while((n = fread(buf, sizeof(unsigned char), 1, src)) > 0)
             fwrite(buf, n, 1, dst);
             fclose(src);
             fclose(dst);
           break;
         case 2:
           fclose(src);
           fclose(dst);
           break;
         }
       }else{
      while((n = fread(buf, sizeof(unsigned char), 1, src)) > 0)
       fwrite(buf, n, 1, dst);
      fclose(src);
      fclose(dst);
         }
// 残骸
//                                      remove(*argv);
//                                      fclose(src);
//                                      fclose(dst);
     }
   }

   return 0;
}

今回は {} を付け忘れたりしてdouble freeというエラーに初めて遭遇した。メモリの2重解放ってのが原因らしく、今回は記述ミスが原因だったので、そのものの解決や追究はしてないけど、こんなのもあるんだなあと。

使える関数を探したりするPHP的(個人的なイメージね)な感じで進めたりしました。

実行結果

$ echo hogehoge.world > kekka.txt
$
$ cat kekka.txt
hogehoge.world
$
$ ./a.out kekka.txt hogehoge.txt
$
$ cat hogehoge.txt
hogehoge.world
$
$ echo Hello world > kekka.txt
$
$ ./a.out kekka.txt hogehoge.txt
ファイルhogehoge.txtはすでに存在します。上書きしていいの? 1:yes 2:no -> 2
$
$ cat hogehoge.txt
hogehoge.world
$
$ ./a.out kekka.txt hogehoge.txt
ファイルhogehoge.txtはすでに存在します。上書きしていいの? 1:yes 2:no -> 1
$
$ cat hogehoge.txt
Hello world
$

いちばん悩んだのが、ファイルの存在確認で、今回はstat関数というのを使いました。
おお、いま流行りのかって思ったけど、あれはstapだった。

fopenの使い方がけっこう強引な感じがするけど、ほかにもっとよさげなものが思いつかなかったさ。rbでfopenしてもよかったけどそっちの方がめんどくさそうだった。

ただ9章はおもしろかった。

おもしろかったなあ。

つづく。