函数是一块代码,接收零个或多个参数,做一件事情,并返回零个或一个值。
()起到了表示函数调用的重要作用,即使没有参数也需要()。
int main() { sum(1,10); sum(20,30); sum(35,45); return 0; }return停止函数的执行,并送回一个值。一个函数里可以出现多个return语句。
没有返回值的函数:void函数名(参数表)
不能使用带值的return,可以没有return,调用的时候不能做返回值的赋值。
#include <stdio.h> void sum(int begin,int end); int main() { sum(1,10); sum(20,30); sum(35,45); return 0; } void sum(int begin,int end) { int i; int sum=0; for(i=begin;i<=end;i++){ sum+=i; } printf("%d到%d的和是%d\n",begin,end,sum); }对于函数参数表中的参数,叫做”形式参数“。
调用函数时给的值叫做”实际参数“。
本地变量:函数的每次运行,就产生一个独立的变量空间,在这个空间中的变量,是函数的这次运行所独有的。定义在函数内部的变量就是本地变量。参数也是本地变量。
变量的生存期:什么时候这个变量开始出现了,到什么时候它消亡了。
变量的作用域:在(代码的)什么范围内可以访问这个变量(这个变量可以起作用)
C语言不允许函数嵌套定义。
运算符&:获得变量的地址,其操作数必须是变量。
int i; printf("%p",&i);地址的大小是否与int相同取决于编译器。
指针:保存地址的变量。
int i; int* p=&i; //下面两种表达方式相同 int* p,q; int *p,q;变量的值是内存的地址。普通变量的值是实际的值。指针变量的值是具有实际值的变量的地址。
void f(int *p); int i=o; f(&i);在被调用的时候得到了某个变量的地址,在函数里面可以通过这个指针访问外面的这个i。
*是一个单目运算符,用来访问指针的值所表示的地址上的变量,可做右值也可做左值。
int k=*p; *p=k+1;
交换两个变量的值
#include <stdio.h> void swap(int *pa,int *pb); int main(void) { int a=5; int b=6; swap(&a,&b); printf("a=%d,b=%d\n",a,b); return 0; } void swap(int *pa,int *pb) { int t=*pa; *pa=*pb; *pb=t; }函数返回多个值,某些值就只能通过指针返回。
传入的参数实际上是需要保存带回的结果的变量。
#include <stdio.h> void minmax(int a[],int len,int *max,int *min); int main(void) { int a[]={1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55,}; int min,max; minmax(a,sizeof(a)/sizeof(a[0]),&min,&max); printf("min=%d,max=%d\n",min,max); return 0; } void minmax(int a[],int len,int *min,int *max) { int i; *min = *max=a[0]; for(i=1;i<len;i++){ if(a[i]<*min){ *min=a[i]; } if(a[i]>*max){ *max=a[i]; } } }函数返回运算的状态,结果通过指针返回。常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错。但是当任何数值都是有效的可能结果,就得分开返回了。
#include <stdio.h> //如果除法成功返回1,否则返回2 int divide(int a,int b,int *result); int mian(void) { int a=5; int b=2; int c; if(divide(a,b,&c)){ printf("%d/%d=%d\n",a,b,c); } return 0; } int divide(int a,int b,int *result) { int ret = 1; if (b==0)ret=0; else{ *result=a/b; } result ret; }函数参数表中的数组实际上是指针,可以用数组的运算符[]进行运算。
下面四种函数原型是等价的:
int sum(int *ar,int n);
int sum(int*,int);
int sum(int ar[],int n);
int sum(int[],int);
数组变量是特殊的指针,数组变量本身表达地址。所以int a[10];int*p=a;无需用&取地址。
但是数组的单元表达的是变量,需要用&取地址。a==*a[0];
[]运算符可以对数组做,也可以对指针做。
运算符可以对指针做,也可以对数组做: * a=25;
数组变量是const的指针,所以不能被赋值
int a[]<==>int *const a=…
指针是const表示一旦得到了某个变量的地址,便不能再指向其他变量。表示不能通过这个指针去修改那个变量,并不能使得那个变量成为const。
const int *p=&i; *p=26;//ERROR!(*p)是const i=26;//OK p=&j;//OK判断哪个被const
const int p 里的const是修饰int的,也就是说这个int值不可以改变 int const * p 里 const是修饰p的 , 而*p的类型是int 也就是说const修饰的是int , 那也是跟上面的一样int值不可变
(int) const § p的类型是int是个指针 这个指针是一个放地址的变量 const修饰的是p也就是修饰的类型是int*也就是这个指针不可变 就是地址不可变 虽然地址不能改变,但是地址指向的int的值是可以变的,const修饰的只是一个地址。
const int *p : 值不可变
int const *p : 值不可变
int *const p : 地址不可变, 那个地址的值可以变
const int *const p : 地址和值都不可变
当要传递的参数类型比地址大的时候,可以将一个非const的值转换成const的。
void f(const int* x); int a=15; f(&a);//ok const int b=a; f(&b);//ok b=a+1;//Error!const int a[]={1,2,3,4,5,6,};
数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int,所以必须通过初始化进行赋值。
保护数组值:因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值,为了保护数组不被函数破坏,可以设置参数为const。
int sum(const int a[],int length);给一个指针加1表示要让指针指向下一个变量
int a[10]; int *p=a; *(p+1)-->a[1]如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义。
*p++:取出p所指的那个数据来,完事后顺便把p移到下一个位置去。*的优先级虽然高,但是没有++高。常用于某些数组类的连续空间操作,在某些CPU上可直接被翻译成一条汇编指令。
无论指向什么类型,所以的指针的大小都是一样的,因为都是地址。但是指向不同类型的指针是不能直接互相赋值的。
void*表示不知道指向什么类型的指针。
计算时与char*相同(但不相通)。
指针也可转换类型。
int *p=&i;void *q=(void *)p;
这并没有改变p所指的变量的类型,而是以不同的眼光通过p看其所指的变量。
int *a = (int *)malloc(n *sizeof(int));
#include <stdio.h> #include<stdlib.h> int main(void) { int number; int *a; int i; printf("输入数量:"); scanf("%d",&number); //int a[number]; a=malloc(number*sizeof(int)); for(i=0;i<number;i++){ scanf("%d",&a[i]); } for(i=number-1;i>=0;i--){ printf("%d",a[i]); } free(a); return 0; }malloc
#include <stdlib.h>
void*malloc(size_t size);
向malloc申请的空间的大小是以字节为单位的,返回的结果是void*,需要类型转换为自己需要的类型。
如果申请失败则返回0或NULL。
free():把申请来的空间还给系统。只是还申请来的空间的首地址。
输出一个中文版九九乘法表
#include <stdio.h> int main() { char a[21]={"0一二三四五六七八九十"}; int i=1,j=1,t=1,u=1; for(i=1;i<=9;i++) { for(j=1;j<=i;j++) { if(i*j<=9&&i!=j) { printf("%c%c%c%c得%c%c\t",a[2*j-1],a[2*j],a[2*i-1],a[2*i],a[2*i*j-1],a[2*i*j]); } if(i*j<=9&&i==j) { printf("%c%c%c%c得%c%c\n",a[2*j-1],a[2*j],a[2*i-1],a[2*i],a[2*i*j-1],a[2*i*j]); } if(i*j>9&&i!=j) { printf("%c%c",a[2*j-1],a[2*j]); printf("%c%c",a[2*i-1],a[2*i]); printf("%c%c",a[2*(i*j/10)-1],a[2*(i*j/10)]); printf("%c%c",a[19],a[20]); if(i*j%10!=0) { printf("%c%c",a[2*(i*j%10)-1],a[2*(i*j%10)]); } printf("\t"); } if(i*j>9&&i==j) { printf("%c%c",a[2*j-1],a[2*j]); printf("%c%c",a[2*i-1],a[2*i]); printf("%c%c",a[2*(i*j/10)-1],a[2*(i*j/10)]); printf("%c%c",a[19],a[20]); printf("%c%c",a[2*(i*j%10)-1],a[2*(i*j%10)]); printf("\t"); printf("\n"); } } } return 0; }小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字 (长度不一定,以 00 结束),记住了然后反着念出来(表示结束的数字 00 就不要念出来了)。这对小鱼的那点记忆力来说实在是太难了,你也不想想小鱼的整个脑袋才多大,其中一部分还是好吃的肉!所以请你帮小鱼编程解决这个问题。
#include <stdio.h> int main() { int a[100],i,t; while(t!=0){ if(i<=99){ printf("请输入一个整数:"); scanf("%d",&t); i++; a[i]=t; }else{ t=0; a[100]=0; } } do{ i--; printf("%d ",a[i]); }while(i>=2); return 0; }输入L、R两个数(L一定小于或等于R且R小于1000),然后输入一个小于10的整数n,请统计范围[L,R]的整数中n出现的次数(如n=2,2 、12、 20、22、222等,注意当n=0时可能会出现bug)
#include <stdio.h> int main() { int n,t,u,i=0; double L,R; printf("请输入两个小于1000的数:"); scanf("%lf %lf",&L,&R); printf("请输入一个小于10的整数:"); scanf("%d",&n); if(R<L) { u=R; R=L; L=u; } if(L/100!=0) { t=L; while(t<=R) { if(t/100==n) { i++; } if(t/10%10==n) { i++; } if(t%10==n) { i++; } t++; } } if(L/100==0&&L/10!=0) { t=L; while(t<=R) { if(t/100==n) { i++; } if(t/10%10==n) { i++; } if(t%10==n) { i++; } t++; } } if(L/10==0) { t=L; while(t<=R) { if(t/100==n) { i++; } if(t/10%10==n) { i++; } if(t%10==n) { i++; } t++; } } printf("%d",i); return 0; }输入10个打乱的整数,使用冒泡排序将这10个数从小到大排好并输出(可以百度冒泡排序,但是要理解怎么用)
#include <stdio.h> int main() { int i,j,t,a[10]; for(i=0;i<10;i++) { scanf("%d",&a[i]); } for(i=0;i<10;i++) { for(j=0;j<10;j++) { if(a[i]<a[j]) { t=a[i]; a[i]=a[j]; a[j]=t; } } } for(i=0;i<10;i++) { printf("%d ",a[i]); } return 0; }输入一个4x5的矩阵,输出它的转置矩阵
#include <stdio.h> int main() { int i,j,a[10][10]; for(i=0;i<4;i++) { for(j=0;j<5;j++) { scanf("%d",&a[i][j]); } } for(j=4;j>=0;j--) { for(i=3;i>=0;i--) { printf("%3d",a[i][j]); } printf("\n"); } return 0; }夏天到了,各家各户的用电量都增加了许多,相应的电费也交的更多了。小玉家今天收到了一份电费通知单。小玉看到上面写:据闽价电[2006]27号规定,月用电量在150千瓦时及以下部分按每千瓦时0.4463元执行,月用电量在151~400千瓦时的部分按每千瓦时0.4663元执行,月用电量在401千瓦时及以上部分按每千瓦时0.5663元执行;小玉想自己验证一下,电费通知单上应交电费的数目到底是否正确呢。请编写一个程序,已知用电总计,根据电价规定,计算出应交的电费应该是多少。
#include <stdio.h> int main() { int amount; float money; printf("请输入用电总计:"); scanf("%d",&amount); if(amount<=150) { money=amount*0.4463; } else if(amount<=400) { money=150*0.4463+(amount-150)*0.4663; } else { money=150*0.4463+250*0.4663+(amount-400)*0.5663; } printf("应交电费为%.1f元",money); return 0; }输入一串长度为20的字母串,其中有大写有小写,请将里面的大写转为小写,小写转为大写后输出
#include <stdio.h> int main() { int i; char a[20]; for(i=0;i<20;i++) { scanf("%c",&a[i]); } for(i=0;i<20;i++) { if(a[i]>='A'&&a[i]<='Z') { printf("%c",a[i]+='a'-'A'); } else { printf("%c",a[i]+='A'-'a'); } } return 0; }当形式参数是一维数组时,可以不说明数组的长度。