質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

18988閲覧

C言語でファイルの書き込みができません(Visual Studio)

programming

総合スコア476

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2016/08/17 10:18

編集2016/08/17 11:46

###前提・実現したいこと
初めて質問します。

Visual Studio 2015 Community を使ってC言語の学習をしている初学者です。
C言語の入門書を用いてサンプルプログラムを実行しています。
ファイルへの書き込みを学んでいますがエラーが出て動きません。
どうやら fopen が非推奨になり fopen_s を使わなければならなくなったためと思われます。

インターネットで検索してもよく分かりませんでした。
何が起きておりどのように対策をすればよいかを教えてください。

###発生している問題・エラーメッセージ
out1.txtに関する動作は正常に動くのですが
(フォルダがなければ "dir1\out1.txtが作成できません"と表示され、フォルダがあれば正しくファイルが生成されます。)
out2.txtに関する動作になるとエラーが出ます。

以下は Visual Studio の出力のデバッグ欄に表示されたメッセージです。

File: minkernel\crts\ucrt\src\appcrt\stdio\output.cpp Line: 31 Expression: stream != nullptr For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

###該当のソースコード

C

1#include "stdafx.h" 2int main(){ 3 FILE *FP; 4 errno_t err; 5 6 err = fopen_s(&FP, "dir1\\out1.txt", "w"); 7 if (FP == NULL) { 8 printf("dir1\\out1.txtが作成できません\n"); 9 return -1; 10 } 11 else { 12 printf("ファイル書き込み成功\n"); 13 fprintf(FP, "0123456789\n"); 14 fclose(FP); 15 } 16 17 if ((err = fopen_s(&FP,"dir2\\out2.txt", "w")) == NULL) { 18 printf("dir2\\out2.txtが作成できません\n"); 19 return -1; 20 } 21 else { 22 printf("ファイルに書き込み成功\n"); 23 fprintf(FP, "ABCDEFG\n"); 24 fclose(FP); 25 } 26 27 printf("プログラムを終了するには何かキーを押してください..."); 28 char x; 29 scanf_s("%c", &x); 30 return 0; 31}

また、これはサンプルプログラムを写してエラーが出たため、インターネットで調べて書き換えたものです。
サンプルプログラムでは

c

1 if ((err = fopen_s(&FP,"dir2\\out2.txt", "w")) == NULL) {

c

1if((FP=fopen("dir2\\out2.txt","w"))==NULL){

となっています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

これ

C

1err = fopen_s(&FP, "dir1\\out1.txt", "w"); 2 if (FP == NULL) {

とこれ

C

1if ((err = fopen_s(&FP,"dir2\\out2.txt", "w")) == NULL) {

を比べてみましょう。

投稿2016/08/17 10:51

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

programming

2016/08/17 11:38

回答ありがとうございます。 言い遅れましたがこれはC言語の本に載っていたサンプルプログラムを写し、うまくいかず自分でインターネットで検索して書いたものです。 質問を編集しようと思いますが、もともとは二つ目の部分は FP を使ったコードでした。
uta_luna

2016/08/17 12:42

takasima20さんのご指摘通り、何が違うのかを考えてみてください。 検索して調べるのはいいことです。調べて得られたものがどんな動きをしているのかを理解することが重要です。
programming

2016/08/17 13:06

すみません。 よく考えたところ NULL になっているか調べる相手が FP か err かの違いであると思います。 と、思って ```C if ((err = fopen_s(&FP,"dir2\\out2.txt", "w")) == NULL) { ``` の err をFP にするだけでは型が合わないそうです。 if文の中に埋め込めるような ```C err = fopen_s(&FP, "dir1\\out1.txt", "w"); if (FP == NULL) { ``` をひとまとめにできる表現はないのでしょうか。
guest

0

ベストアンサー

err = fopen_s(&FP, "dir1\\out1.txt", "w"); if (FP == NULL) {

という表現ですが、以下の様にすれば良いのでは?

if (fopen_s(&FP, "dir1\\out1.txt", "w") != 0) {

fopen_s()は成功した場合0を返しますし、仕様的には失敗した場合でも、
FPがNULLになるとはどこにも規定されていないかと思います。

投稿2016/08/17 13:49

ShinyaAnan

総合スコア241

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

programming

2016/08/17 14:02

ありがとうございます。 無事に正しく動作しました。 fopen_s(&FP, "dir1\\out1.txt", "w")自体が FP の内容を表すのですね。 本には「FP=fopen()」のときにファイルが開けなかった場合に FP に NULL が代入される決まりのようです。 ベストアンサーは甲乙つけがたいですが直接役に立ったこちらとさせていただきます。 皆さんありがとうございました。
uta_luna

2016/08/18 13:31

解決したようですが、正しく理解されていないようです。 fopen_s 関数は成功したら戻り値は「0」です。「fopen_s(&FP, "dir1\\out1.txt", "w")」自体が FP を表すのではありません。成功したら「0」が返ってきます。 if の比較文の書き方も、もう一度見直してみるといいと思います。NULLや数値の比較はわかりやすいですが、関数の戻り値で比較されることを確認してください。
programming

2016/08/19 02:37

戻り値で比較となると、このプログラムでは err が 0 かどうかを調べればよいということになるのでしょうか。 fopen_s 関数は成功したら "0" ,失敗したら "エラーコード" が返ってきたはずです。
ShinyaAnan

2016/08/19 12:28

以下の様に書く事で、fopen_s関数の戻り値と0を比較しています。 if (fopen_s(&FP, "dir1\\out1.txt", "w") != 0) { もちろん、 if ((err = fopen_s(&FP, "dir1\\out1.txt", "w")) != 0) { と書いて、戻り値を err に代入すると同時に、0と比較することもできます。 関数自身が、関数の戻り値を示します。これはC言語の仕様です。 また、代入式自身が、代入した値を示すします。
programming

2016/08/19 12:57

ありがとうございます。 では、 ・fopen_s関数自体が戻り値を表す  →関数自体が戻り値のように扱える ・戻り値を何かに代入する場合は fopen_s関数の戻り値の型である errno で宣言した err に代入することができる ということですね。 思えば FP はファイルポインタであるので、ファイルの場所を表すだけであり、 関数の動作には関係しませんね。 私は以上の認識です。間違っていたらすみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問