小学生都看得懂的C语言入门(3): 数组与函数

#include <stdio.h>
int main()
{
int x;
double sum=0;
int cnt=0;
scanf("%d",&x){
    sum+=x;
    cnt++;
    scanf("%d",&x);
}
printf("the mean is %d",sum/cnt);

这是之前求平均数的代码, 

上述没有记录每一个输入的数, 一旦输入就加上去, 没有记录
//现在问题变了, 需要你求平均数 并且输出大于平均数的值 , 那么有必要记录每一个
输入的数字, 如何实现?

现在需要用到数组进行记录. 在上述代码基础上增加 number[10] 定义,在while 循环中增加number[cnt]=x记录输入的值

#include <stdio.h>
int main()
{
int x;
double sum=0;
int number[10];  //长度是10的数组, 可以放10个int 
int cnt=0;
scanf("%d",&x);
while(x!=-1){
    number[cnt]=x; //记录 赋值 
    sum+=x;
    cnt++;
    scanf("%d",&x);
}
if (cnt>0){
    printf("the mean is %f\n",sum/cnt);
    
    int i; //遍历每一个数 找到大于平均数的值 
    for(i=0;i<cnt;i++){
        if(number[i]>sum/cnt){
        printf("%d\n",number[i]); 
    } 
} 
}
return 0;
}

 

为了清楚的知道number[cnt]=x 的存储机制,增加一段调试代码

#include <stdio.h>
int main()
{
int x;
double sum=0;
int number[10];  //长度是10的数组, 可以放10个int 
int cnt=0;
scanf("%d",&x);
while(x!=-1){
    number[cnt]=x; //记录 赋值 
    // --用于调试 
    {
        int i;
        printf("%d\t",cnt);
        for(i=0;i<=cnt;i++){ 
            printf("%d\t",number[i]);
        }
    }printf("\n"); 
    //--用于调试 
    sum+=x;
    cnt++;
    scanf("%d",&x);
}
if (cnt>0){
    printf("the mean is %f\n",sum/cnt);
    
    int i; //遍历每一个数 找到大于平均数的值 
    for(i=0;i<cnt;i++){
        if(number[i]>sum/cnt){
        printf("%d\n",number[i]); 
    } 
    
} 
}return 0; 
}

 

这是每次的number 数组的存储情况,再输入-1终止计算,得到

但是上述存在很明显的问题: 定义了number [10] ,如果实际输入了超过10 怎么办?

别急啊, 首先掌握下数组的定义

int grades[100];

double weight[20];

数组的特点: 1.数组中的每个元素具有相同的数据类型, 2. 一旦创建数组, 之后不能改变大小,

int a[10] 的顺序是 a[0], a[1],... a[9] ,[] 中的数字是索引, 索引从0开始计数!!

编译器不会检查数组下标是否越界, 越界就出现segmentation fault ,

int a[0] 可以存在, 但是没有任何用处..

 

实例: 输入数量不定的在[0,9]之间的整数, 统计每一种数字出现的次数, 输入-1表示结束

程序如下, 用一个10元数组来作为计数器,

#include <stdio.h>
int main(void)
{
    const int num=10; //num决定数组大小 
    int x;
    int i;
    int cnt[num];
    for (i=0;i<num;i++){
        cnt[i]=0;
    } //初始化数组的每一个元素, 
    
    scanf("%d",&x);
    while(x!=-1){
        if (x>=0 && x<=9){
            cnt[x] ++;
        }
        scanf("%d",&x);
    } 
    for (i=0;i<num;i++){
        printf("%d出现了%d次\n",i,cnt[i]);
    }
    return 0;
}

结果

 

(二) 定义函数

实例: 求从m -n 之间所有素数的和sum

#include <stdio.h>
int main()
{
    int m,n;
    int sum=0;
    int cnt=0;
    int i;
    // 求素数的和 
    scanf("%d %d",&m,&n); //m=10 n=31
    if (m==1)m=2;
    for (i=m;i<=n;i++){
        int isprime=1;
        int k;
        for (k=2;k<i-1;k++){
        if (i%k==0){
            isprime=0;
            break;
        }
        }
        if(isprime){
            sum+=i;
            cnt++;
        }
    }
    printf("有%d个素数, 和为%d\n",cnt,sum);
    return 0;
}

 

我们可以将上述素数判别的单独拿出来 形成一个函数.

#include <stdio.h>
// 定义一个函数 isprime
int isprime(int i)
{
    int ret=1; 
    int k;
    for (k=2;k<i-1;k++){
        if (i%k==0){
            ret=0;
            break;
        }
        }
    return ret;
}
//    
int main()
{
    int m,n;
    int sum=0;
    int cnt=0;
    int i;
    // 求素数的和 
    scanf("%d %d",&m,&n); //m=10 n=31
    if (m==1)m=2;
    for (i=m;i<=n;i++){
        if(isprime(i)){ 
            sum+=i;
            cnt++;
        }
    }
    printf("有%d个素数, 和为%d\n",cnt,sum);
    return 0;
}

实例 : 求 1-10 , 20-30  35-45 三者的和

 '代码复制是程序不良的表现'!!!! keep it  in mind~~, 不利用与将来程序的维护.

#include <stdio.h>

void sum(int begin ,int end)
{
    int i;
    int sum=0;
    for (i=begin;i<=end;i++){
        sum+=i;
    }
    printf("%d到%d 的和是%d \n",begin,end,sum);
 } 
    
int main()
{
sum(1,10);
sum(20,30);
sum(35,45);
    return 0;
}

综合上述两个例子, 我们来看什么是函数, 如何定义?

void sum(int begin ,int end) 称为函数头, sum是函数名, void 表示函数没有返回的东西, ()内是参数, 参数用逗号, 分开

 以下部分称为函数体

{
 int i;
 int sum=0;
 for (i=begin;i<=end;i++){
  sum+=i;
 }
 printf("%d到%d 的和是%d \n",begin,end,sum);
 }

函数头中的圆括号很重要, 调用函数也要加(), 否则出错

#include <stdio.h>
void fun()
{
    printf("nihao");
 } 
 int main()
 { 
    fun();   // 要加() !!!
    return 0;
}

 

而判断别素数的函数 是有返回值的

int isprime(int i)

函数体中有return ret

定义一个最大值函数

int max(int a, int b)
{
    int ret ;
    if(a>b){
        ret=a;
    }
  else{
      ret=b;
 }
 return ret; 
 }
#include <stdio.h>
int max(int a, int b)
{
    int ret ;
    if(a>b){
        ret=a;
    }
  else{
      ret=b;
 }
 return ret; 
 }

int main()
{
 int x;
 x=max(10,20);// 将函数值赋给x
 printf("%d\n",x);
}

上述函数头也可以写成 

 

#include <stdio.h>
int max(int a, int b)
{
    int ret ; if(a>b){
    return a;
    }
  else{
    return b;
}
//return ret; 

 

但是这样不好, 使得函数有多个出口(多个return), 可行但是不建议用这种!!

函数可以嵌套用 比如max(10, max(100,11));

 

没有返回值的函数 则定义为

void 函数名(参数表)

那么之后不能用 return 某个值;

如果函数有返回值, 则必须使用带值的return.

注意: 在书写时, 先定义函数再之后进行调用, 不要把函数的定义放在main  后面, 但是也可以通过函数声明实现

#include <stdio.h>

int max(int a, int b); // 函数声明!! , 加分号!! 也可以不加 参数, int max(int , int )
int main()
{
 int x;
 x=max(10,20);// 将函数值赋给x
 printf("%d\n",x);
}

int max(int a, int b)
{
    int ret ;
    if(a>b){
        ret=a;
    }
  else{
      ret=b;
 }
 return ret; 
 }

其他问题: 

C语言不允许函数的嵌套定义

int main () 实际上也是一个函数,

 

---- 二维数组

int a[3][5]  表示3*5矩阵 

a[0][0], a[0][1],... a[0][4]

..

a[2][0], a[2][1], ...a[2][4]

 

int a[][3]={
{0,1,2},{3,4,5}, 
};  // 定义数组列数一定要给出, 行数可以不给, 计算机会自己数

 实例:   // tic-tac -toe game, 3*3 矩阵中,写1 或者0 ,当有一行 一列或者对角线

可以连成线, 则一方胜出, 游戏结束, 如何判别游戏结束?
 遍历每行 每列, 每个对角线 进行判别

#include <stdio.h>
int main()
{
 const int size=3;
 int board[size][size];
 int i,j;
 int n1;
 int n0;
 int result=-1; // -1没有人胜出,1 表示写1方胜出, 0表写0方胜出 
 //下面读入矩阵 
 for (i=0;i<size;i++){
     for(j=0;j<size;j++){
         scanf("%d",&board[i][j]); 
     }
 } 
 
 // 检查行 
 for (i=0;i<size&&result==-1;i++){
     n0=n1=0;
     for(j=0;j<size;j++){
         if(board[i][j]==1){
             n1++;
         }else{
             n0++; 
         }
     }
     if (n0==size){
         result=0;
     }else if(n1==size){
         result=1;
     }
 } 
 
  //再检查列 
 if (result==-1){ 
 for (j=0;j<size&&result==-1;j++){
     n0=n1=0;
     for(i=0;i<size;i++){
         if(board[i][j]==1){
             n1++;
         }else{
             n0++; 
         }
     }
     if (n0==size){
         result=0;
     }else if(n1==size){
         result=1;
     }
 } 
 } 

// 再检查正对角线 
 if (result==-1){ 
     n0=n1=0;
     for(i=0;i<size;i++){
         if(board[i][i]==1){
             n1++;
         }else{
             n0++; 
         }
     }
     if (n0==size){
         result=0;
     }else if(n1==size){
         result=1;
     } 
 } 
 
 // 最后检查次对角线 
 if (result==-1){ 
     n0=n1=0;
     for(i=0;i<size;i++){
         if(board[i][size-1-i]==1){
             n1++;
         }else{
             n0++; 
         }
     }
     if (n0==size){
         result=0;
     }else if(n1==size){
         result=1;
     } 
 } 
 
// 下结论
if (result==1){
    printf("1 win"); 
} else if(result==0){
    printf("0 win");
}else{
    printf("nobody win, have an another try"); 
}

return 0;
}

接下来, 学习数组的搜索等其他

 数据的集成初始化

#include <stdio.h>
int main(void)
{
    int a[]={1,2,3,4};// 数组的集成初始化 
    for (int i=0;i<4;i++){
        printf("%d\t",a[i]); 
    }
    
}

换一种形式

#include <stdio.h>
int main(void)
{
    int a[4]={1};// 数组的集成初始化 
    for (int i=0;i<4;i++){
        printf("%d\t",a[i]); 
    }    
}

 得到第一个是1 ,后面自动补0

由此若要初始化一个长度n 的数组a 为0, 只需要int a[n]={0}; 

对于稀疏数组, 大部分是0 ,只有少数几个值非零, 则可以

#include <stdio.h>
int main(void)
{
    int a[4]={[1]=1,[3]=4};// 没给定义的位置自动填充0 ,但是只有C99 才可以这样做 
    for (int i=0;i<4;i++){
        printf("%d\t",a[i]); 
    }    
}

如何让编译器自动数数组长度?, 用sizeof

#include <stdio.h>
int main(void)
{
 int a[]={1,2,3,4};
  printf("%d\t",sizeof(a)); //16
  printf("%d\t",sizeof(a[0])); //4
  printf("数组长度是%d\t",sizeof(a)/sizeof(a[0])); 
}

得到数组长度是sizeof(a)/sizeof(a[0])

 

注意数组的赋值

 

#include <stdio.h>
int main(void)
{
    int a[]={1,2,3,4};
    int b[]=a; // 错误! 不能这么赋值    
}

 

数组赋值必须采用遍历

 for(int i=0;i<length;i++) {
 b[i]=a[i]; 
 }

实例:

#include <stdio.h>
//搜索一个数是否在数组中存在
int search(int key, int a[],int length);
int main(void)
{
    int a[]={1,2,3,4,10,21,32,18,19};
    int x;
    int loc;
    printf("please input a number\n");
    scanf("%d",&x);
    int length=sizeof(a)/sizeof(a[0]);
    loc=search(x,a,length); // 调用search函数 
    if(loc!=-1){
        printf("%d在%d位置上\n",x,loc);
    }else{
        printf("%d doesn't exist\n",x); 
    }
    return 0;
}


int search(int key, int a[],int length)
{
    int ret=-1; // 记录key 在数组x 中的位置, 0 表示位置1 
    int i;
    for(i=0;i<length;i++){
        if (a[i]==key){
            ret=i;
            break;
        }
    } 
    return ret; 
}

// 注意,数组作为函数参数时, 必须再用另一个参数传入该数组的大小,
//因为不能在[] 中给出数组的大小, 不能再利用sizeof 来计算数组的元素个数 

 

posted @ 2018-07-03 12:14  xy小崽子  阅读(850)  评论(0编辑  收藏  举报