2010-04-04 201 views
19

我在C中使用fopen將輸出寫入文本文件。該函數聲明爲(其中ARRAY_SIZE前面已經定義):fopen/fopen_s和寫入文件

void create_out_file(char file_name[],long double *z1){ 
    FILE *out; 
    int i; 

    if((out = fopen(file_name, "w+")) == NULL){ 
    fprintf(stderr, "***> Open error on output file %s", file_name); 
    exit(-1); 
    } 

    for(i = 0; i < ARRAY_SIZE; i++) 
    fprintf(out, "%.16Le\n", z1[i]); 
    fclose(out); 
} 

我的問題:

  1. 在編譯時有MVS2008我得到警告:警告C4996: '的fopen':此函數或變量可能是不安全的。考慮使用fopen_s代替。我沒有看到關於fopen_s的很多信息,以便我可以更改我的代碼。有什麼建議麼?

  2. 是否可以指示fprintf將數字以期望的數字精度寫入文件?如果我使用的是long double,那麼我認爲我的答案是好的,直到小數點後15位。我對嗎?

+16

對fopen()沒有任何遠程不安全的想法,但MS中的一些人似乎已經失去了他們的集體大理石而不是以空字符結尾的字符串作爲參數的函數。 – 2010-04-04 17:04:02

+0

我相信這是微軟將所有人鎖定到僅限於Windows的編程的情節。 – stackptr 2016-02-16 17:08:40

回答

16

fopen_sfopen一個變體,它包含的參數驗證和手回一個錯誤代碼,而不是在一些情況下,一個指針超出在開放過程中出錯。它比基本變體更安全,因爲它考慮了更多的邊緣條件。編譯器警告您使用它,因爲fopen代表您的應用程序中可能的開發向量。

您可以使用符%.xg,其中X是你在輸出想要的精確數字指定的精度爲printf家庭的功能位。 A long double從平臺到平臺的精度各不相同,但您通常可以相信它至少有16位數的小數精度。

編輯:雖然我不完全在船上,誰是暗示fopen_s是時間的完整浪費別人,但它代表了一個相當低的剝削機會,它沒有得到廣泛的支持。然而,在C4996下警告的其他一些功能有更嚴重的漏洞,而使用_CRT_SECURE_NO_WARNINGS相當於關閉了「您的臥室門已解鎖」和「您在廚房留下核彈」的警報。

只要您不限制爲您的項目使用「純粹的C」(例如,對於學校任務或嵌入式微控制器),您可以利用幾乎所有現代C編譯器都是C++編譯器的事實,並使用所有這些I/O函數的C++ iostream變體來獲得更高的安全性兼容性。

+0

謝謝。我的代碼中有fprintf(out,「%.16Le \ n」,z1 [i]),是的,我得到了d.p後的16位精度數字。 – yCalleecharan 2010-04-04 17:13:26

+0

再次感謝。我使用C,因爲這是我知道的更好。我正在編寫一個用於研究目的的代碼,它必須提供準確的結果。我不得不對構成C代碼的方程進行無量綱化,以便有一個很好的值範圍,以防止太大的值或太低的值蔓延到模擬中,從而影響解決方案。我不太瞭解C++,我不知道我是否可以將我的文件保存到cpp,並安全地使用C++ iostream,而不需要我的代碼的其他部分給我編譯錯誤。現在,我會限制自己到C,直到我知道如何切換到C++。 – yCalleecharan 2010-04-04 17:37:38

1

只要定義_CRT_SECURE_NO_WARNINGS你有擺脫這個警告的任何文件之前,停止相信什麼MS說,大約fopen

+0

謝謝。只是在頂部添加#define _CRT_SECURE_NO_WARNINGS? – yCalleecharan 2010-04-04 17:05:06

6
  1. fopen_s和所有其他_s功能是MS-特定「安全「標準功能的變體。如果你的代碼不需要跨平臺的話,你可以切換並讓編譯器高興。否則,只需將_CRT_SECURE_NO_WARNINGS預處理器指令添加到您的項目設置中,它就會停止警告您。

  2. 是的,long double對於15位數的精度很容易;實際上,即使是常規雙打也足夠多(但不多)。

+0

謝謝。在我的32位機器上,double和long double都給我16位精度,第16位是不準確的。 – yCalleecharan 2010-04-04 17:14:04

+0

是的,「長雙倍」大小是平臺依賴的;可悲的是,MSVC++使它與'double'一樣,所以沒有用。一個64位雙精度的尾數爲53位,大約爲15.95位十進制數(log10(53))。 – tzaman 2010-04-04 19:50:51

+0

感謝您的信息。 – yCalleecharan 2010-04-05 23:21:49

4

其他海報指出,fopen不是非常不安全。如果你不想要這個警告,但你確實想要其他的警告真正的漏洞,不要 #define _CRT_SECURE_NO_WARNINGS

取而代之,下次您收到fopen警告時,請點擊「請參閱'fopen'聲明」一行。這將帶你到stdio.h中注入警告的行。從該行刪除文本_CRT_INSECURE_DEPRECATE(fopen_s),當您使用fopen時,您將不再收到安全警告,但它將保留爲strcpy,strdup和其他可能危險的警告。

+1

實際上在windows上開放的「標準」實現確實存在一些漏洞,這是由於14,125,16歲的小孩沒有更好地利用他們的時間,而不是找到破解其他人的計算機的方法,所以他們想出了一個不同的方式來傳遞文件描述符,使青少年難以使用 – BrierMay 2013-08-11 23:41:43

8

我遇到了一個與Visual Studio 2012一起工作的類似問題,但是我的問題展開的地方是我正在構建一個程序,我想使用Visual Studio的鈴聲和哨子進行測試,並最終能夠編譯和運行同樣的應用程序在我的Linux服務器(我正在製作一個機器人)

所以這是我想出了一些谷歌後,認爲我會張貼它,以防萬一它可以幫助其他人。

FILE *fp_config; 
const char *configfile ; 
configfile = "bot.conf"; 
#ifdef WIN32 
    errno_t err; 
    if((err = fopen_s(&fp_config, configfile, "r")) !=0) { 
#else 
    if ((fp_config = fopen(configfile, "r")) == NULL) { 
#endif 
     fprintf(stderr, "Cannot open config file %s!\n", configfile); 
    } 

這將安撫Visual Studio和它不會抱怨,它也將允許相同的代碼編譯在海灣合作委員會或任何其他符合標準的C/C++編譯器

4

從FOPEN移動到fopen_s禁用的能力文件打開並寫入時在記事本中打開文件(只讀)。 打開回fopen,我可以讀取wile我的程序寫入文件。

+0

從[參考](http://en.cppreference.com/w/c/io/fopen):當使用fopen_s或freopen_s時,文件使用「w」或「a」創建的任何文件的訪問權限會阻止其他用戶訪問它。文件訪問模式標誌「u」可以有選擇地添加到以「w」或「a」開頭的任何說明符中,以啓用默認的fopen權限。 (C11) – 2017-05-28 22:09:23