![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
はじめまして、お世話になります。
『ダイアログで取得したファイル名』を、含むData構造体をファイルとして書き込む場合に限り、ファイルが出力されません。
Data構造体の文字列file_nameが『ダイアログで取得したファイル名』でなければ正常に出力されます。また、関数の返値や書き込み後のFILE構造体の中身を読み込んで調べたりしましたが、見る限りエラーはありませんでした。
開発ツールはMicrosoft Visual Studio 2005を使用しています。
どうか皆さんの知恵を貸してください! お願いします!
//ファイルとして出力する構造体
typedef struct
{
TCHAR file_name[256];
BYTE id;
}Data;
//ファイルを開くダイアログ
void OpenFile(HWND hWnd, TCHAR file_name[])
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = TEXT("png files {*.bmp}\0*.bmp\0") TEXT("all files {*.*}\0*.*\0\0");
ofn.lpstrFileTitle = (LPWSTR)file_name;
ofn.nMaxFileTitle = CHAR_SIZE;
ofn.lpstrFile = NULL;
ofn.Flags = OFN_FILEMUSTEXIST;
GetOpenFileName(&ofn);
}
//ファイルを書き込む
void SaveData(Data save_file[])
{
FILE *file;
errno_terr;
size_t write_num;
//書き込む
err = _tfopen_s(&file, TEXT("hoge.map"), TEXT("w+b"));
if(err != 0) return;
write_num = fwrite(save_file, sizeof(Data), 6, file);
//きちんと書き込めているか確かめる
Data chek_data[6];
fseek(file, 0L, SEEK_SET);
fread(chek_data, sizeof(Data), 6, file);
fclose(file);
}
No.13ベストアンサー
- 回答日時:
修正後のソースで確認しました。
こちらでは一応動作はしているようです。しかし、
> err = _tfopen_s(&file, TEXT("hoge.map"), TEXT("w+b"));
これでオープンしたファイル"hoge.map" の置かれるディレクトリが、
実行ファイルのあるディレクトリではなく、ビットマップのある
ディレクトリでした(コマンドラインから起動してチェックしてます)。
ひょっとして、書き換えたファイルは別のところにあって、
書き換わってなどいない古いファイルをチェックしていたりは
していませんか?
fopen_s ってそんなものでしたっけ?
時間がないので、フルパス指定でないときのファイル作成場所
については調べてないです。ごめんなさい。
to #9
> C99になってから、ブロックの先頭でなくても、変数宣言してよくなったようです(わたしも、つい最近まで知らなかった^^;)
お心遣いはありがたいのですが、知ってましたよ。
質問者さんの使っている VC++ 2005ではC99は完全にはサポートされておらず、
変数宣言に関するこれも未サポート事項の一つだからああ書いただけです。
ありがとうございます。おかげで解決できました。
どうやらGetOpenFileName()でファイルを開くと、カレントディレクトリが『開いたファイルがあるフォルダ』に移動してしまい、そこにファイルが出力されてしまうようです。ソースファイルの中身にばかり気をとられていて、全く気づきませんでした。
それと、書き込んで下さった皆さんのおかげで、いろいろと新しいことを知ることができ勉強になりました。ありがとうございます。
No.16
- 回答日時:
★アドバイス
・OpenFile() 関数の次の1行のキャストは必要ない気がします。
注意点⇒ofn.lpstrFileTitle = (LPWSTR)file_name;
正しい⇒ofn.lpstrFileTitle = file_name;
理由は file_name が TCHAR 型なので LPWSTR に強制するのはまずい気がするため確認を。
・あと Win32 API で同名の OpenFile() 関数があります。
Cファイルでソースをコンパイルするとエラーがたくさん出すぎてコンパイル不能に陥りました。
CPPファイルでソースをコンパイルするとやっとコンパイルできました。
C++ は引数の個数や型が違うので別関数として識別したようです。
出来ることなら Win32 API 関数と同じ名前の関数(OpenFile)は使わない方がいい気がします。
・ちなみに私は VC2003 でコンパイルしました。
_tfopen_s() 関数がないので fopen() で代用してのコンパイルです。
つまり #include <stdio.h> の次の行に
typedef int errno_t;
#define _tfopen_s(fp,s,t) (((*(fp) = fopen(s,t)) != NULL) ? 0 : -1)
という2行を追加しました。→私は VC2005 を持っていないもので仕方がなしです。
・ソースをコンパイルしていて気づきましたが _tWinMain() 関数を使っていますね。
どうも Unicode 文字でコンパイルしているようだね。
もしかしたらここが原因でファイルに書き出せないのかもしれない。→今はまだ推測。
そこで _tWinMain() を WinMain() に名前を変えてコンパイル・オプションで
文字コードを Unicode からマルチバイト文字(シフトJIS)に変更してからコンパイルして下さい。
これでどうなるのか補足して下さい。
・ちなみに私の環境では『hoge.map』ファイルが作成されました。
作成された場所は exe ファイルと同じフォルダでした。
ファイルのサイズは 1,542 バイトです。
構造体メンバのアライメントを1バイト(/Zp1)にしておかないと正常に読み書きできないので
こちらのオプションも確認して下さい。
最後に:
・WinMain() 関数のメッセージ・ループで PeekMessage() 関数を使っていますが CPU が暇なときに
なにも処理していないせいか CPU 使用率が 100% にずっとなっています。
もしかしたらゲーム・ループを組んでいるのかな?
それだとしたら正しくないよ。組み方がおかしいです。
・正しくは下のようにループ内で PeekMessage() 関数を使ってメッセージがあったら分かりやすく
GetMessage() 関数で取り出すようにして下さい。
satou386 さんのループでは最初の一回しか PeekMessage() 関数でメッセージの有無を
チェックできません。このままだと PeekMessage() 関数を使っている意味がないと思います。
・以上。
//●エントリポイント
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
:
省略
:
//メッセージループ
MSG msg;
for ( ; ; ){
if ( !PeekMessage(&msg,NULL,0,0,PM_NOREMOVE) ){ // メッセージなし
Sleep( 1 ); // 独自の処理
}
else if ( GetMessage(&msg,NULL,0,0) > 0 ){ // メッセージあり
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else{
return (int)msg.wParam; // WM_QUIT、エラーが発生
}
}
}
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_16.png?5a7ff87)
No.15
- 回答日時:
> 変数宣言に関するこれも未サポート事項…
ありゃ。。そうなんですか。それは失礼いたしました^^
ほんじゃ、satou386 さんの環境が特殊なんですね。fwrite() で書き込めないし(笑)
No.14
- 回答日時:
void OpenFile(HWND hWnd, TCHAR file_name[])
{
OPENFILENAMEA ofn;
const char* filter="png files {*.bmp}\0*.bmp\0all files {*.*}\0*.*\0\0";
ZeroMemory(&ofn, sizeof(OPENFILENAMEA));
ofn.lStructSize = sizeof(OPENFILENAMEA);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = filter;
ofn.lpstrFileTitle = file_name;
ofn.nMaxFileTitle = 255;
ofn.lpstrFile = NULL;
ofn.Flags = OFN_FILEMUSTEXIST;
GetOpenFileNameA(&ofn);
}
でもいきませんよね…?
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_16.png?5a7ff87)
No.12
- 回答日時:
あっ、あと最後に、新しいソースのほうもまだ fread() 等して(シークして、ローカル配列に読み込んで、関数の戻り値も配列の中身もチェックしてないですけど(笑))ますね。
どうしても、fread() したければそれでもいいでしょうが、念のため、fwrite() 後に fflush() でも入れておいたらどうでしょうか?^^![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_16.png?5a7ff87)
No.11
- 回答日時:
それから、『FILE構造体の中身を…』と質問の文章中にありますが、FILE 構造体のメンバを FILE を定義しているシステムのインクルードファイルなどで調べて、その各々をチェックしてみたという意味ですか?
http://www5c.biglobe.ne.jp/~ecb/c/12_02.html
_tfopen_s() というのを fopen("hoge.map", "w+b") に変えてみるとか。
しかし、すべて戻り値が正常なのにファイルができないとは。。。MicroSoft は不思議だ^^
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_16.png?5a7ff87)
No.10
- 回答日時:
ちょっと思ったのは、fwrite() したあと、すぐ fread() してるので、stdio の内部バッファ内ですべて行えて、実際、ディスクへの書き出しが行われないのかとも思いましたが、それはないですよね。
。やっぱり(笑)オープンも成功し、書き出しも成功してるのに、そのオープンした名前のファイルができないのは、不思議だ。。。![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_16.png?5a7ff87)
No.9
- 回答日時:
fwrite() などで書き込みが成功しているのにファイルができないというのは摩訶不思議ですねぇ^^ 知らないうちに unlink() みたいなことしてるのかしら(笑)
>『関数の途中で変数宣言をしたりしているので…』
C99になってから、ブロックの先頭でなくても、変数宣言してよくなったようです(わたしも、つい最近まで知らなかった^^;)
No.8
- 回答日時:
#1の補足で提示されているエラーが再現できるというコードですけど
コンパイルすらできないのですが、本当にこれで再現できますか?
ちょこちょこ手直ししながらコンパイルしてみましたが、途中で
面倒になってやめてまいましたが
//●ファイルを開くダイアログ
void OpenFile(HWND hWnd, TCHAR file_name[])
Win32API に同名のものがあります。
windows.hをinclude しないでやるのならわからないでもありませんが
HWNDやTCHAR、BYTEなんかを使っているからそうではないですよね?
#提示プログラムではincludeしていませんが
また、関数の第二引数が TCAHR [] となっていますが
呼び出すところが
OpenFile(hWnd, g_save_data);
となっており、この g_save_data は
//●グローバル変数
Data g_save_data[DATA_NUMBER];
//●ファイルとして出力する構造体
typedef struct
{
TCHAR file_name[CHAR_SIZE];
BYTE id;
}Data;
です。
関数の途中で変数宣言をしたりしているので、C++モードでコンパイル
しているのでしょうが、いくらなんでもこの型違いは見逃してもらえない
と思います。
この回答への補足
分かり易いように変数名を変えたりした後に、コンパイルして確かめていなかったせいだと思います。申し訳ありません。
今度は同じツールなら確実に動くソースを作りました。コンパイルチェック済みですコピー&ペーストでそのまま使えます。ウインドウ枠内の『右クリックでファイルを開く』、『左クリックでファイル保存』です。
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
//●マクロ定数
#define CHAR_SIZE 256
#define DATA_NUMBER 6
#define CLASS_NAME TEXT("strClsName") //ウインドウクラスの名前
#define WINDOW_TITLE TEXT("my_window") //ウインドウ名
#define SCREEN_WIDTH 256 //画面・横
#define SCREEN_HEIGHT 256 //画面・縦
//●ファイルとして出力する構造体
typedef struct
{
TCHAR file_name[CHAR_SIZE];
BYTE id;
}Data;
//●グローバル変数
Data g_save_data[DATA_NUMBER];
//●ファイルを開くダイアログ
void OpenFile(HWND hWnd, TCHAR file_name[])
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = TEXT("png files {*.bmp}\0*.bmp\0") TEXT("all files {*.*}\0*.*\0\0");
ofn.lpstrFileTitle = (LPWSTR)file_name;
ofn.nMaxFileTitle = CHAR_SIZE;
ofn.lpstrFile = NULL;
ofn.Flags = OFN_FILEMUSTEXIST;
GetOpenFileName(&ofn);
}
//●ファイルを書き込む
void SaveData(Data save_file[])
{
FILE *file;
errno_terr;
size_t write_num;
//書き込む
err = _tfopen_s(&file, TEXT("hoge.map"), TEXT("w+b"));
if(err != 0)return;
write_num = fwrite(save_file, sizeof(Data), DATA_NUMBER, file);
//きちんと書き込めているか確かめる
Data chek_data[6];
fseek(file, 0L, SEEK_SET);
fread(chek_data, sizeof(Data), DATA_NUMBER, file);
fclose(file);
}
//●ウインドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_KEYDOWN: //Escキーで終了
if(wParam == VK_ESCAPE)
{
DestroyWindow(hWnd);
}
break;
case WM_LBUTTONDOWN:
SaveData(g_save_data);
break;
case WM_RBUTTONDOWN:
OpenFile(hWnd, g_save_data[0].file_name);
break;
case WM_DESTROY: //ウインドウが破棄された
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, msg, wParam, lParam));
}
return TRUE;
}
//●エントリポイント
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
ZeroMemory(g_save_data, sizeof(g_save_data));
//ウインドウクラスの作成と登録
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszClassName = CLASS_NAME;
wc.hIconSm = NULL;
if(!RegisterClassEx(&wc))
{
return FALSE;
}
//ウインドウを生成
HWND hWnd;
int width = SCREEN_WIDTH + GetSystemMetrics(SM_CXDLGFRAME) * 2;
int height = SCREEN_HEIGHT + GetSystemMetrics(SM_CYDLGFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
hWnd = CreateWindow(CLASS_NAME, WINDOW_TITLE, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL);
if(!hWnd)
{
return FALSE;
}
//メッセージループ
MSG msg;
PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE );
while(WM_QUIT != msg.message)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_16.png?5a7ff87)
No.7
- 回答日時:
『GetOpenFileName() というのは…』って違うか^^ Java のファイルダイアログみたいに、ファイル選択ダイアログを表示するだけのことか^^
で、そのダイアログで、ユーザがファイルを選択して、<Save>ボタンみたいなのをクリックすると、SaveData() が呼び出されるように設定してるってことですよね、たぶん(笑)。失礼しました^^
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- C言語・C++・C# #include <stdio.h>int main(void) { int buf[100] = 6 2022/11/01 22:45
- その他(プログラミング・Web制作) Fortranでの出力ファイル 2 2023/03/21 21:25
- HTML・CSS CSSが効かずどのように指定すれば良いか分からないのでアドバイスお願い致します 2 2023/06/07 12:25
- その他(プログラミング・Web制作) セレクトボックスで選択された値をコントローラーで使用したい 2 2022/07/26 16:41
- Visual Basic(VBA) vbaの構文の修正相談(xmlファイルを順に開いてコピペ作業) 1 2023/04/22 01:18
- その他(プログラミング・Web制作) pythonのこのエラーがわかりません 3 2022/11/16 14:54
- PHP PHPで画像の渡しが上手く行きません。 1 2023/02/02 09:39
- Visual Basic(VBA) 動かなくなってしまった古いVBAを動くようにしたい 8 2022/09/20 13:57
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAを何回も作り直して、容量が...
-
1 つ以上の複数回定義されてい...
-
<math.h>があるのにsqrtが・...
-
C言語でヘッダファイルにグロー...
-
【VC++6.0(MFC)】警告「LINK : ...
-
「fatal error C1189」を回避す...
-
セミコロンについて
-
クリティカルエラー Expressio...
-
cygwin でstackdump
-
マクロ コンパイルがグレーバック
-
sys/types.hの必要性について
-
エクセルVBAではRound...
-
構造体をファイルに出力できません
-
C++Builderでの警告
-
ビルドとリビルドの違いを教え...
-
” OS ビルド ” の意味が分か...
-
C++コンパイル時に『 C1083: in...
-
windowsでLinuxで作成したソー...
-
FindFirstFileについて教えてく...
-
SingleCompile.vimでmsvc110
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAを何回も作り直して、容量が...
-
<math.h>があるのにsqrtが・...
-
” OS ビルド ” の意味が分か...
-
1 つ以上の複数回定義されてい...
-
「fatal error C1189」を回避す...
-
ILSpyで、デコンパイルできない。
-
Makefile作成時の拡張子.oとは?
-
エクセルVBAではRound...
-
C言語でヘッダファイルにグロー...
-
外部シンボル "_main"は未解決です
-
セミコロンについて
-
マクロ コンパイルがグレーバック
-
戻り値について
-
C言語でmからnまでの合計を求め...
-
C++コンパイル時に『 C1083: in...
-
コンパイルエラー:ユーザ定義...
-
クリティカルエラー Expressio...
-
PRO*C コンパイルエラー
-
【VC++6.0(MFC)】警告「LINK : ...
-
[c++] <pthread.h>がinclude で...
おすすめ情報