12天学好C语言——记录我的C语言学习之路



Day 7:



昨天进行了一天的数组学习,今天大家可以先写几个昨天的程序热热身,回顾回顾,然后今天第一个新程序也是关于数组的,比较难,准备好就开始啦!



//输出奇数魔方阵,每一列、每一行以及对角线之和均相等(输入n为魔方阵的阶数,n为奇数)



//首先说明一下魔方阵的形成规律:①将元素1放在第一行中间一列;②依次将数字放在前一个数字的右上角,如果超过了魔方阵的范围,就拿另一侧的位置补齐,这个步骤需要想象成一个可以穿过边界到达另一头的贪吃蛇游戏;③如果另一侧补齐的位置处有元素在,则不考虑这个位置了,就直接把元素写在上一个元素的正下方的位置



//程序分析,我们是分了四部分来写这个方阵的形成规律。①右上角②第一行除右上角③最后一列除右上角④左下角剩下的所有元素(这些元素是最普通的,无特殊处理,顶多就是如果下一个元素位置上面不为0,那么就直接写在正下方)



/* 如下图是五阶魔方阵

 17  24  1   8   15

 23  5   7   14  16

 4   6   13  20  22

 10  12  19  21  3

 11  18  25  2   9

 */



/*//program 7.1

 #include "stdio.h"

 int main()   //这个程序是下标从0开始的

 {

 printf("请输入数字n,n代表魔方阵的阶数:\n");

 int a[20][20]={0},i,j,k,n;

 i=0;

 scanf(“%d",&n);   //输入魔方阵的维度n

 j=n/2;     // j是维度的一半取整,这里一定要注意,如果下标是从0开始的,那么3阶的时候元素1的位置就是(0,1),5阶的时候元素1的位置就是(0,2),可见元素的j坐标是n/2。如果下标从1开始的话,j=n/2+1。注意注意!!!!!

 a[i][j]=1;   //确定第一排的中间一个数为1

 for (k=2; k<=n*n; k++)   //从2开始,一直到n*n,按规律存放

 {

 i=i-1;   //正常情况下的走向是往右上角走,那么确定一个值的位置后(i,j),它的下一个值坐标正常情况下应该为(i-1,j+1)

 j=j+1;

 if(i<0&&j>n-1)   //最后的问题就是i<0的情况难道不就是i=-1吗?为什么不能用i=-1来代替i<0??? 这里说的很对,i<0的情况只有一个,就是i=-1,但是我们写判定条件的时候,要这样写if(i==-1&&j>n-1),也就是两种情况都可以。

 {   //如果该值已经在整个方阵的右上角(上图元素15的位置,第一行、第n列),那么放在这个值的正下方,又因为之前经过了行数-1,列数+1的变化,所以要变回原值的正下方,故得到下面两个变化。

 i=i+2;

 j=j-1;

 }

 if(i<0&&j<=n-1)

 {   //如果该值是处于第一行的位置(但是不包括上个条件排除的右上角的值),那么它的下一个值就应该处于最底行。

 i=n-1;

 }

 

 if(j>n-1)

 {   //如果该值是处于第n-1列(最后一列)的位置,那么它的下一个值一定处于第一列了

 j=0;

 }

 if (a[i][j]==0)

 {   //如果计算出来的位置上面还没有赋值,那么就将该数值赋给该位置

 a[i][j]=k;

 }

 else

 {   //如果计算出来的位置上面已经有数值存在了,那么也是将下一个数值放在其上一个数值的正下方

 i=i+2;

 j=j-1;   //这个地方其实也是是对变化过的i、j进行再操作

 a[i][j]=k;

 }

 }

 for (i=0; i<n; i++)

 {

 for (j=0; j<n; j++)

 {

 printf("%-4d",a[i][j]);

 }

 printf("\n");

 }

 return 0;

 }

*/



上面那个程序的下标是从0开始的(第0行,第0列),可能有些刚打程序的读者有些别扭,那么下面我用下标从1开始写一下这个魔方阵程序,改了初始下标,希望读者能看出来程序哪里发生了实质上的改变。



/*//program 7.2

#include<stdio.h> //这个程序是下标从1开始的

 int main()

 {

 int a[20][20]={0},i,j,n;

 i=1;

 printf("请输入一个数");

 scanf("%d",&n);//输入魔方阵的维度n

 j=n/2+1;     // j是维度的一半加1.

 a[i][j]=1;   //确定第一排的中间一个数为1

 for(int k=2;k<=n*n;k++)//已经确定1的位置了,再循环确定2~n*n的位置

 {

 i=i-1;      //挪位,横坐标往上挪一位。

 j=j+1;      //挪位,纵坐标往右挪一位。

 if((i<=0)&&(j<=n))   //如果横坐标挪到顶,同时纵坐标还没有超过最右,横坐标就到从最下再继续。原位置是第一行 除了 右上角的

 i=n;

 if((i<=0)&&(j>n)) //如果横坐标挪到顶,同时纵坐标超过最右,横坐标往下挪两位,纵坐标排往左移一位。原位置是第一行右上角

 {

 i=i+2;

 j=j-1;

 }

 if(j>n)  //如果只有纵坐标超过最右,纵坐标挪到左边第一行。

 {

 j=1;

 }

 if(a[i][j]==0)

 a[i][j]=k;  //如果这个位置还没有赋值,那么赋值为k。

 else        //已经赋值过了。那么竖排往下挪两位,横排往左移一位,再赋值为k。

 {

 i=i+2;

 j=j-1;

 a[i][j]=k;

 }

 }

 for(i=1;i<=n;i++) //循环输出位置。

 {

 for(j=1;j<=n;j++)

 printf("%5d",a[i][j]);

 printf("\n");

 }

 }

*/



魔方阵程序不难,如果说读者一时消化不了,可能难点就在魔方阵的算法难理解,还有就是对临界点几个情况的分析。另外一旦下标初始值发生改变了,可能就单单改了一个从0开始还是从1开始,就又让人迷糊一阵子。这里慢慢琢磨总能琢磨出来的,现在有程序给大家参考,想起来还是比较方便的,可以先把程序拷下来运行一下,然后自己理解了这道题的含义在自己试着去敲。希望大家能牢牢的掌握这个程序。



下面这个程序是要输出一个平行四边形的。这个程序有一个地方我觉得初学者可能会犯错,给大家拿出来说一下。



*****     

 *****    

  *****   

   *****  

    *****

 

输出上面的图形。

         

/*//program 7.3

#include<stdio.h>

int main()

{

    int i,j;

    char a[10][10];

    for(i=0;i<10;i++)    //先把每一个数组中的元素都赋上空格~然后把需要替代的元素用'*'替代就好了

        for (j=0; j<10; j++) {

            a[i][j]=' ';

        }

    

    for (i=0; i<=4; i++) {

        for (j=i; j<=i+4; j++) {

            a[i][j]='*';

            // printf(“%c",a[i][j]);    //不要赋值一个就输出一个,你输出的只是你赋值的这些元素,而那些被初始化为空格的元素是没有输出的,所以就会出现输出一个长方形的现象(这就是读者需要注意的一个地方,在此我已经注释掉了)

        }

        //printf("\n");

    }

    for (i=0; i<10; i++) {

        for (j=0; j<10; j++) {

            printf(“%c",a[i][j]);    //把该赋值的都赋值完了,然后将所有元素输出,自然得到想要的结果了~

        }

        printf("\n");

    }

    return 0;

}

*/



数组方面的学习到此为止了,用了一天多点的时间,我觉得学习重在自己的理解和练习,只要是打够代码,一定能在短时间里有质的提升。下面我们开始函数的学习:



//   注意一下无参函数和有参函数的调用形式

//   abc(); 这是调用无参函数      c=def(a,c,v); 这是调用有参函数(注意把结果要赋给一个变量),当然函数调用本身并不一定非要有分号或者是把结果赋给一个变量,如:printf(“%d",max(a,b));



一个小程序(program 7.4)让大家感受一下函数。

对了,也不知道提醒没提醒过大家,max函数是自己人为写的,可没有什么头文件中含有这个函数的,不要直接就用,虽然这个函数作用很简单



/*//program 7.4

 #include "stdio.h"

 int main()

 {

 int max(int ab,int cd);    //ab、cd都是形参

 int a,b,k;     //这里是定义变量

 scanf("%d%d",&a,&b);

 k=max(a,b);    //a、b是实参,调用函数调用的是实参

 printf("%d",k);

 return 0;

 }

 int max(int x,int y){

 int c;

 c=(x>y)?x:y;

 return c;

 }

 */



下面我们来学习一下函数的嵌套,看程序 program 7.5



/*//program 7.5

//输入四个数,找出最大值,用函数的嵌套实现。

#include "stdio.h"

int max1(int a,int b,int c,int d);

int max2(int a,int b);

int temp;

int main()

{

    int a,b,c,d;

    scanf("%d%d%d%d",&a,&b,&c,&d);

    a=max1(a,b,c,d);    //可以把最后的结果赋给a,都是形参

    printf("max is %d\n",a);

    return 0;

}

int max1(int f,int b,int c,int d)    //这里的f,b,c,d都是形参

{

    int m;

    m=max2(f,b);    //应用了函数的嵌套,从上到下进行读取执行

    m=max2(m,c);

    m=max2(m,d);

    return m;

}

int max2(int a,int b)

{

    if (a<b) {

        temp=a;

        a=b;

        b=temp;

    }

    return a;

}

*/



当然上面的方法感觉还是太过繁琐,我们还可以再优化一下:



/*//program 7.6

//对上题的改进。

#include <stdio.h>

int main()

{

    int max3(int,int);

    int a,b,c,d;

    scanf("%d%d%d%d",&a,&b,&c,&d);

    printf(“%d",max3(max3(max3(a,b),c),d));    //多重嵌套,这样只需要写一个函数max3就可以了~简单明了

    return 0;

}

int max3(int a,int b)

{

    int temp;    //temp必须在这里声明,而不能在主函数中声明,两边不扯

    if (a<b) {

        temp=a;

        a=b;

        b=temp;

    }

    return a;

}

 */



在看这样一个题目,关于函数的 递归调用。



//有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大?(program 7.7)



/*//program 7.7

#include <stdio.h>

int main()

{

    int a,n;

    scanf("%d",&n);

    int age(int n);

    a=age(n);

    printf("age=%d",a);

    return 0;

}

int age(int n)

{

    int c;   //注意,这里函数名和变量名不能重名

    if (n==1) {

        c=10;

    }

    else

    {

        c=age(n-1)+2;

    }

    return c;

}

*/

   

程序比较简单,读者耐心看一下就能看懂。



那么再做一个题目来加深一下今天学习过的递归问题。

 

//用递归方法求n!



/*//program 7.8

#include <stdio.h>

int main()

{

    int n,a;

    scanf("%d",&n);

    int mul(int n);

    a=mul(n);

    printf("n!=%d",a);

    return 0;

}

int mul(int n)

{

    int m;

    if (n==1||n==0) {

        m=1;//不管n多大,n都肯定要慢慢减少最终等于1的,而最后n=1时,m是1,这个m是mul(1),而不是取代了之前算出来的m的值,递归的意义就在此。也可以这么想,最后的m=1是最内层的m,最内层的m求出来了,然后逐渐扩大到最外层的也就是最终的结果了

    }

    else

    {

        m=n*mul(n-1);

    }

    return m;

}

 */



最后一个程序结束今天的学习,这个题目比较的抽象,也是递归题目里面必做的一道题,那就是Hanoi塔问题,让我们一起来尝试一下吧。



/*//program 7.9

//Hanoi塔问题

#include <stdio.h>

int main()

{

    int n;

    scanf("%d",&n);

    void Hanoi(int n,char a,char b,char c);   //把m个盘子从 圆柱a 上通过 圆柱b 移至 圆柱c

    Hanoi(n,'A','B','C');

    return 0;

}

void Hanoi(int n,char a,char b,char c)

{

    void move1(char a,char b);    //Hanoi函数中需要用到Move1函数,所以Move1函数要在Hanoi函数中声明一下

    

    if(n==1)

    {

        move1(a,c);

    }

    else

    {

        Hanoi(n-1, a, c, b);    //想到这里的时候,一定得想到递归的逻辑是什么,做递归的题目,不要带入数进行验证,只要把递归到最底层的值写出来之后,剩下的就是n到n-1之间的递归,我认为此时可以在脑海里念着怎么移动,用通俗的语句来表示这复杂的代码

        move1(a, c);

        Hanoi(n-1, b, a, c);    //这句话就可以这样理解“将n-1个盘子从b通过a移动到c上”

    }

}

void move1(char a,char b)    //这里就不用解释了吧,将这个程序分解开来其实简单不过了

{

    printf("将一个盘子由%c移至%c\n",a,b);

}

*/



好了,第七天的学习结束了,不知道大家掌握的怎么样,希望今天的学习大家也能够牢牢的记在心里,一定要多做题,一道题再简单敲一遍是不够的,多多敲几遍,你会有不同的收获!

版权声明:本文为博主原创文章,未经博主允许不得转载。

12天学好C语言——记录我的C语言学习之路(Day 7)的更多相关文章

  1. 12天学好C语言——记录我的C语言学习之路(Day 12)

    12天学好C语言--记录我的C语言学习之路 Day 12: 进入最后一天的学习,用这样一个程序来综合考量指针和字符串的关系,写完这个程序,你对字符串和指针的理解应该就不错了. //输入一个字符串,内有 ...

  2. 12天学好C语言——记录我的C语言学习之路(Day 11)

    12天学好C语言--记录我的C语言学习之路 Day 11: 因为指针部分比较的难,所以我们花费的时间也是最长的,希望大家耐的住性子,多多理解,多多打代码.好了,废话不多说,来看第11天的学习. //编 ...

  3. 12天学好C语言——记录我的C语言学习之路(Day 10)

    12天学好C语言--记录我的C语言学习之路 Day 10: 接着昨天的指针部分学习,有这么一个题目: //还是四个学生,四门成绩,只要有学生一门功课没及格就输出这个学生的所有成绩 /*//progra ...

  4. 12天学好C语言——记录我的C语言学习之路(Day 9)

    12天学好C语言--记录我的C语言学习之路 Day 9: 函数部分告一段落,但是我们并不是把函数完全放下,因为函数无处不在,我们今后的程序仍然会大量运用到函数 //转入指针部分的学习,了解指针是什么 ...

  5. 12天学好C语言——记录我的C语言学习之路(Day 8)

    12天学好C语言--记录我的C语言学习之路 Day 8: 从今天开始,我们获得了C语言中很有力的一个工具,那就是函数.函数的魅力不仅于此,一个程序到最后都是由众多函数组成的,我们一定要用好函数,用熟练 ...

  6. 12天学好C语言——记录我的C语言学习之路(Day 6)

    12天学好C语言--记录我的C语言学习之路 Day 6: 今天,我们要开始学习数组了. //①数组部分,数组的大小不能够动态定义.如下: //int n;   scanf("%d,& ...

  7. 12天学好C语言——记录我的C语言学习之路(Day 5)

    12天学好C语言--记录我的C语言学习之路 Day 5: 第五天的学习开始了,今天我们主要对几个程序进行编写,让自己充分的熟练编程语言,大量的题目会让自己变的精炼.以一个程序(program 5.1) ...

  8. 12天学好C语言——记录我的C语言学习之路(Day 4)

    12天学好C语言--记录我的C语言学习之路 Day 4: 首先来看一段程序: //输出下面4*5的矩阵 /* 1  2  3   4   5 2  4  6   8   10 3  6  9   12 ...

  9. 12天学好C语言——记录我的C语言学习之路(Day 3)

    12天学好C语言--记录我的C语言学习之路 Day 3: 不知不觉到了第三天的学习,我们前两天学习的东西很杂乱,各个方面都有学习.我觉得这不是不系统,也不是学的不扎实,这种学习对于初学者而言我认为是很 ...

随机推荐

  1. 一步一步学数据结构之n--n(图遍历--深度优先遍历--非递归实现)

    前面已经说了图的深度优先遍历算法,是用递归实现的,而在这里就讲一下用非递归实现,需要借助栈: 算法思想:        1. 栈初始化        2. 输出起始顶点,起始顶点改为“已访问”标志,将 ...

  2. java入门学习(十一)逻辑运算符和位运算符

    请关注我的博客:www.taomaipin.com 家里有急事 暂停了几天,抱歉,现在呢开始说说java的运算语句和运算符 如果想利用java的运算语句 那么就离不开java的运算符,前面第九章讲了j ...

  3. Partition Array

    Given an array nums of integers and an int k, partition the array (i.e move the elements in "nu ...

  4. CSS区块、浮动、定位、溢出、滚动条

    CSS中区块的使用 CSS中浮动的使用 CSS中定位的使用 CSS中溢出的使用 CSS中滚动条的使用 17.1 CSS中区块的使用 属性名称            属性值                ...

  5. HTML5要点(二)

    <p> <b>今天周一</b>,<span>呵呵呵呵呵...</span> </p> <i>斜体文字</i&g ...

  6. <meta 标签的详细使用

    meta是用来在HTML文档中模拟HTTP协议的响应头报文.meta 标签用于网页的<head>与</head>中,meta   标签的用处很多.meta  的属性有两种:na ...

  7. [MODx] 9. Real Example

    Snippet code: <?php $path = MODX_CORE_PATH . 'components/storefinder/'; $result = $modx->addPa ...

  8. Google maps API开发(一)(转)

    一.加载Google maps API <script type="text/javascript" src="http://ditu.google.com/map ...

  9. EasyARM i.mx28学习笔记——开箱试用总结

    0 前言     本月初(2014年8月)购买了周立功的EasyARM开发板,主控为EasyARM i.mx287.出于下面几个理由购买了该开发板.     [1]主要原因,有人约我一起学习一起使用该 ...

  10. PAT 1008

    1008. Elevator (20) The highest building in our city has only one elevator. A request list is made u ...