网易云课堂程序设计入门—C语言第六周 数组学习笔记

第六周 数组


标签(空格分隔):程序设计入门—C语言

6.1数组

  1. 写一个程序,计算用户输入的平均数,并输出所有大于平均数的数
  2. 定义数组
    • <类型>变量名称[元素数量];
      int greads[100];
      double weight[20];
    • 元素数量必须为整数
    • C99之前,元素数量必须是编译时刻确定的字面量
  3. 数组
    • 数组是一种容器(放东西的东西),特点是:
      其中所有的元素具有相同的数据类型
      一旦创建,不能改变大小
      *(数组中的元素在内存中是连续依次排列的)
  4. int a [10];
    • 一个int数组
    • 10个单元:a[0],a[1],a[2]……a[9]
    • 每个单元就是一个int类型的变量
    • 可以出现在赋值的左边和右边,a[1]=a[2]+6; *在赋值的左边叫做左值
  5. 数组的单元
    • 数组的每个单元数就是数组类型的一个变量
    • 使用数组时放在[ ]中的数字叫做下标或索引,下标从0开始计数
  6. 有效的下标范围
    • 编译器和运行环境都不会检查数组下标是否越界,无论对数组单元做读还是写
    • 一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃
      segmentation fault 可能是下标越界
    • 但也可能运气好,没造成严重后果
    • 所以这是程序员的责任来保证程序只使用有效的下标值 [0, 数组的大小-1]
  7. 数组例子:统计个数
#include<stdio.h>
//输入[1,9]输入-1结束,统计输入各个数字的个数 
main(void){
    const int number =10;  //数组的大小 C99 
    int x;  
    int count[number];  //定义数组 
    int i;

    for(i=0;i<number;i++){  //初始化数组 
        count[i]=0;         // 
    }                       //
    scanf("%d",&x);
    while(x!=-1){
        if(x>=0 && x<10){
            count[x]+=1;   //数组参与运算 
        } 
        scanf("%d",&x);
    }
    for(i=0;i<number;i++){                      //遍历数组输出 
        printf("%d输入了%d次\n",i,count[i]);     // 
    }                                           //
    return 0;
} 

6.2数组运算

  • 搜索
#include<stdio.h>
/*
找出key在数组中的位置,
@param key 要寻找的数字 
@param a[] 要寻找的数组 
@param length 数组a的长度
@return如果找到返回其在a中的位置,如果找不到则返回-1 
*/ 
int search(int key,int a[],int length);

int main (void){
    int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32};
    int x;
    int loc;
    printf("请输入一个数字:");
    scanf("%d",&x);
    loc=search(x,a,sizeof(a)/sizeof(a[0]));
    if (loc!=-1){
        printf("%d在第%d个位置上\n",x,loc);
    }else{
        printf("%d不存在",x);
    }

    return 0;
} 

int search(int key,int a[],int length){
    int ret =-1;
    int i;
    for(i=0;i<length;i++){
        if(a[i]==key){
            ret =i;
            break;
        }
    }
    return ret;
}
  1. 数组的集成初始化
    int a[ ]={2,4,6,7,1,3,5,9,11,13,15,};
    int a[4]={1} –>{1,0,0,0,}给一个单元值,后面的没给值
    int a[5]={0} –>{0,0,0,0,0,}代替遍历初始化
  2. 集成初始化时的定位 (C99)
    int a[10] = {[0]=2,[2]=2,6,7} –>{2,2,6,7,0,0,0,0,0,0}
  3. 数组的大小
    • sizeof给出整个数组所占据的内容的大小,单位是字节
      sizeof(a)/sizeof(a[0])
    • sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组单元的个数
    • 这样的代码,一旦修改数组中初始的数据,不需要修改遍历的代码
  4. 数组的赋值
    int a[] = {1,3,5,7,}
    int b[] = a; (错)
    • 数组变量本身不能被赋值
    • 要把一个数组的所有元素交给另一个数组,必须采用遍历
  5. 遍历数组

    • 通常都是使用for循环,让循环变量i从0到<数组的长度,这样循环体内最大的i正好是数组最大的有效下标
    • 程序员写for一般从0到小于某个数,而不是从1到小于等于某个数
    • 常见错误
      *循环的条件是<=数组的长度或;
      *离开循环后,继续用i的值做数组元素的下标,因为离开时,i正好等于length是无效下标
    • 数组作为函数参数时,往往必须再用另一个参数来传入数组的大小
    • 不能在[ ]中给出数组的大小,不能再利用sizeof来计算数组的元素个数

    • /n 回车

    • /t 下一个制表符
  6. 素数
#include<stdio.h>
#include<math.h>
//int isPrime (int x){
//  int ret =1;
//  int i;
//  if (x==1||(x%2==0&&x!=2)){ //如果x是偶数,就不是素数 
//      ret =0;
//  }
//  for (i=2;i<sqrt(x);i++){  //值需要循环sqrt(x)遍 
//      if(x%i==0){
//          ret =0;
//          break;
//      }   
//  }
//  return ret;
//}

//判断是否能被已知的且<X的素数整除 
int isPrime (int x,int knowPrimes[],int numberOfKnowPrime) {
    int ret =1;
    int i;
    for (i=0;i<numberOfKnowPrime;i++){
        if(x % knowPrimes[i]==0){
            ret =0;
            break;
        }   
    }
    return ret;
}

int main (void){
    const int number =7;//100;
    int prime[number]={2};  // 
    int count =1;
    int i =3;
        {//调试输出  输出表头 
            int i;
            printf("\t\t");
            for( i=0;i<number;i++) {
                printf("%d\t",i);
            }
            printf("\n");
        }
    while (count<=number){
        if (isPrime(i,prime,count)){
            prime[count++]=i;  //常见套路 
        }
        {//调试输出
         //加大括号是为了在里面定义自己的变量,而不会影响到外面的变量 
            printf ("i=%d \tcnt=%d\t",i,count) ;
            {  
                int i;
                for( i=0;i<number;i++){
                    printf("%d\t",prime[i]);
                } 
                printf("\n");
            } 
        } 
        i++; 
    }
    for (i=0;i<number;i++){
        printf("%d",prime[i]);
        if ( (i+1)%5 ) printf ("\t");
        else printf("\n");
    }
    return 0;
}
/*
构造素数表  算法不一定和人的思考方式相同 
欲构造N以内(不含)的素数表
1x2
22X 3X 4X直至aX<n的数标记为非素数
3x为下一个没有被标记为非素数的数,重复2;直到所有的数都尝试完毕 
-->
1 开辟prime[n],初始化其所有元素为1,prime[x]为1表示是素数 
2x=2
3 如果x是素数,则对于(i=2;x*i<n;i++)令prime[i*x]=0
4x++,如果x<n,重复3,否则结束 
*/

#include<stdio.h>
int main (void){
    const int maxNumber =25;
    int isPrime[maxNumber];
    int i,x;
    for(i=0;i<maxNumber;i++){  //初始化 
        isPrime[i]=1;
    } 
    for(x=2;x<maxNumber;x++){
        if ( isPrime[x] ){
            for(i=2;x*i<maxNumber;i++){
                isPrime[i*x]=0; 
            }
        }
    }
    for(i=2;i<maxNumber;i++){
        if( isPrime[i] ){
            printf("%d\t",i);   
        }
    }
    printf("\n"); 
    return 0;
}
  • 二维数组
    int a[3][5]; 通常理解为a是一个三行五列的矩阵
  • 二维数组的遍历
for(i=0; i<3; i++){
    for(j=0; j<5; j++){
        a[i][j]=i*j;  //a[i][j]是一个int,表示第i行第j列上的单元
    }
}
  • 二维数组的初始化
    • 列数是必须给出的,行数可以用编译器来数
    • 每行一个{},逗号分离
    • 最后的逗号可以存在,有古老的传统
    • 如果省略,表示补零
    • 也可以用定位(*C99 Only)
int a[][5]={
    {0,1,2,3,4},
    {2,3,4,5,6},
};
  • tic-tac-toe
#include<stdio.h>
int main(void){
    const int size =3;
    int board[size][size];
    int i,j;
    int numOfO;
    int numOfX;
    int result =-1;//-1没人赢; 0:O赢; 1:X赢 
    //读入矩阵
    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++){
        numOfO=numOfX=0;
        for(j=0;j<size;j++){
            if(board[i][j]==1){
                numOfX++;
            }else{
                numOfO++;
            }   
        }       
        if(numOfO==size){
            result = 0;
        }else if(numOfX==3){
            result = 1;
        }
    } 
    //检查列
    if(result==-1){
        for(j=0;j<size && result ==-1;j++){
            numOfO=numOfX=0;
            for(i=0;i<size;i++){
                if(board[i][j]==1){
                    numOfX++;
                }else{
                    numOfO++;
                }
            }
            if(numOfO==size){
                result = 0;
            }else if(numOfX==3){
                result = 1;
            }   
        }
    }   
    //检查对角线
    if(result==-1){
        numOfO=numOfX=0;
        for(i=0;i<size;i++){
            if(board[i][i]==1){
                numOfX++;
            }else{
                numOfO++;
            }   
        }   
        numOfO=numOfX=0;
        for(i=0;i<size;i++){
            if(board[i][size-i-1]==1){
                numOfX++;
            }else{
                numOfO++;
            }   
        }           
        if(numOfO==size){
            result = 0;
        }else if(numOfX==3){
            result = 1;
        }
    }
    //结果 
    if(result==1){
        printf("X赢了!\n");
    } else if(result ==0){
        printf("0赢了!\n");
    } else{
        printf("平局\n");
    }

    printf(" ————————————\n");
    for(i=0;i<size;i++){
        for(j=0;j<size;j++){
            printf("|   %d   ",board[i][j]);
        }
        printf("|\n  ———————————\n");
    }
    return 0;
} 
  • 以下程序片段的输出结果是:(A)
int m[][3] = {1,4,7,2,5,8,3,6,9,};
int i,j,k=2;
for ( i=0; i<3; i++ ) {
    printf("%d", m[k][i]);
}

A.369
B.不能通过编译
C.789
D.能编译,但是运行时数组下标越界了


第六周编程题

1 多项式加法(5分)
  • 题目内容:一个多项式可以表达为x的各次幂与系数乘积的和,比如:
    现在,你的程序要读入两个多项式,然后输出这两个多项式的和,也就是把对应的幂上的系数相加然后输出。程序要处理的幂最大为100。
  • 输入格式:
    总共要输入两个多项式,每个多项式的输入格式如下:
    每行输入两个数字,第一个表示幂次,第二个表示该幂次的系数,所有的系数都是整数。第一行一定是最高幂,最后一行一定是0次幂。
    注意第一行和最后一行之间不一定按照幂次降低顺序排列;如果某个幂次的系数为0,就不出现在输入数据中了;0次幂的系数为0时还是会出现在输入数据中。

  • 输出格式:从最高幂开始依次降到0幂,如:2x6+3x5+12x3-6x+20
    注意其中的x是小写字母x,而且所有的符号之间都没有空格,如果某个幂的系数为0则不需要有那项。

  • 输入样例:
    6 2
    5 3
    3 12
    1 6
    0 20
    6 2
    5 3
    2 12
    1 6
    0 20

  • 输出样例:
    4x6+6x5+12x3+12x2+12x+40

#include<stdio.h>
int main(void){     
    const int a =101;
    int num[a]={0}; //初始化数组 
//  int num[a]; 
//  for(i=0;i<a;i++){
//      num[i]=0;
//  }

    int m=0; //计数 
    int mi,xi;
    while(m!=2){
        do{
            scanf("%d %d", &mi, &xi);
            num[mi]+=xi;            
        }while(mi!=0);
        m++;
    }

    int zui;//最高次幂 
    int i;
    for(i=100;i>1;i--){
        if(num[i]!=0){
            zui=i;
            printf("%dx%d",num[i],i); 
            break;
        } 
    }

    for(i=zui-1;i>1;i--){
        if(num[i]!=0){
            printf("+%dx%d",num[i],i); 
        }   
    }

    if(num[1]!=0){
        printf("+%dx",num[1]); 
    }
    if(num[0]!=0){
        printf("+%d",num[0]); 
    }
    return 0;
}
2 鞍点(5分)
  • 题目内容:给定一个n*n矩阵A。矩阵A的鞍点是一个位置(i,j),在该位置上的元素是第i行上的最大数,第j列上的最小数。一个矩阵A也可能没有鞍点。你的任务是找出A的鞍点。

  • 输入格式:输入的第1行是一个正整数n,(1<=n<=100),然后有n行,每一行有n个整数,同一行上两个整数之间有一个或多个空格。

  • 输出格式:对输入的矩阵,如果找到鞍点,就输出其下标。下标为两个数字,第一个数字是行号,第二个数字是列号,均从0开始计数。
    如果找不到,就输出
    NO
    题目所给的数据保证了不会出现多个鞍点。

  • 输入样例:
    4
    1 7 4 1
    4 8 3 6
    1 6 1 2
    0 7 8 9

  • 输出样例:
    2 1

#include<stdio.h>
int main (void){
    int x;
    scanf("%d",&x);
    if(x>0 && x<=100){
        int n[x][x];
        int i,j;
        for (i=0;i<x;i++){
            for (j=0;j<x;j++){
                scanf("%d",&n[i][j]);
            }
        }
        int find =0;
        int zhao =1;
        for (i=0;i<x;i++){
            for (j=0;j<x;j++){
                zhao=1;
                for(int a=0;a<x;a++){
                    if(n[i][j]<n[i][a]){
                        zhao=0;
                        break;
                    }
                    if(n[i][j]>n[a][j]){
                        zhao=0;
                        break;
                    }   
                }
                if(zhao==1){
                    printf("%d %d\n",i,j);
                    find =1;    
                }
            }
        }       
        if(find==0){
            printf("NO");
        }       
    }   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值