BUAA程设第二周上机总结
long long数据的使用
在做题的时候同学们要注意所给的数据范围。
i
n
t
int
int 的数据范围是
−
2147483648
~
2147483647
-2147483648~2147483647
−2147483648~2147483647 ,如果数据的运算可能会超过这个范围,就需要使用
l
o
n
g
l
o
n
g
long\ long
long long 这一数据类型。在读写
l
o
n
g
l
o
n
g
long\ long
long long 的时候要注意使用正确的格式符%lld
。
long long num;
scanf("%d", &num); //wrong!
scanf("%lld", &num); //yes!
在这次做题情况时同学们使用 i n t int int 存储读入的数据,计算输出会错误,这是因为在计算两个 i n t int int 数相乘的过程中已经出现了错误,实际上是将一个错误的结果存储到了要输出的 l o n g l o n g long\ long long long 数中。
int a, b;
long long ans;
scanf("%d%d", &a, &b); //此时读到了两个很大但是在int范围内的数字
ans = a * b; //虽然a和b都在int范围内,但是a*b超出了int的范围,故计算得到的是错误的结果
以后在做题时同学们要记得根据题干的数据范围选择合适的类型来存储数据哦。
for循环的执行过程
我发现有一些同学对 f o r for for 循环掌握得还不是很好。这里我推荐大家多使用 f o r for for 循环而不是 w h i l e while while ,很多时候这能够提高代码可读性。(当然不是说 w h i l e while while 不好的意思)
下面以一个 f o r for for 循环举例:
for(/*第一部分*/; /*第二部分*/; /*第三部分*/){
//第四部分
}
将 f o r for for 循环分为如上四个部分。第一部分是 f o r for for 的初始化部分,这部分只会执行一次。第二部分是 f o r for for 循环的条件判断部分,在这里判断循环是否继续进行。在第三部分,你可以对变量进行一些运算操作。第四部分是 f o r for for 循环的主体循环代码,这里是循环的主体部分。
那么当程序运行到
f
o
r
for
for 循环时,将会按照这样的顺序执行:
先执行第一部分的代码,然后对第二部分内的条件进行判断,如果成功则执行第四部分的代码,执行完第四部分后执行第三部分,随后回到第二部分对条件进行再次判断,以此循环。
下面以向数组中读入一百个数字举例:
int num[100];
for(int i = 0; i < 100; i++){
scanf("%d", &num[i]);
}
初值问题
尽管上周已经说过这个问题了,这周依旧有不少同学在犯这个错误。这里我建议大家在定义变量的时候不如直接习惯性的把变量赋值为 0 0 0 ,可以有效避免初值问题。
此外在定义变量的时候可以尝试一行定义一个变量,这样其实更加符合代码规范。
int sum = 0;
int ans = 0;//比如这样
不定组输入
同学们在这周遇到了不定组输入的问题。我在这里稍微讲解一下原理:
在此仅讲解使用 scanf()
读入的情况。我们需要利用到 scanf()
的返回值。如果scanf
成功读取了 n
个数据,就将返回 n
,如果读取到了文件末尾或是读取失败,则会返回 -1
。
此外科普一下 EOF
这个宏,它的意思是 -1
。
因此我们就会使用这样的代码来解决不定行输入:
while(scanf("%d", &a) != EOF){ //实际上的意思是当scanf()返回-1的时候,退出循环。
//...
}
当读到文件末尾时, scanf()
就会返回 -1
,此时即退出循环。
在终端调试的时候,可以使用快捷键 ctrl+Z
来指示读取结束。
判断相等与不等
再次强调判断两个数字相等要使用 ==
而不是 =
,此外如果想判断两个数字不等则使用 !=
。!
在C语言中表示逻辑非。
读取数据记得加&
在使用 scanf()
函数时,记得添加 &
!!!这是一个简单却又易错的问题。如果不能正确读入数据,无论后面的代码写了什么都无济于事~
scanf("%d", n); //wrong!
scanf("%d", &n); //yes!
scanf()函数内部不要添加换行符
我看到有些同学在使用 scanf()
函数的时候会有这样的写法:
scanf("%d\n", &n);
我的建议是,无论在什么时候都不要在 scanf()
内部使用 \n
。这有可能让你的程序在评测机上卡死,无法完成读入操作。
printf()函数内部可以添加换行符
评测机不会检查输出末尾的换行符,因此向 printf()
末尾添加换行符是没有问题的。此外有些题干要求有多行输出,此时就一定要记得在需要换行的时候输出换行符。
定义数组时要确定数组大小
是不推荐大家在C语言中使用动态数组的。许多同学还不理解动态数组的概念,用浅显的话说就是,在定义数组的时候, []
内部要传一个确定的常量,而不是变量。
//假如你想开一个容量是100的数组,而现在你恰好拥有一个值是100的变量n
int num[n]; //不推荐!
int num[100]; //推荐!
在做题的时候建议同学们开的数组容量比题干所给的数据范围稍微大一点点,不要正好卡着数据范围开数组。
此外是在 m a i n main main 函数内部开的数组容量不要超过 1 e 5 1e5 1e5 。这可能会直接导致程序死亡。(涉及全局变量和局部变量的区别,可以参见第一周总结。)
数组下标从零开始
比如我们定义了一个 num[100]
,实际上我们可以使用的下标是
0
~
99
0~99
0~99 。数组的第一个数字将被存储在 num[0]
的位置上。
强制类型转换
在C语言中强制类型转换的语法:<type><data>
。
强制类型转换可以实现一些方便的操作,比如方便的舍弃 d o u b l e double double 数的小数位,我们只需要:
int i = (int)d; //注:小数在强制类型转换为整数时会舍弃小数部分,这里的d假设是一个小数
同学们可以自行搜索学习C语言类型转换的知识,这里就不过多介绍了。
关于评测姬
很多同学都有这样的疑问:为什么我本地跑样例过了,交上去却WA了?
这是因为样例给的数据是比较弱的,评测姬在后台评测的时候会使用一些比较强的数据测试你的程序。如果WA了那一定是你的程序还有哪些地方考虑的不够周全。
如果REG了就优先检查和数组有关的地方,使用数组的时候不要出现下标越界的情况。举例来说,最常见的错误比如:
int num[100]; //定义了一个数组
num[100] = 0; //Oh No!
上面提到,容量为
100
100
100 的数组,实际上可使用的下标范围是
0
~
99
0~99
0~99 ,那么我们就不能使用 num[100]
,这就是一种下标越界错误。(实际上是使用了非法的地址)
结语
同学们在第二次上机可能遇到了一些困难,希望大家不要气馁。在课后多练习、做题、学习,相信大家最后都能够掌握C语言!
那么,第二周的总结就先到这里结束,希望同学们再接再厉!