書く側のファイルも読み込み側に合わせたい。

[戻る]
JJ 2003/09/24(水) 10:03:02
         strcpy(filename, fd.cFileName);
          fprintf(fo, "[%s] ", filename);
          if ((fp = fopen(filename, "rt")) != NULL) 
      {
           exit(3);
          }
というコマンドで、別途、読みこまれたファイルを加工して
WRITE側に出力したいのですが、
そのREAD側のファイルの名前を、*.docとすると、
WRITE側のファイルの名前も、
しれに合わせて、*12.docというようにしたい、
(例えば、READ側のファイルが top.docという名前だとすると、
  加工後のWRITE側のファイルの名前を  top12.docというようにしたい)
とすると、WRITE側のファイルの開き方としては、
どうすれば、いいのでしょうか?

επιστημη [HomePage] 2003/09/24(水) 10:11:53
ファイル全体を一気に取り込んでおくことができるなら、そのまま同名で上書きすればよし。
それが無理ならとりあえず異なる名前で書いてからファイル名をすりかえ。

sugar 2003/09/24(水) 11:00:56
"top.doc"というファイル名から、"top12.doc"という名前を
どうやって作ればよいかを聞かれているようにも解釈できるのですが。

_splitpath()という関数を使うと、パス名やら拡張子やらをバラバラに分解できます。
あとは文字列操作で"12"をくっつけてあげればよいような。

入力ファイルも出力ファイルも物理的に別々なファイルなら、
プログラムの冒頭で2つのファイルをオープンしておけばいいし・・・

そういうことじゃないのかな?

επιστημη [HomePage] 2003/09/24(水) 11:13:08
あ、そういうコトか。失礼。
ならば単に文字列操作だけの問題です。
ファイル名の中で最後に現れる'.'を探し、
その前に"12"を挿入すればいいのだから。

2003/09/24(水) 15:33:57
FILE *fp1 ;
FILE *fp2 ;
char buff[256] ; // サイズは適当です。扱う情報にあわせて変更が必要。
char fileName1[256] ;
char fileName2[256] ;
char *p ;

printf("暇つぶしに作ってみました。") ;
printf("サンプルです。コンパイルしてません。ご利用はご自身の責任下でお願いします。");

strcpy( fileName1, "top.doc" ) ;
strcpy( fileName2, fileName1 ) ;

p = strchr( fileName2, '.' ) ; // 拡張子 ".doc" 開始部分取得
*p = '\0'                    ; // "top.doc" を "top" にする
strcat( fileName2, "12" )    ; // "top" を "top12" にする
p = strchr( fileName1, '.' ) ; // "top.doc" の拡張子部分をもってくる
strcat( fileName2, p )       ; // "top12" を "top12.doc" にする

// "top.doc" オープン処理 /////////////////////////////////////////////////////
fp1 = fopen( fileName1, "rt" ) ; // "top.doc" をテキスト読み込み用にオープン
if( fp1 == NULL )
{
    return ; // "top.doc" オープン失敗
}

// "top12.doc" オープン処理 ///////////////////////////////////////////////////
fp2 = fopen( fileName2, "wt" ) ; // "top12.doc" をテキスト書き込み用にオープン
if( fp2 == NULL )
{
    return ; // "top12.doc" オープン失敗
}

// "top.doc" 参照& "top12.doc" 書き込み //////////////////////////////////////
while( !feof(fp1) )
{
    // 1行取得
    if( fgets( buff, 255, fp1 ) == NULL )
    {
        printf( "top.doc 参照失敗" ) ;
        break ;
    }

    // なにか加工するならこの場所で。

    if( fputs( buff, fp2 ) == EOF )
    {
        printf( "top12.doc 書き込み失敗" ) ;
        break ;
    }
}

// "top.doc" と "top12.doc" のクローズ処理 ////////////////////////////////////
fclose( fp1 ) ; // "top.doc" のクローズ
fclose( fp2 ) ; // "top12.doc" のクローズ

printf("終了です。");

JJ 2003/09/25(木) 08:46:51
みなさん
ありがとうございます。

おかげさまで、ファイルは、.docの付くファイルは
全て、スキャンさん、中身も新たに変わったものも出来たのですが、
一つ問題が起きました。

それは、
元のファイルが、XXX.doc
新しいファイルが、XXX12.doc
だから、
一通り既存のXXX.doc系のファイルに対して、スキャンが終わると、
次に、新しく出来たXXX12.doc系のファイルに対してもスキャンに入り、
同じく加工に行き、永久ループに入ります。

既存のXXX.doc系のファイルに対してだけに
この操作を限定させるようなことは出来ないのでしょうか?

επιστημη [HomePage] 2003/09/25(木) 08:54:16
書き込みを始める前にファイルの検索だけ先にやっちまっておけばいいんじゃないですか?

ひろぴー 2003/09/25(木) 09:00:03
> 既存のXXX.doc系のファイルに対してだけに
> この操作を限定させるようなことは出来ないのでしょうか?
XXXの部分に数字が入らないのなら文字コードで比較すればよいと思います。
その他ファイル名の桁数が決まっていれば比較は容易に出来ますね。
そういう制約をつけたくなければ、一度つけたXXX12.docのファイル名を保存しておいて
「XXX.doc → XXX12.doc」化する時に一度作成されたかどうかチェックするなどしては
どうでしょうか?

ひろぴー 2003/09/25(木) 09:00:48
あ、επιστημηさんの方式がスマートでよいと思います(ToT)

JJ 2003/09/25(木) 09:39:16
さっそくありがとうございます。

ファイルの検索は、
FINDFIRSTFILE
と
FINDNEXTFILE
の間でfopen、fcloseがうまくかかるか、見ながら
カウントしておいて、
再度、そのカウント回数分、
FINDFIRSTFILE
と
FINDNEXTFILE
をかけて、加工に行く
ということでいいでしょうか?

sugar 2003/09/25(木) 09:54:03
FINDFIRSTFILE、FINDNEXTFILEで取得したファイル名を
配列などに退避しておけばよろしいかと。
ファイルの加工は、ファイル名さえわかっていれば問題ないはず。
検索ループは1回で十分ですよ。

επιστημη [HomePage] 2003/09/25(木) 10:19:40
#include <windows.h>
#include <string>
#include <vector>
#include <iostream>

int main() {

  std::vector<std::string> filenames;

  // *.doc を(filenamesに)列挙する
  WIN32_FIND_DATA find_data;
  HANDLE handle = FindFirstFile("*.doc", &find_data);
  if ( handle != INVALID_HANDLE_VALUE ) {
    do {
      if ( !(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
    filenames.push_back(find_data.cFileName);
      }
    } while ( FindNextFile(handle, &find_data) );
    FindClose(handle);
  }   

  // 列挙されたファイルに対し...
  for ( std::vector<std::string>::iterator iter = filenames.begin();
        iter != filenames.end(); ++iter ) {
    std::string read_filename  = *iter;
    std::string write_filename = read_filename;
    // '.'の手前に"12"を付加する 
    write_filename.insert(write_filename.rfind('.'),"12");
    std::cout << read_filename << "->" << write_filename << std::endl;
    // read_filename を読み、write_filenameに書く
  }

  return 0;
}

サイファ 2003/09/25(木) 20:58:28
vectorのpush_backって限界はないんですかねぇ?

επιστημη 2003/09/25(木) 21:44:16
どういった限界でしょうか?

PAI 2003/09/26(金) 04:39:42
>vectorのpush_backって限界はないんですかねぇ?

件数のことであれば size_t がひっくり返るところが限界です。
一般的に2の32乗か、64乗か、

ヒープ容量のことでしたら vectorのpush_back とは無関係です。
他の手段でもそれは限界となります。
一般的にファイル名を扱うぐらいであればまったく問題はありません。
普通のPCであればMAX_PATH長のstring数万件でも扱えます。

サイファ 2003/09/26(金) 20:25:17
PAIさん有難うね。
良く分かりました。

古いスレッドには追加発言できません。