
Visual StudioでWindowsプログラミングをしています。
RESULT CALLBACK WndProc(HWND hwnd, UINT imsg, WPARAM wp, LPARAM lp){
…
switch(imsg){
case WM_COMMAND:
switch(LOWORD(wp)) {
case ID_FILEOPEN:
FileSet(hwnd);
break;
case ID_WRITE:
if((fp_test=fopen("test_data.dat","w"))==NULL)
exit(0);
fputs("******",fp_test);
fclose(fp_test);
break;
…
}
return 0;
}
のようにメニューからファイルの読み書きを行わせたいと思っています。
プログラムを実行してすぐにWRITE部分を行うと、
ファイルは正常に作られ、書き込みもできています。
ところが、先にFILEOPENを行うと、その後WRITEが正しく動かず、
ファイル自体が作成されません。
ファイルオープンに失敗すれば、終了するはずですが、それもしません。
FILEOPENで呼び出しているFileSet関数は以下です。
void FileSet(HWND hwnd){//ファイルの選択
char filePath[MAX_PATH];
char fileFolder[MAX_PATH];
char *pt,*ptEnd,*ptEndNext;
if(OpenFiles(hwnd)==1){
pt = FileName;
ptEnd = strchr(FileName,'\0');
ptEndNext = ptEnd + 1;
if(ptEnd){
int nLength;
if(*(ptEndNext) == '\0'){//ファイルが1つしか選択されていない
strcpy( filePath, FileName );
FileOperation(filePath); //ファイルオープンとデータの平滑化
}else{ //複数選択
strcpy( fileFolder, FileName );//フォルダ名の取得
nLength = strlen(fileFolder);
if(fileFolder[nLength]!='\\')
strcat(fileFolder, "\\");
while(*(ptEndNext) != '\0'){
strcpy(filePath, fileFolder); //パス名を作成
strcat(filePath, ptEndNext ); //ファイル名を連結
FileOperation(filePath);
ptEnd = strchr( ptEndNext, '\0' ); //次のファイルを探す
ptEndNext = ptEnd + 1;
}
}
}
}
}
FileSet関数内で呼んでいるFileOperationは以下です。
テキストデータを数値に変換し、indataという構造体配列に代入しています。
indata,numはグローバル変数です。
void FileOperation(char *filePath, int b){//ファイルオープンとデータスケーリング
int i,j;
double datawork;
char work[10];
if((fp=fopen(filePath,"r"))==NULL)//ファイルオープン
exit(0);
for(i=0,j=0;(i<DATA_NUM) && (fscanf(fp,"%s",work)!=EOF);++i){//データ読み込み
datawork = atof(work);
indata[num].data[j] = (float)datawork/NORM;
j++;
}
fclose(fp);
datawork = 0;
indata[num].number = num;
strcpy(indata[num].fname,filePath);
num++;
}
おそらくこのあたりに原因があるとは思うのですが、
自分ではわかりませんでした。
お力を貸していただければと思います。
WinXP SP3, VisualStudio 2005で作成しています。
説明不足な部分がありましたらすみません。
よろしくお願いいたします。
No.1ベストアンサー
- 回答日時:
多分関係ありませんが,
if(fileFolder[nLength]!='\\')
strcat(fileFolder, "\\");
この処理はおかしいような気がします. 「\ で終わっていれば何もせず, \ で終わっていない場合には \ を付ける」という処理をしたいのだと思いますが, \ で終わっている場合にも \ を付けるのではないでしょうか.
例えば fileFolder が "a" だと nLength は 1 になりますが, fileFolder[nLength] は '\0' ですよね.
回答ありがとうございました。
ファイルが作れないことに関しては自己解決いたしまして、
FILEOPENした時にカレントディレクトリが変更されていたようで、、
オープンしたファイルのあるディレクトリに、
ファイルはきちんと作成されていました。
書き込みファイル名を絶対パスで指定していなかったことと、
私の早とちりが原因でした。お騒がせいたしました。
ご指摘の部分ですが、確かに変な処理をしていますね…。
実行時に、予期せぬ動作などしなかったので、見過ごしていました。
修正したいと思います。ありがとうございました。
No.2
- 回答日時:
Windowsのコールバック関数は、リエントラントである事が要求されます。
しかし、Cの標準ライブラリ関数のfopenは、リエントラント関数である保証はありません。
もし、fopenが非リエントラントで実装されている場合、リエントラントである事が要求される関数内で使用すると、動作は未定義です。
つまり「RESULT CALLBACKと定義されたWndProc関数内では、fopen関数を使用すると、動作は未定義」と言う事です。
リエントラントでない実装のfopen関数をコールバック関数で使用した為、fopenは「予期せぬ動作」をします。それが「どんな動作」かは、誰にも判りません。
今回は「予期せぬ動作」として「ファイルも作らず、何もせず、エラーにもせず、何だか正体の判らないFILEへのポインタを返す」と言う動作をしました。
fopenがリエントラントでない場合については、以下の質問の、当方の回答を参照して下さい。
http://oshiete1.goo.ne.jp/qa4545663.html
リエントラントである事が要求されるコールバック関数では、fopenの使用を避けCreateFile(API)を使用するか、fopenに再入しないようミューテックスを設けるなど、工夫が必要です。
ともかく、現状のままでは「fopenは使えない」と思って下さい。
回答ありがとうございました。
ファイルが作れないことに関しては自己解決いたしまして、
FILEOPENした時にカレントディレクトリが変更されていたようで、、
オープンしたファイルのあるディレクトリに、
ファイルはきちんと作成されていました。
書き込みファイル名を絶対パスで指定していなかったことと、
私の早とちりが原因でした。お騒がせいたしました。
リエントラント関数については、全く知識がありませんでした。
これから勉強したいと思います。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語での採番について
-
続・EOF判定されない
-
fopenで開いたファイルのサイズ...
-
VS2010 MFC CStdioFileについて
-
fgetsで2行目から文字化け
-
FTPでputすると空ファイルが出...
-
Access クエリ実行が急に非常に...
-
フルパスから最後のディレクト...
-
csvファイルを開かずに文字を検...
-
テキストファイルの最終行を削...
-
VB.NETで他のプロジェクトで作...
-
バッファとは何ですか
-
vba ActiveSheet.pasteを使った...
-
C言語初心者の質問失礼します。
-
UTL_FILEにて既存のExcelに追加...
-
c言語でファイルのタイムスタン...
-
シェルコマンドの 2>&1 とはど...
-
FTPでリモートのファイル一覧取得
-
ファイル出力の場所を指定
-
OLE又はDDEを使うVISUAL BESIC...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テキストファイルの行数を取得...
-
ファイル内のデータを1行削除...
-
バイナリファイルをテキストフ...
-
fgetsで2行目から文字化け
-
ファイルサイズ指定し、ファイ...
-
c言語 2つのファイルを行ご...
-
0x00をファイル出力
-
C言語での採番について
-
VBSで指定行に挿入
-
テキストファイルの先頭への文...
-
fopen(ファイルパス)
-
C言語での改行コードの扱いにつ...
-
fopenで開いたファイルのサイズ...
-
winsock recvでの文字化け
-
EOF判定されない
-
fscanf関数のscanf集合を使う時...
-
巨大なテキストファイル(可変...
-
VS2010 MFC CStdioFileについて
-
(UWSC)このような場合、解決策...
-
改行までの一文字ずつのファイ...
おすすめ情報