新手最常见的误解和错误

编译问题(该问题只与VC相关,与Codeblocks无关)

 fatal error C1010: unexpected end of file while looking for precompiled header directive 
 

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题目上交上去不一定本地机器的编译器了

 

posted on 2014-12-23 23:37  天地过客  阅读(864)  评论(0编辑  收藏  举报

导航