————————————————————————————————————————————————————————
定义一维数组(类型说明符 数组名【常量表达式】类似于 int a【10】)
1.为n个变量连续分配存储空间
2.所有的变量数据类型必须相同
3.所有变量所占的字节大小必须相等
有关一维数据的操作
初始化 完全初始化 int a【5】={1,2,3,4,5}
不完全初始化,未被初始化元素是0 int a【5】={1,2}
不初始化,所有元素是垃圾值 int a【5】
清零 int a【5】=0
注:只有定义数组的同时才可以整体赋值,其他情况下整体赋值都是错误的
还有赋值,排序,倒置,求最大/小值,查找,插入,删除等
例1:用数组来处理求Fibonacci数列问题
#include
void main()
{
int i;
int f[20]={1,1};
for(i = 2; i < 20; i++)
f[i]=f[i-2]+f[i-1];//Fibonacci数列公式
for(i = 0; i < 20; i++)
{
if(i%5 == 0)
printf("\n");
printf("%12d",f[i]);
}
}
例2:方法一:冒泡法对10个数排序
# include
void main()
{
int a[10];
int i,j,t;
printf("input 10 numbers :\n");
for(i=0; i<10; i++)
scanf("%d",&a[i]);
printf("\n");
for(j=0; j<9; j++)//进行9次循环,实现9次比较
for(i=0; i<9-j; i++)//在每一趟中进行9-i次比较
if(a[i] > a[i+1])//从小到大//if(a[i]
{
t = a[i];
a[i] = a[i+1];
a[i+1] = t;
}
printf("the scorted numbers :\n");
for(i=0; i<10; i++)
printf(" %d",a[i]);
printf("\n");
}
方法二:选择法对10个数排序
# include
void main()
{
int a[10];
int i,j,t;
printf("input 10 numbers :\n");
for(i=0; i<10; i++)
scanf("%d",&a[i]);
printf("\n");
for(i=0; i<=9; i++)
for(j=i+1; j<10; j++)
if(a[i] > a[j])//从小到大//if(a[i]
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
printf("the scorted numbers :\n");
for(i=0; i<10; i++)
printf(" %5d",a[i]);
printf("\n");
}
例3,进制转换问题,从终端输入要进行转换的数字(num)及某种转换的进制(base),按输入要求进行输出
# include
# include
void main()
{
int num ,base;
int a[128],i=0;
printf("please enter for num:");
scanf("%d",&num);
printf("please enter for base:");
scanf("%d",&base);
do
{
a[i]=num%base;
num=num/base;
i++;
}
while(num!=0);
for(i--;i>=0;i--)
{
if(a[i]>=10)
printf("%c",a[i]-10+'A');
else
printf("%d",a[i]);
}
printf("\n");
}
定义二维数组: 类型说明符 数组名【常量表达式】【常量表达式】
初始化
int a[2][3];//默认存储类型为auto,随机值
int a[2][3]={{3,4,5},{6,7,8}};//全部元素按行初始化
int a[2][3]={3,4,5,6,7,8};//全部元素初始化
int a[][3]{3,4,5,6,7,8};//全部元素初始化时,可忽略行标
int a[2][]={3,4,5,6,7,8};//FFFFFF错误!列标何时都不能省略
int a[2][3]={{3},{7,8}};//部分元素初始化3,0,0 7,8,0
inta[2][3]={3,7,8};//部分元素初始化3,7,8 0,0,0
static int a[2][3];//静态修饰0,0,0 0,00
例1.将一个二维数组a的行和列元素互换,存到另一个二维数组b中4
# include
void main()
{
int a[2][3]={{1,2,3},{4,5,6}};
int b[3][2],i,j;
printf("array a:\n");
for(i=0; i<=1; i++)
{
for(j=0; j<=2; j++)
{
printf("%5d", a[i][j]);
b[j][i] = a[i][j];
}
printf("\n");
}
printf("array b :\n");
for(i=0; i<=2; i++)
{
for(j=0; j<=1; j++)
{
printf("%5d", b[i][j]);
}
printf("\n");
}
}
与例1相类似
/* 编写程序,实现矩阵(3 行、3 列)的转置(即行列转换)。
例如,若输入下面的矩阵:
100 200 300
400 500 600
700 800 900
则程序输出:
100 400 700
200 500 800
300 600 900*/
# include
void main()
{
int a[3][3],i,j,t;
for(i=0; i<3; i++)
for(j=0; j<3; j++)
scanf("%d",&a[i][j]);
for(i=0; i<3; i++)
for(j=0; j<i; j++)//for(j=i;j<3;j++)
{
t = a[i][j];
a[i][j] = a[j][i];
a[j][i] = t;
}
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
{
printf("%5d", a[i][j]);
}
printf("\n");
}
}
例2.定义一个 N*N 的二维数组(N 为 4),采用键盘赋值方式赋值后以矩阵形式显示,然后将 数组右上半角元素中的值乘以 m(m 键盘赋值)后显示。
# include
# define N 4
void main()
{
int a[N][N],i,j,m;
for(i=0; i<N; i++)
for(j=0; j<N; j++)
scanf("%d", &a[i][j]);
scanf("%d",&m);
for(i=0; i<N; i++)
for(j=0; j<N; j++)
printf("%5d", a[i][j]);
printf("\n\n");
for(i=0; i<N; i++)
for(j=i; j<N; j++)
{
a[i][j] = a[i][j]*m;//右上角
}
for(i=0; i<N; i++)
for(j=0; j<N; j++)
printf("%5d", a[i][j]);
printf("\n\n");
}
例3.对 4 行 4 列二维数组的每一行排序,偶数行(0 当作偶数)由小到大排序,奇数行由大到
小排序。如二维数组:int a[4][4]= {{15,4,2,16},{12,7,9,6},{8,14,11,5},{3,10,1,13}};,经过排
序以后为:{{2,4,15,16},{12,9,7,6},{5,8,11,14},{13,10,3,1}}。
# include
# include
void main()
{
int a[4][4]= {{15,4,2,16},{12,7,9,6},{8,14,11,5},{3,10,1,13}};
int i,j,t,k;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf("%d ",a[i][j]);
printf("\n\n");
}
for(i=0;i<4;i++)
{
if(i%2==0)
{
for(j=0; j<4; j++)
for(k=j+1;k<4;k++)
if(a[i][j] > a[i][k])
{
t = a[i][j];
a[i][j] = a[i][k];
a[i][k] = t;
}
}
else
{
for(j=0; j<4; j++)
for(k=j+1;k<4;k++)
if(a[i][j] < a[i][k])
{
t = a[i][j];
a[i][j] = a[i][k];
a[i][k] = t;
}
}
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf("%d ",a[i][j]);
printf("\n\n");
}
}
杨辉三角形
# include
# include
void main()
{
int a[10][10]={0},i,j;
for(i=0;i<10;i++)
{
a[i][0]=1;
for(j=1;j<i;j++)
a[i][j]=a[i-1][j-1]+a[i-1][j];
a[i][j]=1;
}
for(i=0;i<10;i++)
{
for(j=0;j<=i;j++)//左下半角
printf("%4d",a[i][j]);
printf("\n");
}
/*for(i=0;i<10;i++)
for(j=i;j<10;j++)右上半角*/
}
双引号引起来的0个或多个字符和转义字符构成,存储特点为以结尾0作为结束标记,结尾0即‘\0’,称为空字符
char str[5]={‘a’,‘b’,‘c’,‘d’,‘e’}//单个字符赋值
char str[5]={“alan”}//字符串赋值
char str[]=“alan”//字符串赋值
根据字符数组所存储的内容选择输入输出函数
//以单个字符为单位,则选择scanf/printf为输入输出函数
# include
void main()
{
char str[5]={'a','b','c','d','e'};
int i;
for(i=0;i<sizeof(str)/sizeof(str[0]);i++)
printf("%c",str[i]);
printf("\n");
}
//以字符串数据存入,则首选gets和puts来实现输入输出函数
# include
void main()
{
char str[]="alan";
puts(str);
(# include
char str1[30]={"People's Republic of "};
char str2[]={"China"};
printf("%s\n",strcat(str1,str2));//strcat(字符数组1,字符数组2);
显示结果:
People's Republic of China
Press any key to continue
strlen测量字符串长度,遇到'\0'结束,'\0'不计数
char str[]="alan";
printf("strlen(str)=%d\n",strlen(str));//不包含0的长度
printf("sizeof(str)=%d\n",sizeof(str));//某变量所占的字节内存数
char str[128]="welcome";
char str2[]="China";
strcpy(str,str2);
puts(str)
显示结果
China
Press any key to continue
char str[128]="abcdf";
char str2[]="abcde";
strcmp(str,str2);
printf("%d\n",strcmp(str,str2));
显示结果
1
strlwr :将字符串中大写字母转换成小写字母
strupr: 将字符串中小写字母转换成大写字母
//输入一行字符串,统计其中有多少单词,单词之间用空格分开
# include
# include
void main()
{
char string [81];
int i,num=0,word=0;
char c;
gets(string);
for(i=0;(c=string[i])!='\0';i++)
{
if(string[i]== ' ')
{
word=0;
}
else if(word==0)
{
word=1;
num++;
}
}
printf("There are %d words in the line.\n",num);
}
//从键盘输入如下字符:******A*BC**D******,完成以下功能:删除尾部的*,结果为:
******A*BC**
# include
void main()
{
char a[20];//******A*BC**D******
int i;
gets(a);
for(i=0;a[i]!='\0';i++);
i--;
while(a[i]=='*')
i--;
i++;
a[i]='\0';
puts(a);
}
/*从键盘输入如下字符:******A*BC**D******,删除中间的星号,结果为:
******ABCD*******/
# include
# include
void main()
{
char a[20];
int i,j,k;
gets(a);
for(i=0;a[i]=='*';i++);
k=strlen(a)-1;
while(a[k]=='*')
k--;
for(j=i;j<=k;j++)
if(a[j]!='*')
{
a[i]=a[j];
i++;
}
for(j=k+1;a[j]!=0;j++,i++)
a[i]=a[j];
a[i]='\0';
puts(a);
}
避免重复性操作
有利于程序的模块化
逻辑上:能够完成特定功能的独立的代码块
物理上:能够接收数据(当然也可以不接受数据)
能够对接受的数据进行处理
能够将数据处理的结果返回(当然也可以不返回任何值)
总结:函数是个工具,它是为了解决大量类似问题而设计的函数可以是黑匣子
类型标识符 函数名(形式参数表列)
{
函数执行体
}
1.函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体方法
2.return表达式:1>终止被调函数,向主调函数返回表达式
2>如果表达式为空,则终止函数,不向被调函数返回任何值
3>break是用来终止循环和switch的,return是用来终止函数的
3.函数返回值的类型也称为函数的类型,因为如果函数名前的类型不同的话,则最终函数返回值的类型,以函数名前的返回值类型为准
# include
int print_fun(int m)//被调函数,m为形参
{
printf("Hello World\n");
printf("Code:%d\n",m);
return 0;
}
void main()//主调函数
{
int i = 1,vet;
vet = print_fun(i);//i被称为主调函数所调用的实际参数
printf("vet = %d\n",vet);
}
有参函数 无参函数
有返回值函数 无返回值函数
库函数 用户自定函数
普通函数 主函数(main函数)
一个程序必须有且只能有一个函数
主函数可以调用普通函数
普通函数不能调用主函数
普通函数可以相互调用
主函数是程序的入口,也是程序的出口
如果函数调用写在了函数定义的前面,则必须加函数前置声明
函数前置声明:1.告诉编译器即将可能出现的若干个字母代表的是一个函数
2.告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况
3.函数声明是一个语句,末尾必须加分号
4.对库函数的声明是通过# include<库函数所在的文件名字.h>来实现
形参和实参 个数相同;位置一一对应,数据类型必须相互兼容
如何在软件开发合理的设计函数来解决实际问题
一个函数的功能是尽量独立,单一
多学习,多模仿牛人的代码
函数是C语言的基本单位,类是Java,C#,C++的基本单位
double sqrt(double x) 求x的平方根
double fabs(double x) 求x的绝对值
int abs(int x) 求x的绝对值
//调用三个数,最大值与最小值之差
# include
# include
int max_(int x,int y,int z)
{
int t;
t = x > y? x : y;
return t > z? t : z;
}
int min_(int x,int y,int z)
{
int t;
t = x < y? x : y;
return t < z? t : z;
}
int dis(int x,int y,int z)
{
return max_(x,y,z) - min_(x,y,z);
}
void main()
{
int a,b,c,ret;
scanf("%d%d%d",&a,&b,&c);
ret=dis(a,b,c);
printf("ret=%d\n",ret);
}
一个函数的直接或间接调用自身
已知条件 出错条件 递进/递出条件
斐波那契数列
# include
# include
int fib(n)
{
if(n<=0)
return -1;
if(n==1||n==2)
return 1;
return (fib(n-1)+fib(n-2));
}
void main ()
{
int n;
scanf("%d",&n);
printf("%d\n",fib(n));
}
阶乘n!
int fun(n)
{
if(n<0)
return -1;
if(n==0||n==1)
return 1;
return n * fun(n-1);
}
void main ()
{
int n;
scanf("%d",&n);
printf("%d\n",fun(n));
}
#include
void main()
{
int *p;//p是变量的名称,int *p表示p变量存放的int类型变量的地址上
int i = 3;
p = &i;//ok
//p=i;//error,因为类型不一致,p只能在存在int 类型的地址,不能存在int 类型的值
return 0;
}
1 int *p//(1)不表示定义了一个名字叫做 p的变量;
(2)p是变量名,p变量的数据类型是int 类型(即存放int变量地址的类型)
2.p = & i;//(1).p保存了i的地址,因此p指向了i
(2)p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值也不影响p的值
(3)如果一个指针变量指向了某个普通变量则指针就完全等同于普通变量
例子:如果p是个指针变量,并且p存放了普通i的地址,则p指向了普通变量i
p就完全等同于i
或者说在所有出现p的地方可以换成i;在所有出现i的地方都可以替换成p
*p就是以p的内容为地址的变量
1.指针就是地址,地址就是指针
2.地址就是内存单元的编号
3.指针变量是存放地址的变量
4.指针和指针变量是两个不同的概念。但是要注意,通常我们叙述时把指针变量称为指针,实际上他们含义不一样
//野指针:指针还没有指向的空间,就开始用指针所指向的空间
#include
void main()
{
int *p;
*p = 100;
printf("%d\n",*p);
}
//空指针:指针指向NULL
int *p=NULL;
*p=100;//报错
//空类型:void *赋给任何类型的指针都是合法的,任何类型的指针赋给void *也是合法的、
void * temp;
temp= p;
q=temp;
# include
int main()
{
int i = 5;
int * p;
int * q;
p = &i;
i=123;
*p=456;
printf("%d\n",i);
printf("%d\n",*p);//i=456,*p=456
//*q = p;
//*q = *p;error 语法编译会出错
p = q;//q是垃圾值,q赋给p,p也变成垃圾值
printf("%d\n",*q);//q的空间是属于本程序的,所以本程序可以读写q的内容,但是如果q的内部是垃圾值,则本程序不能读写*q的内容。因为此时*q所代表的内存单元的控制权限并没有分配给该程序
}
传参(值传递不适合,地址传递合适)
//值传递
void swap(int a,int b)
{
int t;
t=a;
a=b;
b=t;
}
void main()
{
int i=3,j=5;
printf("i=%d,j=%d\n",i,j);
swap(i,j);
printf("i=%d,j=%d\n",i,j);
}
//地址传递
# include
void huhuan_2(int *p, int *q)
{
int t;//如果要互换p和q的值,则t必须是int
t = *p;
*p = *q;
*q = t;//p是int *,*p是int
}
void main()
{
int a = 3;
int b = 5;
huhuan_2(&a,&b);
//huhuan_2(* p,* q);是错误的
printf("a = %d, b = %d\n",a,b);
}
附注:*的含义 1.乘法
2.定义指针变量 int *p//定义了一个名字叫p的变量 int 表示只能存放int变量的地址
3.指针运算符
该运算符放在已经定义好的指针变量,如果 p是已经定义好的指针变量,则p表示以p的内容为地址的变量
如何通过被调函数修改主调函数变量的值
1.实参必须为该普通变量的地址
2.形参必须为指针变量
3.在被调函数中通过
*形参名=……
就可以修改主调函数相关变量的值
//例子:输入a、b、c这三个整数,按大小顺序输出
# include
void main()
{
void exchange (int * q1,int * q2,int * q3);
int a, b, c,* p1,* p2,* p3;
scanf("%d,%d,%d",&a, &b, &c);
p1 = &a;
p2 = &b;
p3 = &c;
exchange(p1, p2, p3);
printf("\n%d,%d,%d\n",a,b,c);
}
void exchange (int * q1,int * q2,int * q3)
{
void swap(int * pt1, int * pt2);
if( * q1 < * q2)swap(q1,q2);
if(* q1 < * q3)swap(q1,q3);
if(* q2 < * q3)swap(q2,q3);
}
void swap(int * pt1, int * pt2)
{
int temp;
temp = *pt1;
* pt1 = *pt2;
* pt2 = temp;
}
一维数组名是个指针常量,它存放的是一维数组第一个元素的地址
如果p是个指针变量,则p[i]永远等于*(p+i)
确定一个一维数组需要几个参数(数组第一个元素的地址,数组的长度)
//基本指针操作一维数组
# include
void main()
{
int a[]={3,4,5,6,7,8,9,0};
int i;
int *p;
p=a;//p=&a[0];
for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
printf("%d ,*(p+i));
}
//指针运算:指针做减法时常常是两个指针指向了同一块的存储空间,结果为两个指针之间相差的元素个数
# include
void main()
{
int a[]={13,44,85,96,27,58,9,10};
int *p,*q;
p=&a[0];
q=&a[3];
printf("%d\n",q-p);
}
//由指针控制一维数组的输入输出
# include
void main()
{
int a[5];
int *p=a,i;
for(i=0;i<5;i++,p++)
scanf("%d",p);
p=a;//重新初始化,因为在上述中的循环之后,指针已经指向了数组外的空间
for(i=0;i<5;i++,p++)
printf("%d",*p);
printf("\n");
}
//基本指针操作二维数组
# include
void main()
{
int a[2][3]={3,4,5,6,7,8};
int i,j;
int (*p)[3]=a;//行地址
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
printf("%d",*(*(p+i)+j));
printf("\n");
}
}
//扩展
int a[2][3];
int (p)[3]=a;//数组指针
值:a[i][j]=((a+i)+j)=((p+i)+j) =p[i][j];
地址:&a[i][j]=(a+i)+j=*(p+i)+j =&p[i][j];
//指针作函数参数,二维数组
# include
void print_arr(int(*p)[3],int i,int j)
{
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
printf("%d",*(*(p+i)+j));
printf("\n");
}
}
void main()
{
int a[2][3]={3,4,5,6,7,8};
print_arr(a,2,3);
}
//习题:构建一个二维数组,用来存放3个学生4门课的成绩,写函数,分别完成:(1)求总平均成绩,(2)输出指定要查看的学生
# include
# define M 3
# define N 4
float score_are(int *p, int n)
{
int i;
float sum = 0;
for(i=0;i<n;i++)
sum+=p[i];
return sum/n;
}
void find_stu(int(*p)[4],int m, int n)
{
int id,i;
printf("please enter iD:");
scanf ("%d",&id);
if(id<0||id>=m)
return;
for(i=0;i<n;i++)
printf("%d",*(*(p+id)+i));
printf("\n");
}
void main()
{
int a[M][N]={{89,87,91,76},{100,70,88,69},{95,89,71,80}};
printf("%f\n",score_are(*a,M*N));
find_stu(a,M,N);
}
# include
void main()
{
char *p="Hello World";
char str[]="Hello World";
printf("sizeof(p)=%d\n",sizeof(p));
printf("sizeof(str)=%d\n",sizeof(str));
puts(p);
puts(str);//输出一样
}
返回地址值的函数 (指针函数:返回值为地址的函数,如int *fun(int,int) )
/*用函数实现查找某一行,并将找到的相关数据的地址返回*/
# include
# define M 3
# define N 4
int* find_stu(int(*p)[4],int m)
{
int id,i;
printf("please enter iD:");
scanf ("%d",&id);
if(id<0||id>=m)
return NULL;
return *(p+id);
}
void main()
{
int a[M][N]={{89,87,91,76},{100,70,88,69},{95,89,71,80}};
int *p;
int i;
p=find_stu(a,M);
if (p==NULL)
printf("can not find!");
else
{
for(i=0;i<N;i++)
printf("%d",*(p+i));
}
}
# include
void main()
{
int m=3,j=5,k=7,i;
int *arr[3]={&m,&j,&k};
for(i=0;i<3;i++)
printf("%d",*arr[i]);
}
# include
int add(int a,int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
int fun_op(int num1,int num2,int(*p)(int, int))
{
return p(num1,num2);
}
void main()
{
int i=3,j=5;
printf("%d\n",fun_op(i,j,add));
}