C语言学习-翁凯(第八章笔记)
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以内的素数表
- 令x为2
- 将2x、3x、4x直到ax<n的数标记为非素数
- 令x为下一个没有被标记为非素数的数,重复2;直到所有的数都已经尝试完毕
- 要构造n以内(不含)的素数表
- 开辟prime[n],初始化其所有元素为1,prime[x]为1表示x是素数
- 令x=2
- 如果x是素数,则对于
(i=2;x*i<n;i++);
令prime[i*x]=0
- 令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语言学习-翁凯(第八章笔记)相关推荐
- C语言学习-翁凯(第九章笔记)
C语言学习-翁凯(第九章笔记) 第九章 9.1.1 取地址运算:&运算符取得变量的地址 运算符& scanf("%d",&i);里面的& 获得变量的 ...
- C语言学习-翁凯(第七章笔记)
C语言学习-翁凯(第七章笔记) 第七章 7.1.1初见函数 素数求和 int m,n;int i;int cnt=0;int sum=0;scanf("%d %d",&m, ...
- C语言学习-翁凯(第六章笔记)
C语言学习-翁凯-第六章 第六章 6.0.1 给定条件的整数集 int a;scanf("%d",&a);int i,j,k;int cnt=0;//i=indexi=a; ...
- c语言翁凯中程序,程序设计入门——C语言(翁凯老师)(基础部分)(总结)...
Tips1:关于int main(int argc, char* argv[]) argc是命令行总的参数个数 argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数 命令行后面跟的用户 ...
- 【三万粉丝终极福利】Python、C、Java三大语言学习路线和资源整理
大家好,我是辣条. 今天给大家带来三万粉丝三大语言学习路线和资源整理,收藏就对了. 目录 C语言 学习路线 学习书籍 学习视频 资源推荐 Java语言 学习路线 学习书籍 学习视频 资源推荐 Pyth ...
- C语言有简单基础的入手指南(MOOC课程 浙大 翁凯老师主讲)听课笔记 the basic knowledge of C
欢迎各位小白来了解C语言相关知识 下面的是我在MOOC课程中做的笔记 由简单到复杂,建议收藏后慢慢看,这里有很多不常用但很实用的东西 //else if的另一种表述switch-case switch ...
- r语言c函数怎么用,R语言学习笔记——C#中如何使用R语言setwd()函数
在R语言编译器中,设置当前工作文件夹可以用setwd()函数. > setwd("e://桌面//") > setwd("e:\桌面\") > ...
- 梓益C语言学习笔记之链表&动态内存&文件
梓益C语言学习笔记之链表&动态内存&文件 一.定义: 链表是一种物理存储上非连续,通过指针链接次序,实现的一种线性存储结构. 二.特点: 链表由一系列节点(链表中每一个元素称为节点)组 ...
- 6.方法(go语言学习笔记)
6.方法(go语言学习笔记) 目录 定义 匿名字段 方法集 表达式 1. 定义 方法是与对象实例绑定的特殊函数. 方法是面向对象编程的基本概念,用于维护和展示对象的自身状态.对象是内敛的,每个实例对象 ...
- 梓益C语言学习笔记之指针
梓益C语言学习笔记之指针 一.32位平台下,地址是32位,所以指针变量占32位,共4个字节 二.内存单元的地址即为指针,存放指针的变量称为指针变量,故:"指针"是指地址,是常量,& ...
最新文章
- 谷歌简单粗暴“复制-粘贴”数据增广,刷新COCO目标检测与实例分割新高度
- 【Android 组件化】路由组件 ( 组件间共享的服务 )
- 书评 - 《展望敏捷软件测试》
- 一条语句执行跨越若干个数据库
- nginx配置静态资源访问路径
- 情人节,我表白了CSDN小姐姐后,竟然...【为表白写了一个绘图工具,让我不再手残】
- IntelliJ IDEA 选中变量名,高亮显示其它地方的这个变量名,高亮颜色如何设置呢?
- sql server计算机用户权限,SQL Server新增用户并控制访问权限设置。
- Segment Routing 之 Data-Plane Control-Plane
- js html json 压缩工具,JS格式化/压缩JSON数据
- VBA 收集 Word关键字批量处理-Excel版
- 谷歌地图api根据经纬度查询地名php,在线查询经纬度 google map查询地名返回经纬度 geocode geocoder的完整实例 代码下载...
- java的nexttoken_int nextToken()
- RMON学习笔记(二)
- Win32 OpenGL 编程
- 测试工程师常见面试题
- Qt学习笔记(五):菜单栏
- 航空公司营销渠道管理研究
- 无人驾驶(二)---室外导航之RTK配置与接入及GPS与UTM坐标转换
- second life 新手必读 原文http://www.chezhe.com/game/ol/paopao/zhin
热门文章
- java五子棋人机对战_java swing人机对战五子棋
- 一种基于C6748 DSP+FPGA的软件无线电平台的设计及应用
- 您有一张H5新年贺卡未领取
- 调用情迁机器人发送微信或者QQ消息等即时通讯消息
- 荣耀6plus+android5.1,荣耀6Plus Emui3.1-Android5.1.1 Root教程
- PCI Express (PCIe) 介绍
- ftps协议怎么连接服务器,浅谈 FTP、FTPS 与 SFTP的区别
- 用74ls90组成二十四进制计数器_尘埃粒子计数器的工作原理和应用分析
- svn图标消失解决办法
- 计算机动态评估英语阅读,计算机辅助二语动态评估系统PELDiaG和CODA的比较研究...