编译问题(该问题只与VC相关,与Codeblocks无关)
scanf 忘记 &
输入与输出的次序
有题目的要求如下
http://125.221.232.253/JudgeOnline/problem.php?cid=1090&pid=1
样例输入
4
3 4 4
3 4 5
3 4 6
3 4 7
样例输出
Acute triangle
Right triangle
Obtuse triangle
NO
这个题目有多组数据(示例中是4组), 是不是要全部先读入所有的数据, 然后再产生所有的输出呢? 答案是你可以这样做,但是没有必要。完全可以读入一个,处理一个,也就是,在屏幕上的输入输出效果如下也是正确的:
4
3 4 4
Acute triangle
3 4 5
Right triangle
3 4 6
Obtuse triangle
3 4 7
NO
输入的约束条件
比如下面的题目:
编写程序,给出一个其值不超过12345678的正整数,求出它是几位数。
有些同学的代码类似下面的
1 int n; 2 scanf("%d", &n); 3 if(n <= 12345678)
第3行的判断是没有必要,每个题目提交以后OJ都会用数据来测试你的程序,题意保证测试你程序的数据不超过12345678,并不需要你自己来检查。
题目中给定条件约束往往决定了能使用什么方法,比如下面的题目:
2010省赛题:数字整除
题目描述
定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍。当且仅当差是17的倍数时,原数也是17的倍数 。例如,34是17的倍数,因为3-20=-17是17的倍数;201不是17的倍数,因为20-5=15不是17的倍数。输入一个正整数n,你的任务是判断它是否是17的倍数。
输入
输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1<=n<=10100),表示待判断的正整数。n=0表示输入结束,你的程序不应当处理这一行。
注意到n的范围远远超过了int,long long所能表示的范围,所以你无法用一个整数类型存储n,解决的方法是用字符串来存储n,再模拟除法。
范围往往决定了你需要的存储空间,比如下面的题目
问题 G: 实验7_3:多行字符串反转输出
题目描述
输入多行字符串,把这些字符串逆序且反转输出。
输入
输入多个(小于30个)字符串,每行一个字符串,字符串长度不超过30
这意味你可以定义一个字符数组 char s[30][31]; 来存储所有的输入
多组数据状态的初始化
先来看一组数据的例子,求1到n的总和
1 #include <stdio.h> 2 3 int main() 4 { 5 int i, n; 6 int sum = 0; 7 8 scanf("%d", &n); 9 for(i = 1; i <=n; i++) 10 sum += i; 11 printf("%d\n", sum); 12 13 return 0; 14 }
sum初始化为0是大家熟悉的, 但是如果要求输入多个n,分别求1到n的总和呢?许多同学会犯错,见下面的第6行,sum 清0只进行了一次,后面sum的计算是在前一次的基础上进行的
1 #include <stdio.h> 2 3 int main() 4 { 5 int i, n; 6 int sum = 0; 7 8 while(scanf("%d", &n) != EOF) { 9 for(i = 1; i <= n; i++) 10 sum += i; 11 printf("%d\n", sum); 12 } 13 14 return 0; 15 }
对于多组数据,如果状态是针对每一组数据,则每一组数据都应该初始化其状态一次,见下面的第9行
1 #include <stdio.h> 2 3 int main() 4 { 5 int i, n; 6 int sum; 7 8 while(scanf("%d", &n) != EOF) { 9 sum = 0; 10 for(i = 1; i <= n; i++) 11 sum += i; 12 printf("%d\n", sum); 13 } 14 15 return 0; 16 }
读整数后再读入字符串
一个常见的情况是先读入整数n,再读入n个字符串(我们假定是各自有独立的行)
如果字符串中没有空格,则可以使用下面的代码
1 #include <stdio.h> 2 3 int main() 4 { 5 int n; 6 char s[80]; 7 8 scanf("%d", &n); 9 while(n--) { 10 scanf("%s", s); 11 puts(s); 12 } 13 14 return 0; 15 }
但是字符串有空格的话,你必须用类似gets的函数,比如下面的样例
样例输入
2
zhe shi hui yin ni dong ma?
yukkuri shite itte ne!!!
你必须使用类似下面的代码,注意第9行。 因为样例的整数 2后面有回车, 如果是scanf("%s", s);则会跳过回车接收后面真正的字符串;但是gets不会,它直接碰到回车的话会认为接收到了一个空串。为了避免该情况的发生,我们用getchar()吃掉回车键。然后再用gets接收就没有问题了。
1 #include <stdio.h> 2 3 int main() 4 { 5 int n; 6 char s[80]; 7 8 scanf("%d", &n); 9 getchar(); 10 while(n--) { 11 gets(s); 12 puts(s); 13 } 14 15 return 0; 16 }
下面第8行的做法也是可行的,scanf里面的\n会忽略掉换行,但不推荐同学们这样写。
1 #include <stdio.h> 2 3 int main() 4 { 5 int n; 6 char s[80]; 7 8 scanf("%d\n", &n); 9 while(n--) { 10 gets(s); 11 puts(s); 12 } 13 14 return 0; 15 }
在函数里面开辟大数组
下面的代码是错的:
int main() { int a[1000000]; ... }
程序运行直接出错。原因局部变量分配在栈上,栈的空间往往有限制,比如Windows下的VS编译栈空间大小默认1MB,见https://msdn.microsoft.com/zh-cn/library/tdkhxaks.aspx。
解决办法:
(1)将a定义为全局变量,推荐同学们使用
(2)使用malloc动态分配空间
(3)见上面的链接,设置编译器选项,调整栈大小。不推荐,因为OJ题目上交上去不一定本地机器的编译器了