这次的歌是《悠哉日常大王》的ED

我们这些大一学生刚学到C语言基础的“输入与输出”这一部分。由于坚信“实践是最好的老师”,于是我又一次开始着手编程。自己的平板是Windows 10 ,VC++6.0肯定是运行不起来了。我又懒得去装虚拟机,正好看到巨硬提供免费的VS2017社区版,有Outlook邮箱的我就下载了它。

结果,不出我所料,兼容性问题层出不穷。下面就列出我遇到的一些问题。

问题1:输出字符后直接退出。

我先编了一个Hello World,代码如下:

#include <stdio.h>
int main()
{
printf("Hello,World!\n");
return 0;

}

结果运行后只是黑窗口一闪而过,我还以为自己编错了。最后才知道要用system("pause")来在输出后停下来。

可是我再次编译时却提示“未定义标识符system”,在网上查资料后才知道要再添加一个头文件stdlib.h。

最后的代码是:

#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("Hello,World!\n");
system("pause");
return 0;

}

问题2:无法打开源文件math.h。

我第二次想编一个解一元二次方程的小程序。由于求根公式涉及开方,C语言里的开方函数是sqrt,需要头文件math.h的支持。但是VS2017提示无法打开math.h。

这是因为VS2017的默认新建C/C++项目的库目录中没有包含有math.h的目录,要手动在项目属性-配置属性-C/C++-所以选项-附加包含目录里添加。而且比较坑的是,因为版本问题,添加的目录在不同电脑上是不同的。

 

同时还要去VC++目录里添加相应的库目录。

问题3: 'scanf': This function or variable may be unsafe. 

解决了sqrt的问题,再编译还是出错,提示scanf不安全,在网上查资料后给了我这样的解释;


旧式的scanf在读取数据的时候会根据format指示从缓冲区中读取直至结束,但有些时候我们的format指示会有Bug,导致scanf读取了给定的缓冲区以外(数组越界)的数据。看下例

int a = 0;
scanf("%d", &a);
假设我们输入数字123456,然后按回车。缓冲区中应该是一个数组123456,加上一个换行符,通常是"\r\n"。
这时候我们可以正常地读取到数字a。
但“有些时候”,缓冲区中的数据并不一定正确,这时候我们需要限制scanf的读取范围,通常是给定缓冲区的起始位置和缓冲区的长度。这样可以安全地处理错误数据。
但涉及CRT的人在涉及scanf的时候没有考虑到这么多的不安全因素,所以有了安全版本的scanf,及scanf_s,s的意思就是safe,我们会看到很多_s版本的函数,sprintf_s,vsnprintf_s等等,它们的作用都是一样的。
总之,带_s的函数是不带_s的安全版本,我们在代码中应当尽量使用安全版本。

在VS2005以及以后的VC++中,如果我们使用了不安全的版本,编译器会给我们一条警告,警告的内容就和下面的一样。
'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\users\user\documents\visual studio 2013\projects\test\test.cpp 8 1 Test


我真是懒得吐槽巨硬了,安全就安全吧,我把所有的scanf换成了scanf_s。

接下来再编译,终于成功了!

但我很快发现自己又悲剧了。

问题4:输出中文乱码。

就是上图的样子。还好我的耐心还有,并且我知道这是编码的问题。不过我找解决方案时,还是用了“VS2017输出中文乱码”。网上给出的解决方法大体上分为三种。

第一种是安装ForceUTF8这个插件,然而我硬是没找到它。

第二种是利用自定义添加“高级保存”,从而把源码保存为GB2312格式。我也是使用了这一种方法。

还有一种方法是把代码导出到Notepad++之类的专业文本编辑工具中转码,再用VS重新打开项目。最后改掉源码中的乱码部分。我觉的相较别的方法麻烦了一点,于是没用使用这种方法。

问题4:第二个及之后的scanf_s函数不起作用。

这个问题在之后的运行测试中被发现,可以正常输入第一个变量a的值,但之后的输入代码就失效了。我之后也把源码给了我的C语言老师看,他认为代码没问题,而这个问题到现在都没解决,源码如下:

// ConsoleApplication1.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdlib.h" //支持sstem函数
#include "math.h" //支持sqrt函数
#include "stdio.h"

int main()
{
float a, b, c, x1, x2, step; //定义a、b、c、x1、x2与中间变量step
printf("本程序可用来解形如ax?+bx+c=0(x≠0)的一元二次方程。\n");
system("pause");
printf("请输入a:");
scanf_s("f%", &a); //录入a
printf("请输入b:");
scanf_s("f%", &b); //录入b
printf("请输入c:");
scanf_s("f%", &c); //录入c
step = b*b - 4 * a*c; //计算b?-4ac
step = sqrt(step); //计算(b?-4ac)^(1/2)
x1 = (b + step) / (2 * a); //计算x1
x2 = (-b + step) / (2 * a); // 计算x2
printf("方程的解为\n");
printf("x1=%f\n", x1); //输出x1
printf("x2=%f\n", x2); //输出x2
printf("按任意键退出\n");
system("pause");
return 0;
}

 

总结:看来学校里一般只用VC++6.0学习C语言还是很有道理的。

 

最后更新于 2019-04-18