#jitoa# 【C语言刷题技巧和错误检查】 原创
本博客由金陵科技学院-开放原子开源社陆柏廷编写
在C语言刷题的过程中,最重要的不是代码的敲写,而是思路的形成。随着题目难度的上升,程序的复杂度也越来越高,但其实再复杂的题目也不过是由无数基础题目的思路堆叠而成的。因此,在做基础题时,我们就可以有意识的记住它的思路和方法,甚至以后当作源码直接拿出。
1.【冒泡排序】
题目(1)冒泡排序:
将输入的n个数按从小到大的顺序输出。
代码:
#include <stdio.h>
int main(){
int n,i,j;
int a[100];
int b;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d\n",&a[i]);
}
for(i=1;i<=n-1;i++){
for(j=1;j<=n-1-i;j++){
if(a[j+1]<a[j]){
b=a[j];
a[j]=a[j+1];
a[j+1]=b;
}
}
}
for(i=1;i<=n;i++){
printf("%d ",a[i]);
}
return 0;
}
题目(2)成绩排序:
给出班里某门课程的成绩单,请你按成绩从高到低对成绩单排序输出,如果有相同分数则名字字典序小的在前。
输入格式:
第一行为n (0 < n < 20),表示班里的学生数目;
接下来的n行,每行为每个学生的名字和他的成绩, 中间用单个空格隔开。名字只包含字母且长度不超过20,成绩为一个不大于100的非负整数。
输出格式:
把成绩单按分数从高到低的顺序进行排序并输出,每行包含名字和分数两项,之间有一个空格。
输入样例:
在这里给出一组输入。例如:
4
Kitty 80
Hanmeimei 90
Joey 92
Tim 28
输出样例:
在这里给出相应的输出。例如:
Joey 92
Hanmeimei 90
Kitty 80
Tim 28
代码:
#include <stdio.h>
#include <string.h>
struct student{
char name[30];
int score;
};
int main(){
int n;
int i,j;
struct student b;
struct student a[100];
scanf("%d\n",&n);
for(i=1;i<=n;i++){
scanf("%s %d\n",&a[i].name,&a[i].score);
}
for(i=1;i<n;i++){
for(j=1;j<=n-i;j++){
if(a[j].score<a[j+1].score){
b=a[j];
a[j]=a[j+1];
a[j+1]=b;
}else if(a[j].score==a[j+1].score&&strcmp(a[j].name,a[j+1].name)>0){
b=a[j];
a[j]=a[j+1];
a[j+1]=b;
}
}
}
for(i=1;i<=n;i++){
if(i!=n){
printf("%s %d\n",a[i].name,a[i].score);
}else if(i==n){
printf("%s %d",a[i].name,a[i].score);
}
}
return 0;
}
本题中要求有相同分数则名字字典序小的在前,正是利用了题目(1)的冒泡排序,只不过题目(2)变成了姓名的大小比较,思路仍然相同。
2.【递归】
题目(1)斐波那契数列:
斐波那契数列的是这样一个数列:1、1、2、3、5、8、13、21、34…,即第一项 f(1) = 1,第二项 f(2) = 1…,第 n 项目为 f(n) = f(n-1) + f(n-2)。求第 n 项的值是多少。
int f(int n){
// 1.先写递归结束条件
if(n <= 2){
return 1;
}
// 2.接着写等价关系式
return f(n-1) + f(n - 2);
}
用递归的关键就是找到通用的公式,方便一次次的往复。
题目(2)输出全排列:
请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。
输入格式:
输入给出正整数n(<10)。
输出格式:
输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a1,a2,…an排在序列b1,b2,…,bn之前,如果存在k使a1=b1,…,ak=bk,且ak+1<bk+1.
输入样例:
3
输出样例:
123
132
213
231
312
321
代码:
#include <stdio.h>
int x1[10],x2[10],n;
void quan(int k){
int i;
if(k>n){
for(i=1;i<n;i++){
printf("%d",x1[i]);
}
printf("%d\n",x1[n]);
return ;
}else{
for(i=1;i<=n;i++){
if(x2[i]==0){
x1[k]=i;
x2[i]=1;
quan(k+1);
x1[k]=0;
x2[i]=0;
}
}
return ;
}
}
int main(){
scanf("%d",&n);
quan(1);
return 0;
}
本题的难度与题目(1)相比上升极大,但大致的思路又很相像,其实还是递归的应用,当我们习惯递归的思维后自然可以完成更高难度的题。建议还可以练习:青蛙跳台阶,汉诺塔。
随着代码长度的增加,这时我们就可以适时引入C++的内容简化代码,用更简便的方法达到同样效果。
写题目的过程中我们更多的时间其实花在找错误上,因此,我再介绍几个写题目是常见的报错与错误的检查方法。
(1)直接提示类
这种只要跟着报错提示就可以改对。
(2)答案错误
去devc++上一步步调试,看看是哪一步出错,再进行相应的改动。调试时可以在程序中多设点中间值输出,方便确定错误的位置。
(3)答案正确,但错误
这种多半是情况没考虑全,可以多试试特殊情况,再重复第二种改法。
(4)莫名其妙运行时错误
大部分情况应该是越界,可以看看设的数组是否太小,又可能是在找寻数据的过程中超出范围了,实在不行可以换种思路做题。
(5)段错误
这是访问了不可访问的内存导致的,这种可以直接重写。