2010-04-04 206 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