>>这里我们再说明一下,判断与循环我们把后面的课程结束了再做,现在进入数组的环节
基本数据类型,大家都知道,但是基本数据类型有一个弊端,就是在任何一个给定的时刻,一次只能保存一个数值。因此,数组这个东西都出现了。
数组:大小固定,含有相同的数据类型的元素的聚合。
数组是一种数据结构,数组名是里面所有元素所共享的,我们通过下标来获取里面的值,下标是从0开始的,也就是下标比数组元素的个数少一位。
数组又分为一维,二维和多维数组
这里说明一点,c语言是不进行下标检查的,所以,应该确保数组索引位于所声明的范围之内。
定义一个一维数组:
比如:float height [50];,int group[10];
数组这里要注意两点:
第一点:如果对数组引用超过了所声明的范围,不一定会产生错误,但是它会导致不可预知的运行结果。
第二点:数组的大小必须是一个数字常量或者符号常量
大家可能会想,C语言的字符串是怎么来处理的,c 语言里面,没有字符串这种数据类型,那么怎么来处理
就是字符数组,也就是char name[10];最多可以保存10个字符。
“well done”长度为10的字符串,也就是说下标从0--9
当编译器遇到一个字符串的时候,会为它添加空字符串作为结尾。即,元素name[10]保存的是空“\0”。当声明字符数组的时候,必须保留出一个额外的元素空间来保存空字符。
需求:从1到10,计算他们的平方和,也就是说1^2+2^2+...+10^2
结果:
下面我们来说明一下关于数组的初始化:
一维数组的初始化:
数组声明后,必须对其元素进行初始化,否则,他们包含的是些“垃圾”,也就是无法确定的值,数组初始化可在如下两个阶段进行:
编译时 运行时
一般形式如下:
比如:float number[3]={0,0,0};将变量number声明为大小为3的数组,并把0赋给每个元素。如果列表中的数组少于元素的个数,那么就只有部分被初始化。剩余的元素自动变成0.
例如:float total[5]={0.0,15.75,-10};前三个元素有值,后面两个为0,如果数组类型是字符的话,后面没有声明的元素就为空
当然了数组的大小也是可以省略的,比如int counter[]={1,1,1,1};//长度为4个元素的数组,并且值为1
字符串数组也可以用同样的方式进行初始化:
Char name[]={‘l’,’o’,’v’,’e’,’\0’};//5个字符长度的字符数组,也可以如下方式将字符串直接赋给数组
Char name[]=”love”;//注意是双引号
但是,请记住:如果用于初始化的数值多于所声明的数组大小,编译器将产生一个错误。
下面是运行时初始化数组:
这种方法通常用于大数组的初始化
用for循环来初始化。
也可以用scanf来指定输入;
Int x[3];
Scanf(“%d%d%d”,&x[0],&[1],&[2]);
下面是统计计数的方法:
一共50个学生,每个学生按照成绩分组计数
注意就是对于++ group[(int) value/10]的理解。就是说数组里面一个元素出现了多少次。
下面,我们插入一个小的知识点,代码如下,是关于循环结构的。
求2^n的代码:
#include <stdio.h>
int main4()
{
int res=1;
int i;//计数器
scanf("%d",&i);//通过键盘输入进行初始化
while(i)
{
res*=2;
i--;
}
//注意变量的作用域,出了方括号就不有效了
printf("\nres=%d,i=%d",res,i);//打印数据
system("pause");
return 0;
}
我这里想说的是,不是说程序有多难,程序非常好理解,但是,对于打印的i值,大家要注意,不管你i输入的是几,最后都是0;对i为0的时候,while循环才不会执行,对不对。
下面给大家看一下,我们调戏qq的代码:当然了,这个程序肯定是在windows上面跑的
也就是说,打开qq,然后它沿着对角线,若隐若现的移动
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
//打开qq
void open_qq()
{
ShellExecuteA(0,"open","\"C:\\Program Files (x86)\\Tencent\\QQ\\Bin\\QQScLauncher.exe\"",0,0,3);//正常打开
}
//移动qq
void move_qq()
{
int i=0;//变量的声明必须放在函数的开头
//找到窗口的位置,也就是窗口的编号
HWND win1=FindWindowA("TXGuiFoundation","QQ");//一个是类名,一个是标题
//判断一下,有没有找到这个窗口编号
if(NULL==win1)
{
printf("QQ正在玩失踪");
}
//如果找到了,我们要设置窗口位置,以及窗口的大小
while(i<768)
{
//设置窗口的位置以及窗口的大小
SetWindowPos(win1,NULL,2*i,i,400,400,0);
Sleep(500);//缓冲500豪秒
i+=10;//让i成相同的倍数增长
//我们再来做一些特效,让窗口若隐若现
if(i/10%2==1)
{
//奇数就让窗口隐藏
ShowWindow(win1,SW_HIDE);
}else{
//偶数让窗口显示
ShowWindow(win1,SW_SHOW);//打开窗口
}
}
}
int main()
{
//先把已有的qq杀死,再来打开
system("taskkill /f /im QQ.exe");
open_qq();
Sleep(5000);//缓冲秒
//移动qq
move_qq();
}
看一下下面的代码,我们可以改变wwindows里面黑窗口的背景颜色与标题
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
int main()
{
int i,i1=1;
char str[20];//20个字符的字符数组,存放颜色信息
char str1[40];//40个字符数组,存放标题信息
for(i=0;i<16;i++)//循环16次
{
//这个也就是说,改变cmd窗口的颜色
sprintf(str,"color %x%x",i,15-i);
//然后调用windows里面的系统函数改变黑窗口的颜色
system(str);
printf("\n%s",str);//打印字符串
//Sleep(1000);//缓冲是为了让它变得更慢一点
sprintf(str1,"title 启动%d秒",i1);
i1++;
//调用系统函数,改变窗口的标题
system(str1);
Sleep(1000);//缓冲一下,让程序不要那么快
}
return 0;
}
下面给大家看一个程序,疯狂的吃别人电脑的内存
Void main()
{
Do
{
Malloc(1024*1024*10);//一次吃10M的内存
}while(1);//不停的循环,这也就是一个死循环
}
下面写一个代码,通过我们的输入的数,来异步代开计算器
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
scanf("%d",&num);
printf("num=%d",num);
//do.....while
do
{
system("start calc");
num--;
}while(num);
system("pause");//暂停一下程序
return 0;
}
注意一个问题就是,do.......while中,while后面必须加上分号
下面写一个代码来输出大写转小写,小写转大写的程序代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch;
ch=getchar();//从键盘上面读取一个字符
if(ch>='A' && ch<='Z')
{
//大写转小写
ch+=32;
}else{
//小写转大写
ch-=32;
}
putchar(ch);
system("pause");
return 0;
}
//注意if里面的条件判断不要写错了
下面我们简单的来说一下for循环
For()里面条件为空,意味着死循环
需求:打印100以内,所有相邻奇偶数之积的和
#include <stdio.h>
#include <stdlib.h>
int main()
{
//这里有一个公式(2n-1)*2n,就是每个相邻数的乘积
int res=0,i;
for(i=1;i<=50;i++){
res+=(2*i-1)*2*i;
}
//循环完了之后打印结果
printf("%d,%d",i,res);
system("pause");
return 0;
}
注意:里面的i是小于等于50的,因为一次计算就是两个数,所以,只循环到50就可以了,还有就是循环完了之后,i的结果是51,这个我想大家应该知道。
我们下面在用另外一种思路来解决这个问题,也就是说,有些人特别的死板,说,我就要让i循环到100,好吧,那就来吧。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int res=0,i;
for(i=1;i<=100;i+=2)
{
res+=i*(i+1);
}
printf("i=%d,res=%d",i,res);
system("pause");
return 0;
}
需求:把数316分解为两个数之和,其中一个数是13的倍数,一个是11的倍数
13*x+11*y=316;
#include <stdio.h>
int main()
{
int i;
for(i=0;;i++)
{
printf("\ni=%d",i);
if((316-13*i)%11==0){
printf("\n%d*13+%d*11=316",i,(316-13*i)/11);
break;//一旦找到就跳出循环
}
}
getchar();
return 0;
}
注意:for循环里面,没有结束条件就是死循环,我们用了一个break,当找到了符合要求的结果,就会跳出这个死循环。
需求:利用switch条件判断来做一个Windows窗口弹出
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
int main()
{
char ch=getchar();
switch(ch)
{
case 'a':
MessageBoxA(0,"你是一个好人","好人",0);
break;
case 'c':
MessageBoxA(0,"你是一个坏人","坏人",0);
break;
case 'd':
MessageBoxA(0,"不好意思,你的电脑中毒了","360安全中心",0);
break;
}
system("pause");
return 0;
}
下面我来讲讲continue的用法
Contiue用于跳出本次循环,继续执行下一次循环,并不会像Break一样,结束整体的循环。
需求:找出0-100之间能被3整除的数
#include <stdio.h>
int main()
{
int i;
for(i=0;i<100;i++)
{
if(i%3!=0){
continue;
}
printf("%d\t",i);
}
getchar();
return 0;
}
Continue是不是明显比if.....else好用多了。
goto语句就不多说了,利用语句标号来玩的。
下面是几道算法题的解析:
第一道:数据分离
求一个水仙花数,(一个三位数,其各位数字的立方和等于该数本身)
#include <stdio.h>
int main()
{
int i;
for(i=100;i<1000;i++)
{
//个位
int g=i%10;
//十位
int s=i/10%10;
//百位
int b=i/100;
//判断
if(i==b*b*b+s*s*s+g*g*g)
{
printf("%d\t",i);
}
}
getchar();
return 0;
}
注意:上面的代码主要问题就是数据的分离,如何找出个位数,十位数,百位数。
也考了数据类型转换的问题。
第二道:整数逆置
输入一个数,然后倒转,最长不超过五位数
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,g,s,b,q,w;
scanf("%d",&a);
//判断是几位数,然后来进行处理
if(a>10&&a<100){
//两位数
g=a%10;
s=a/10;
printf("%d%d",g,s);
}else if(a>100&&a<1000){
//三位数
g=a%10;
s=a/10%10;
b=a/100;
printf("%d%d%d",g,s,b);
}else if(a>1000&&a<10000){
//四位数
g=a%10;
s=a%100/10;
b=a%1000/100;
q=a/1000;
printf("%d%d%d%d",g,s,b,q);
}else{
printf("你输入的数不符合规范");
}
system("pause");
return 0;
}
上面是整数逆置,不过不是很完美的,因为上了五位数,就不可以用了,下面我们来看看比较完美的。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//定义一个返回多少个的函数
int get10n(int n)
{
int res=1,i;
for(i=0;i<n;i++)
{
res*=10;
}
return res;//返回这个结果
}
int main()
{
int num,i,numA,last=0,wei=0;
scanf("%d",&num);
numA=num;
printf("要倒转的数据是%d\n",num);
for(;num;num/=10)
{
wei++;//当num==0时,停止for循环
}
printf("位数=%d\n",wei);
//下面就进入了核心代码
for(i=0;i<wei;i++)
{
int now_wei=0;//当前位置上的数
now_wei=numA/get10n(i)%10;//从个位开始取
last+=now_wei*get10n(wei-1-i);
}
printf("转换以后的结果是:%d\n",last);
system("pause");
return 0;
}
注意问题:
在标准c语言中规定,变量的声明必须放在所有的执行语句前面,中途声明,会有错误产生。在任何块的开头可以声明所有的局部变量。代码的具体讲解,可以参考学习笔记本。
需求:下面我们进入很有名的一个东西,叫做斐波拉契数列。我们需要求出斐波拉契数列的前四十个数。
先说一下这个数列的特点:第1,2l两个数为1,1
从第三个数开始,该数是前两个数之和。
1 1 2 3 5 8 13 21 34 55........
#include <stdio.h>
#include <stdlib.h>
/*
列举前个斐波拉契数列
*/
int main()
{
int f1=1,f2=1,f3=0,i;
printf("%d\n%d\n",f1,f2);
for(i=1;i<=38;i++)
{
//因为已知前两个数,所以只循环38次
f3=f1+f2;
printf("%d\t",f3);
f1=f2;
f2=f3;
}
system("pause");
return 0;
}
斐波拉契数列这个思想非常的漂亮,移位思想。
需求:求出100-150之间全部的素数,这道题,我们采用两种方法来做。
第一种方法:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int k;
for(k=101;k<150;k++)
{
int var=sqrt(k),i;
for(i=2;i<=var;i++)
{
if(k%i==0){
break;
}
}
if(i>var)
{
//说明上面是循环完了,是素数
printf("%d\t",k);
}
}
system("pause");
return 0;
}
上面这种方法,就是简单,大气,不失风度,再来看看下面的代码:
#include <stdio.h>
#include <stdlib.h>
int sushu(int num)
{
if(num==2 || num==3)
{
return 1;//代表是素数
}
else
{
int flag=1;//定义一个标识符,假设是素数
int i;
for(i=2;i<num;i++)
{
if(num%i==0)
{
flag=0;//素数标签变为
break;
}
}
return flag;
}
}
int main()
{
int i;
for(i=101;i<150;i++)
{
if(sushu(i)==1)
{
//返回,说明是素数
printf("%d\n",i);
}
}
system("pause");
return 0;
}
关于上面求素数的代码,我不得不说,效率太低了,第一如果是计算150的素数,->sushu(150),
他会计算148次,那么越大,次数就越多。不过思想很不错,利用一个标签的返回,来判断素数,不错,也就是说,只要进去了,俺么必定会留下东西,这个就是判断素数的方法。
下面我们再来看一道算法题:
需求:输入一个表达式,马上计算出结果。
1+2/(3+4)*5/6-6*7
正确结果应该是:-42
下面我们接着最上面的数组知识继续往下面走,讲讲二维数组,我们可以把数组看成矩阵来处理。每一个元素都有它与之对应的行数与列数。
需求:下面是一个二维数组的案例,一共4行3列,也就是12行数据,每一行代表一个美女销售,这些数据需要我们输入,然后来计算,每个美女销售的生产总值,每个物品的物品总值,总产值。
#include <stdio.h>
#include <stdlib.h>
#define MAXGIRLS 4//最大女孩业务员个数
#define MAXITEMS 3//最大物品数
int main()
{
int value[MAXGIRLS][MAXITEMS];//主要是为了存值
int girl_total[MAXGIRLS],item_total[MAXITEMS];//女孩总值与物品总值
int i,j,grand_total;//产品总值,还有两个循环变量
//reading of values and computing girl_total
printf("Input data\n");
printf("Enter values,one at the time,row_wise\n\n");
for(i=0;i<MAXGIRLS;i++)
{
//一共个女孩,每个女孩循环三次,赋上三个值
//每一次循环完了,初始化总值为
girl_total[i]=0;
for(j=0;j<MAXITEMS;j++)
{
//里面循环次
scanf("%d",&value[i][j]);
//计算每个Girl的生产总值
girl_total[i]+=value[i][j];
}
}
//computing item total
for(j=0;j<MAXITEMS;j++)
{
//计算每个物品的生产总值
item_total[j]=0;
for(i=0;i<MAXGIRLS;i++)
{
item_total[j]+=value[i][j];
}
}
//computing grand total
grand_total=0;
for(i=0;i<MAXGIRLS;i++)
{
//每个女孩的生产总值加起来就是全部的生产总值
grand_total+=girl_total[i];
}
//printing of result
printf("\nGirls Totals\n\n");
for(i=0;i<MAXGIRLS;i++)
{
printf("Salesgirl[%d]=%d\n",i+1,girl_total[i]);
}
printf("\n Item Totals\n\n");
for(j=0;j<MAXITEMS;j++){
printf("Item[%d]=%d\n",j+1,item_total[j]);
}
printf("\nGrand Total=%d\n",grand_total);
system("pause");
return 0;
}
需求:编写一个程序,显示1-5乘法表,格式如下
#include <stdio.h>
#include <stdlib.h>
#define ROWS 5//一共有五行
#define COLUMNS 5//一共五列
int main()
{
int row,column,product[ROWS][COLUMNS];
int i,j;//i代表行变量,j代表列变量
printf(" Multiplication table\n\n");
printf(" ");//这个是三个空格的宽度
for(j=1;j<=COLUMNS;j++)
{
printf("%4d",j);
}
printf("\n");
//printf("-----------\n");
for(i=0;i<ROWS;i++)
{
row=i+1;//i从开始的
printf("%4d ",row);
for(j=1;j<=COLUMNS;j++)
{
column=j;
product[i][j]=row*column;//得到乘积的结果
//每次都要打印一下结果
printf("%4d",product[i][j]);
}
printf("\n");
}
system("pause");
return 0;
}
>>下面我们来说说二维数组的初始化
列子如下:
int table[2][3]={0,0,0,1,1,1};//两行三列
上面代码的意思就是,将第一行所有元素初始化为0,第二行所有元素初始化为1.数组数组的初始化时逐行进行的。上面语句也可以写为
Int table[2][3]={{0,0,0},{1,1,1}};
也可以按照矩阵的形式来初始化二维数组
Int table[2][3]={
{0,0,0},
{1,1,1}
};
在PHP声明数组里面,最后一行元素不用加逗号
当然,如果数组元素进行了初始化,那么就不必指定第一个维数的大小了,比如下面
int table[][3]={
{0,0,0},
{1,1,1}
};
注意,如果在初始化的过程中遗漏了元素的值,那么自动将这些元素设置为0.
如果要把数组所有元素初始化为0.可以使用如下的快捷方法。
int m[3][5]={{0},{0},{0}};
下面我们进入案例的学习:
需求:数列中值的计算
首先,我们必须保证数列中的值都是按照顺序排列的,然后再来说中值的问题,如果是奇数,那么中值就是最中间的那个数,如果是偶数,就是中间的两个数之和,然后除以2
,这里主要是涉及到了一个排序问题和求中值的问题
这里我们要把数列降序排列
#include <stdio.h>
#include <stdlib.h>
#define N 10//数组能处理的最大元素个数
int main()
{
int i,j,n;
float median,a[N],t;
printf("Enter the number of items\n");
scanf("%d",&n);
//reading items into array a
printf("Input %d values \n",n);//提示一下输入几个值
for(i=1;i<=n;i++)
{
//有几个值我们就输入几个值
scanf("%f",&a[i]);//然后把它存放在数组里面
}
//核心的东西来了,排序
//注意,数组里面的值是从a[1]开始取得,也是从a[1]开始赋值的
for(i=1;i<=n-1;i++)
{
//每次循环找出最小的数,每循环一次少一次
for(j=1;j<=n-i;j++)
{
if(a[j] <= a[j+1])
{
//也就是说后一个数大于前一个数,就要交换
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
//上面循环完了,排序也排好了,下面就来计算中值
//当然了必须判断奇偶性
if(n % 2 == 0)
{
median=(a[n/2]+a[n/2+1])/2.0;
}
else
{
median=a[n/2+1];
}
//下面就是打印了
for(i=1;i<=n;i++)
{
printf("%f ",a[i]);
}
//打印中值
printf("\n\nMedian is %f\n",median);
system("pause");
return 0;
}
上面需要注意的一点就是,数组是从1开始往里面存值的。
需求:下面来计算一下标准偏差
先来说一下,平均值=所有数加起来/数的个数
方差=(每一个数与平均数的差之和)^2/数的个数
再来说标准偏差=sqrt(方差)
我们必须要记住常量是不可以修改的,尽管在.c文件它可以给予警告编译通过,但是在.cpp文件中,对语法的要求是特别严格的,也就是编译器根本不会让你通过。
上面的编译时完全没有问题的。
上面的编译也没有错。但是我想说,数组的大小是一个常量,ok没有任何的问题,但是不能是变量,也不能是表达式,不管表达式能不能计算出结果。