2012/06/01

C言語 ドラッグ&ドロップで読込み書込み

CUIベースでCの学習をしているのだが、実用的なアプリにはGUIの必要性を感じていた。GUIは各OSに依存する部分。マルチプラットフォームを意識するとファイルサイズやスピードが犠牲になってしまう。見た目もイマイチだったり・・・ そこでCUIアプリでも、そこそこの使い勝手を維持できないか調べていたら、作ったexeにファイルをドラッグ&ドロップして起動できることが分かったので、ちょっと作ってみた。この方法であれば、それほどストレスなく、ファイル操作できそうだ。CUIアプリなら手軽にプログラムを作れるし、exeファイルのサイズも最小にできる。何と言ってもネイティブなので起動が高速。ちょっとやる気になってきた。

wavファイルをexeにドロップすると読込み書込みを行うプログラム

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
  FILE *fpr,*fpw;
  unsigned char buf[1024];
  int size;
  int i;
  char str1[128];
  char *str2;
  for(i=0; i<argc; i++){
    printf("%d = %s\n", i, argv[i]);
  }
  fpr = fopen(argv[1], "rb");
  if (fpr == NULL){
      printf("error rb");
      gets(argv[0]);
      exit(EXIT_FAILURE);
  }
  strcpy(str1,argv[1]); /* 文字列コピー */
  str2 = strtok(str1,"."); /* 文字列を.で分割 */
  strcat(str2,"_new.wav"); /* 文字列連結 */
  fpw = fopen(str2, "wb"); /* 新規ファイル作成 */
  if (fpw == NULL){
      printf("error wb");
      getchar();
      exit(EXIT_FAILURE);
  }
  size = fread(buf, sizeof(unsigned char), 1024, fpr);
  fwrite(buf, sizeof(unsigned char), size, fpw);
  printf("newfile = %s\n",str2);
  fclose(fpr);
  fclose(fpw);
  printf("success");
  getchar();
  return 0;
}
例えば「sample.wav」ファイルを、コンパイルして出来た「a.exe」ファイルにドラッグ&ドロップすると、コマンドプロンプトが起動する。自動で新規に「sample_new.wav」を作って、コピーして保存する。上記は配列を固定しているので、大きなwavファイルだと、はじめの部分しかコピーされない。実用的なプログラムにする場合は、配列を柔軟に対応できるようにすればよい。成功すれば「success」と表示されるので、enterを押せばコマンドプロンプトは閉じて終了する。 プログラムとしてはコマンドライン引数を使っている。これは起動時に文字列を取得する。今回はドラッグ&ドロップによって、ファイルのパスを取得している。そのパスを文字列の分割、結合を使ってsample_new.wavという文字列に変形。そして新規ファイルとして保存している。ファイルの位置はexeと同じ階層にある必要はないので、使い勝手は悪くない。
0 = C:\a.exe
1 = C:\samaple.wav
newfile = C:\sample_new.wav
success


改良 大きなwavファイルにも対応

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
  FILE *fpr,*fpw;
  int size;
  int i;
  char str1[256];
  char *str2;
  float in = 0, out = 0;
  for(i=0; i<argc; i++){
    printf("%d = %s\n", i, argv[i]);
  }
  fpr = fopen(argv[1], "rb");
  if (fpr == NULL){
        printf("error rb");
        getchar();
        exit(EXIT_FAILURE);
  }
  strcpy(str1,argv[1]);
  str2 = strtok(str1,".");
  strcat(str2,"_new.wav");
  fpw = fopen(str2, "wb");
  if (fpw == NULL){
        printf("error wb");
        getchar();
        exit(EXIT_FAILURE);
  }
  /* float 単位で処理 */
  for(;!feof(fpr);){
     /* read */
     fread(&in, sizeof(float), 1, fpr);
     if(ferror(fpr)){
          perror("read error");
          break;
     }
     /* effects */
     /* empty */
     out = in;
     /* write */
     fwrite(&out, sizeof(float), 1, fpw);
     if(ferror(fpw)){
          perror("write error");
          break;
     }
  }
  fclose(fpr);
  fclose(fpw);
  printf("success");
  getchar();
  return 0;
}
大きなwavファイルもコピーして保存できるようにした。内部的にはバッファの配列を廃止し、float単位で、読込み書込みを繰り返している。読込むものがなくなればループから抜ける。読込んだ直後に /*effects*/ とコメントを入れたが、ここに各種エフェクトの関数を入れれば、音の加工が可能になる。実際にやる場合は、wavファイルのヘッダとか、リトルエンディアンとかの処理を追加する必要があるけど。

C言語 ANSI C89 Meadow & MinGW GCC 目次はこちら