C语言学习-翁凯(第八章笔记)

第八章

8.1.1 初试数组

  • 之前讨论过

    • 如何写一个程序计算用户输入的数字的平均数?
int x;
double sum=0;
int cnt=0;
scanf("%d",&x);
while(x!=-1){sum+=x;cnt++;scanf("%d",&x);
}
if(cnt>0){printf("%f\n",sum/cnt);
}
  • 不需要记录输入的每一个数

  • 如何写一个程序,计算用户输入的数字的平均数,并输出所有大于平均数的数?

如何记录很多数?

  • int num1,num2,num3…?

数组

  • int number[100];
  • scanf("%d",&number[i]);
int x;double sum=0;int cnt=0;int number[100]; scanf("%d",&x);while(x!=-1){number[cnt]=x;/*int i;for(i=0;i<=cnt;i++){printf("%d ",number[i]);}printf("\n"); */sum+=x;cnt++;scanf("%d",&x);}if(cnt>0){printf("%f\n",sum/cnt);int i;for(i=0;i<cnt;i++){if(number[i]>sum/cnt){printf("%d\n",number[i]);}}}return 0;

(这个程序存在安全隐患,是什么?)

(数组定义为100,但是未讨论cnt是否大于100)

8.1.2 数组的使用:如何定义和使用数组,数组的下标和下标的范围

定义数组

  • <类型>变量名称[元素数量];

    • int grades[100];
    • double weight[20];
  • 元素数量必须是整数
  • C99之前:元素数量必须是编译时刻确定的字面量

数组

  • 是一种容器(放东西的东西),特点是:

    • 其中所有的元素具有相同的数据类型;
    • 一旦创建,不能改变大小
    • *(数组中的元素在内存中是连续依次排列的)

int a[10]

  • 一个int的数组
  • 10个单元:a[0],a[1],…a[9]

  • 每个单元就是一个int类型的变量
  • 可以出现在赋值的左边或右边:
    • a[2]=a[1]+6;
  • *在赋值左边的叫做左值

数组的单元

  • 数组的每个单元就是数组类型的一个变量
  • 使用数组时放在[]中的数字叫做下标或索引,下标从0开始计数:
    • grades[0]
    • grades[99]
    • average[5]

有效的下标范围

  • 编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元做读还是写
  • 一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃
    • segmentation fault
  • 但是也可能运气好,没造成严重的后果
  • 所以这是程序员的责任来保证程序只使用有效的下标值:[0,数组的大小-1]
int x;double sum=0;int cnt=0;int number[100]; scanf("%d",&x);while(x!=-1){number[cnt]=x;/*int i;for(i=0;i<=cnt;i++){printf("%d ",number[i]);}printf("\n"); */sum+=x;cnt++;scanf("%d",&x);}if(cnt>0){printf("%f\n",sum/cnt);int i;for(i=0;i<cnt;i++){if(number[i]>sum/cnt){printf("%d\n",number[i]);}}}return 0;
  • 这个程序是危险的,因为输入的数据可能超过100个

计算平均数

  • 如果先让用户输入有多少数字要计算,可以用C99的新功能来实现
 int x;double sum=0;int cnt;peintf("请输入数字的数量:");scanf("%d",&cnt);
if(cnt>0){int number[100]; scanf("%d",&x);while(x!=-1){number[cnt]=x;/*int i;for(i=0;i<=cnt;i++){printf("%d ",number[i]);}printf("\n"); */sum+=x;cnt++;scanf("%d",&x);}
}if(cnt>0){printf("%f\n",sum/cnt);int i;for(i=0;i<cnt;i++){if(number[i]>sum/cnt){printf("%d\n",number[i]);}}}return 0;

(C99 ONLY!)

长度为0的数组?

  • int a[0];
  • 可以存在,但是无用

8.1.3 数组例子:统计个数

  • 写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束
const int number=10;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<=9){count[x]++;}scanf("%d",&x);}for(i=0;i<number;i++){printf("%d:%d\n",i,count[i]);}return 0;

8.2.1 数组运算

  • 在一组给定的数据中,如何找出某个数据是否存在?
#include<stdio.h>/*
找出key在数组a中的位置
@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不存在。\n",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+1;//这里我改了下,从1开始数数,老师给的代码是从0开始数数的break;}}return ret;
}

数组的集成初始化

int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32};

  • 直接用大括号给出的数组的所有元素的初始值
  • 不需要给出数组的大小,编译器替你数数

(如果int a[10]={1};则除了第一个是1之外,其他的默认为0,如果为了给数组初始化,就直接int a[10]={0};就可以了)

集成初始化时的定位(C99ONLY!)

int a[10]={[0]=2,[2]=3,6};

  • 用[n]在初始化数据中给出定位
  • 没有定位的数据接在前面的位置后面
  • 其他位置的值补零
  • 也可以不给数组大小,让编译器算
  • 特别适合初始数据稀疏的数组

数组的大小

  • sizeof给出整个数组所占据的内容的大小,单位是字节

sizeof(a)/sizeof(a[0])

  • sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
  • 这样的代码,一旦修改数组中初始的数据,不需要修改遍历的代码

数组的赋值

int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32};

int b[]=a;

  • 数组遍历本身不能被赋值
  • 要把一个数组的所有元素交给另一个数组,必须采用遍历
for(i=0;i<length;i++){b[i]=a[i];
}

遍历数组

  • 通常都是使用for循环,让循环变量i从0到<数组的长度,这样循环体内最大的i正好是数组最大的有效下标
  • 常见的错误是:
    • 循环结束条件是<=数组长度,或:
    • 离开循环后,继续用i的值来做数组元素的下标!

(数组作为函数参数时,往往必须再用另一个参数来传入数组的大小)

  • 数组作为函数参数时:

    • 不能在[]中给出数组的大小
    • 不能再利用sizeof来计算数组的元素个数!

8.2.2 数组例子:素数

判断素数

int isprime(int x);int main(void)
{int x;scanf("%d",&x);if(isPrime(x)){printf("%d是素数。\n",x);}else{printf("%d不是素数。\n",x);}return 0;
}

从2到x-1测试是否可以整除

int isPrime(int x)
{int ret=1;int i;if(x==1)ret=0;for(i=2;i<x;i++){if(x%i==0){ret=0;break;}}return ret;
}
  • 对于n要循环n-1遍

    • 当n很大时就是n遍

去掉偶数后,从3到x-1,每次加2

int isPrime(int x)
{int ret=1;int i;if(x==1||(x%2==0&&x!=2))ret=0;for(i=3;i<x;i+=2){if(x%i==0){ret=0;break;}}return ret;
}
  • 如果x是偶数,立刻
  • 否则要循环(n-3)/2+1遍
    • 当n很大时就是n/2遍

无需到x-1,到sqrt(x)就够了

int isPrime(int x)
{int ret=1;int i;if(x==1||(x%2==0&&x!=2))ret=0;for(i=3;i<sqrt(x);i+=2){if(x%i==0){ret=0;break;}}return ret;
}
  • 只需要循环sqrt(x)遍

(sqrt求平方根)

判断是否能被已知的且<x的素数整除

(适合于构造一张表,将元素输入进去)

构造素数表

  • 要构造n以内的素数表
  1. 令x为2
  2. 将2x、3x、4x直到ax<n的数标记为非素数
  3. 令x为下一个没有被标记为非素数的数,重复2;直到所有的数都已经尝试完毕
  • 要构造n以内(不含)的素数表
  1. 开辟prime[n],初始化其所有元素为1,prime[x]为1表示x是素数
  2. 令x=2
  3. 如果x是素数,则对于(i=2;x*i<n;i++);prime[i*x]=0
  4. 令x++,如果x<n,重复3,否则结束

  • 算法不一定和人的思考方式相同

8.2.3 二维数组

二维数组

  • int a[3][5]
  • 通常理解为a是一个3行5列的矩阵

二维数组的遍历

for(i=0;i<3;i++){for(j=0;j<5;j++){a[i][j]=i*j
;    }
}
  • a[i][j]是一个int
  • 表示第i行第j列上的单元
    • a[i,j]是什么?(,表达式,表达的是a[j])

二维数组的初始化

int a[][5]={{0,1,2,3,4},{2,3,4,5,6},};
  • 列数是必须给出的,行数可以由编译器来数
  • 每行一个{},逗号隔开
  • 最后的逗号可以存着,有古老的传统
  • 如果省略,表示补零
  • 也可以用定位(*C99 ONLY!)

tic-tac-toe游戏

  • 读入一个3x3的矩阵,矩阵中的数字为1表示该位置上有一个X,为0表示为○
  • 程序判断这个矩阵中是否有获胜的一方,输出表示获胜一方的字符X或○,或输出无人获胜

读入矩阵

const int size=3;
int board[size][size];
int i,j;
int num0fx;
int num0fo;
int result=-1;//-1:没人赢,1:x赢,0:o赢//读入矩阵
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++){num0fo=num0fx=0;for(j=0;j<size;j++){if(board[i][j]==1)num0fx++;}else{num0fo++;}
}
if(num0fo==size){result=0;
}else if(num0fx==size){result=1;
}
}

检查列

//检查列
if(result==-1){for(j=0;j<size&&result==-1;j++){num0fo=num0fx=0;for(i=0;i<size;i++){if(board[i][j]==1)num0fx++;}else{num0fo++;}
}
if(num0fo==size){result=0;
}else if(num0fx==size){result=1;
}
}
}

(能否用一个两重循环来检查行和列?)

检查对角线

num0fo=num0fx=0;
for(i=0;i<size;i++){f(board[i][i]==1){num0fx++;}else{num0fo++;}
}
if(num0fo==size){result=0;
}else if(num0fx==size){result=1;
}
num0fo=num0fx=0;
for(i=0;i<size;i++){f(board[i][size-i-1]==1){num0fx++;}else{num0fo++;}
}

C语言学习-翁凯(第八章笔记)相关推荐

  1. C语言学习-翁凯(第九章笔记)

    C语言学习-翁凯(第九章笔记) 第九章 9.1.1 取地址运算:&运算符取得变量的地址 运算符& scanf("%d",&i);里面的& 获得变量的 ...

  2. C语言学习-翁凯(第七章笔记)

    C语言学习-翁凯(第七章笔记) 第七章 7.1.1初见函数 素数求和 int m,n;int i;int cnt=0;int sum=0;scanf("%d %d",&m, ...

  3. C语言学习-翁凯(第六章笔记)

    C语言学习-翁凯-第六章 第六章 6.0.1 给定条件的整数集 int a;scanf("%d",&a);int i,j,k;int cnt=0;//i=indexi=a; ...

  4. c语言翁凯中程序,程序设计入门——C语言(翁凯老师)(基础部分)(总结)...

    Tips1:关于int main(int argc, char* argv[]) argc是命令行总的参数个数 argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数 命令行后面跟的用户 ...

  5. 【三万粉丝终极福利】Python、C、Java三大语言学习路线和资源整理

    大家好,我是辣条. 今天给大家带来三万粉丝三大语言学习路线和资源整理,收藏就对了. 目录 C语言 学习路线 学习书籍 学习视频 资源推荐 Java语言 学习路线 学习书籍 学习视频 资源推荐 Pyth ...

  6. C语言有简单基础的入手指南(MOOC课程 浙大 翁凯老师主讲)听课笔记 the basic knowledge of C

    欢迎各位小白来了解C语言相关知识 下面的是我在MOOC课程中做的笔记 由简单到复杂,建议收藏后慢慢看,这里有很多不常用但很实用的东西 //else if的另一种表述switch-case switch ...

  7. r语言c函数怎么用,R语言学习笔记——C#中如何使用R语言setwd()函数

    在R语言编译器中,设置当前工作文件夹可以用setwd()函数. > setwd("e://桌面//") > setwd("e:\桌面\") > ...

  8. 梓益C语言学习笔记之链表&动态内存&文件

    梓益C语言学习笔记之链表&动态内存&文件 一.定义: 链表是一种物理存储上非连续,通过指针链接次序,实现的一种线性存储结构. 二.特点: 链表由一系列节点(链表中每一个元素称为节点)组 ...

  9. 6.方法(go语言学习笔记)

    6.方法(go语言学习笔记) 目录 定义 匿名字段 方法集 表达式 1. 定义 方法是与对象实例绑定的特殊函数. 方法是面向对象编程的基本概念,用于维护和展示对象的自身状态.对象是内敛的,每个实例对象 ...

  10. 梓益C语言学习笔记之指针

    梓益C语言学习笔记之指针 一.32位平台下,地址是32位,所以指针变量占32位,共4个字节 二.内存单元的地址即为指针,存放指针的变量称为指针变量,故:"指针"是指地址,是常量,& ...

最新文章

  1. 谷歌简单粗暴“复制-粘贴”数据增广,刷新COCO目标检测与实例分割新高度
  2. 【Android 组件化】路由组件 ( 组件间共享的服务 )
  3. 书评 - 《展望敏捷软件测试》
  4. 一条语句执行跨越若干个数据库
  5. nginx配置静态资源访问路径
  6. 情人节,我表白了CSDN小姐姐后,竟然...【为表白写了一个绘图工具,让我不再手残】
  7. IntelliJ IDEA 选中变量名,高亮显示其它地方的这个变量名,高亮颜色如何设置呢?
  8. sql server计算机用户权限,SQL Server新增用户并控制访问权限设置。
  9. Segment Routing 之 Data-Plane Control-Plane
  10. js html json 压缩工具,JS格式化/压缩JSON数据
  11. VBA 收集 Word关键字批量处理-Excel版
  12. 谷歌地图api根据经纬度查询地名php,在线查询经纬度 google map查询地名返回经纬度 geocode geocoder的完整实例 代码下载...
  13. java的nexttoken_int nextToken()
  14. RMON学习笔记(二)
  15. Win32 OpenGL 编程
  16. 测试工程师常见面试题
  17. Qt学习笔记(五):菜单栏
  18. 航空公司营销渠道管理研究
  19. 无人驾驶(二)---室外导航之RTK配置与接入及GPS与UTM坐标转换
  20. second life 新手必读 原文http://www.chezhe.com/game/ol/paopao/zhin

热门文章

  1. java五子棋人机对战_java swing人机对战五子棋
  2. 一种基于C6748 DSP+FPGA的软件无线电平台的设计及应用
  3. 您有一张H5新年贺卡未领取
  4. 调用情迁机器人发送微信或者QQ消息等即时通讯消息
  5. 荣耀6plus+android5.1,荣耀6Plus Emui3.1-Android5.1.1 Root教程
  6. PCI Express (PCIe) 介绍
  7. ftps协议怎么连接服务器,浅谈 FTP、FTPS 与 SFTP的区别
  8. 用74ls90组成二十四进制计数器_尘埃粒子计数器的工作原理和应用分析
  9. svn图标消失解决办法
  10. 计算机动态评估英语阅读,计算机辅助二语动态评估系统PELDiaG和CODA的比较研究...