ACM提交,C++,G++,C,GCC的区别
今天做了一道水题,POJ-1004,水题一个,12个double类型的数求平均数
但是,
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int main() { 5 double n; 6 while (cin>>n) { 7 int i=0; 8 double total = n; 9 while (i++<11) { 10 cin>>n; 11 total += n; 12 } 13 printf("$%.2lf\n", total/12); 14 } 15 return 0; 16 }
这个看起来没毛病的代码,竟然WA了,
又WA两次之后,这不是代码的事,分别用GCC,G++,C++提交,到C++的时候,A了!!!
总结总结,避免再犯
------------------------------------------------------------------------------------------------------------------------
放在最先:G++和GCC分别是C++和C的编译器,C++和C是语言。
但POJ上的则表示你提交代码运行所需的编译器,C和C++对应的编译器是VC++ 2008里面的C和C++编译器,而GCC和G++则对应相应的编译器。
那我上面既用了printf又用了cin怎么提交?
看到一篇博客叙述:G++和C++选项下的代码是没有差异的,但在库上面,两者有一定差距,比如G++默认可以cin一个string变量,而选择C++时则需要#include<string>,如果用C++编写代码,提交时最好选择G++作为编译器。
不好意思,我没用string类, 但是G++提交WA!!!
说明区别不止这一点。
------------------------------------------------------------------------------------------------------------------------
为什么G++提交WA了?
好吧回到现实中来。我昨天在做poj 3122这道题的时候,再一次的遇到了G++WA;C++AC的尴尬局面。
为什么呢?其实这个也算是编译器优化的一部分,那就是精度缺省。
众所周知,long long类型,作为一个在C/C++11才被确认为基本数据类型的一个数据类型,在不同的环
境下,他的类型标识符是不同的。也就是我们津津乐道的%lld 和 %I64d了。同样,double类型也是一
个有趣的类型。double类型其实准确地说是双精度型,他的内存长度一般是比float类型(单精度型)
的多了一倍,有的时候很早的标准里是把double称为long float的。所以说就有了为什么float类型
用%f,double用%lf。但是由于现在不是以前的那种一个内存条就几兆,多开一个double就会超内存的
年代了,所以double还有float在gcc中被自动优化。
在用scanf读数据时,为了与float区分,使用%lf。
在用printf写数据时,由于实质上,double和float是同一个类型,只不过内存占用有差异而已,他们
的标识符都是%f,注意,这个和标准C不同,这里的都是%f。
当然对于另外一个特殊的类型long double虽然不常用,但是编译器依旧在支持,这里有个插曲,理论
上long double应该是两倍的double(类似long long和int的关系,因为long和int其实是一个东西)
。但是实际上,long double很奇怪的是一个10字节的怪物,他有两个空余字节,是怎么改动都不会发
生变化的。输入输出的标识符都是%Lf,大写的L。
但是这里又有问题了,为什么我在本地用%f会WA,在OJ上用%f会AC?
因为我们本机如果使用的是Windows下的Code::Blocks这款IDE的话,编译器也就是MinGW这个东西。事
实上,为了尽量保持gcc的跨平台性,MinGW在某些地方是直接用了MSVC的东西的,而对我们影响最大的
就是这个标识符的问题。简单的说,如果你是要在本机测试,那么最好,请使用标准C的那个标识符系
统;如果你要提交代码,那么请改成gcc的那一套标识符系统。
再有就是编译器版本的问题,现在的MinGW版本已经到了4.8,但是POJ上仍然使4.4,所以低版本的编译
器同样会有一些不寻常的问题。
当然还有更简单的方法,就是直接用输入输出流在控制输入输出,这样更省事,而且跨平台性能更好,
不会出现这种因为标识符而出错的情况。
列个表格出来就是这个样子的:
列个表格出来就是这个样子的:
double f; | POJ G++提交 | POJ C++提交 | 本机测试(MinGW GCC 4.8) | 最安全的方法 |
输入 | scanf(“%lf”, &f); | scanf(“%lf”, &f); | scanf(“%lf”, &f); | cin >> f; |
输出 | printf(“%f“, f); | printf(“%lf”, f); | printf(“%lf“, f); | cout << f; |
------------------------------------------------------------------------------------------------------------------------
原来还有精度的问题,那么总结:
1.用string的时候,c++需要包含头文件:#include <string>,G++不需要
2.精度问题
3.使用GCC/G++的提醒:
对于64位整数, long long int 和 __int64 都是支持并且等价的.但是在读和写的时候只支持scanf("%I64d", ...)和printf("%I64d", ...).
不支持"%lld"是因为MinGW下的GCC和G++使用的msvcrt.dll动态链接库并不支持C99标准.
根据ISO C++标准,在G++下,main函数的返回值必须是int,否则将会导致Compile Error(编译错误)的判答
4.G++/GCC使用scanf、printf时注意引用<stdio.h>/<cstdio>,只引用<iostream>不识别