(原创)一些常见小程序(C)
2013-08-27 11:19 Keiven_LY 阅读(514) 评论(0) 编辑 收藏 举报1、求一个数的全部素因子(形如60=1*2*2*3*5)
#include<stdio.h> void main() { int m,n,i=1; printf("请输入一个整数: "); scanf("%d",&m); printf("%d=%d",m,i); for(n=2;n<=m;n++) { while(m%n==0) { printf("* %d",n); m=m/n; } } printf("\n"); system("pause"); //屏幕结果显示语句 }
结果显示:
2、求一个数的全部因子
#include<stdio.h> void main() { int m,i; printf("请输入一个整数: "); scanf("%d",&m); printf("%d的全部因子有:\n",m); for(i=1;i<=m/2+1;i++) { if(m%i==0) printf(" %d",i); } printf("\n"); system("pause"); //屏幕结果显示语句 }
结果显示:
3、求100~200之间的全部素数
#include<stdio.h> #include<math.h> void main() { int n,j,i,m=0; for(n=101; n<200; n=n+2) /**偶数不可能是,直接过滤掉**/ { j = sqrt(n); for (i = 2; i <= j; i++) { if (n%i == 0) { break; } } if (i >= j + 1) { printf(" %d",n); m = m + 1; } if (m%10 == 0) /**m表示输入每10个数字一行,为了结果友好显示**/ { printf("\n"); } } printf("\n"); system("pause"); //屏幕结果显示语句 }
结果显示:
4、判断一个数是否是素数
#include<stdio.h> #include<math.h> void main() { int number,i,j; printf("请输入一个数:"); scanf("%d",&number); j = sqrt(number); for(i = 2; i <= j; i++) if (number%i == 0) break; if (i > j) printf("\n %d是一个素数。\n\n",number); else printf("\n %d不是素数。\n\n",number); system("pause"); //屏幕结果显示语句 }
结果显示:
5、判断一个年份是否是闰年
#include<stdio.h> void main() { int year,a; printf("请输入年份:"); scanf("%d",&year); if((year%4==0&&year%100!=0)||(year%400==0)) a=1; else a=0; if(a==1) printf("\n %d年是闰年\n",year); else printf("%d年非闰年\n",year); system("pause"); //屏幕结构显示 }
结果显示:
6、求两个正整数a和b的最大公约数p与最小公倍数q
方法1:
p从a开始,检测p是否能同时整除a和b, 若是则停止循环,不是则令p减1,继续检测。
q从b开始,检测q是否能同时被a和b整除,若是则停止循环,不是则令q增1,继续检测。
#include<stdio.h> void main() { int a,b, temp,p, q; printf("请输入a和b:\n"); scanf("%d%d",&a,&b); if (b<a) //将输入的两个数中小的放在a中,大的放在b中 { temp=b; b=a; a=temp; } p=a; while( a%p!=0 || b%p!=0) p--; printf("这两个数的最大公约数是%d\n",p); q=b; while( q%a!=0 || q%b!=0) q++; printf("这两个数的最小公倍数是%d\n",q); system("pause"); //屏幕结果显示 }
结果显示:
方法2:(方法1的改进)
已知整数a,b及其最大公约数p,则直接可推算出最小公倍数q:q= a*b/p;
#include<stdio.h> void main() { int a,b, temp,p, q; printf("请输入a和b:\n"); scanf("%d%d",&a,&b); if (b<a) //将输入的两个数中小的放在a中,大的放在b中 { temp=b; b=a; a=temp; } p=a; while( a%p!=0 || b%p!=0) p--; printf("这两个数的最大公约数是%d\n",p); q=a*b/p; printf("这两个数的最小公倍数是%d\n",q); system("pause"); //屏幕结果显示 }
方法3:辗转相除(以1397与2413为例)
以大数2413为被除数,以小数1397为除数,相除得:商为1,余数为1016
以除数1397为被除数,以余数1016为除数,相除得: 商为1,余数为381
以除数1016为被除数,以余数381为除数, 相除得: 商为2,余数为254
以除数381为被除数, 以余数254为除数, 相除得: 商为1 ,余数为127
以除数254为被除数, 以余数127为除数,
相除得: 商为2,余数为0
~~发现能整除,则127就是最大公约数。整个计算过程为:
#include<stdio.h> void main() { int a,b, temp,m,r; printf("请输入a和b:\n"); scanf("%d%d",&a,&b); if (b<a) //将输入的两个数中小的放在a中,大的放在b中 { temp=b; b=a; a=temp; } m=a*b; while(a!=0) { r=b%a; b=a; a=r; } printf("这两个数的最大公约数是:%d\n",b); printf("这两个数的最小公倍数是:%d\n", m/b); system("pause"); //屏幕结果显示 }
结果显示:
7、输出所有“水仙花”数。
注:所谓“水仙花”数是指一个三位数,其各位数字的立方和等于该数本身。如153就是一个“水仙花数”,因为153=13+53+33
#include<stdio.h> void main() { int n,i,j,k; printf("所有的水仙花数为:\n"); for(n=100;n<1000;n++) { i=n/100; j=n/10-i*10; k=n%10; if(n==i*i*i+j*j*j+k*k*k) printf("%d ",n); } printf("\n"); system("pause"); //屏幕结果显示 }
结果显示:
8、找出1000以内的所有“完数”
注:所谓“完数”是指一个数如果恰好等于它的因子之和,这个数就称为“完数”
如 6的因子是1 2 3,且6=1+2+3,所以6称为“完数”
#include<stdio.h> void main() { int m,s,i; printf("1000以内的所有完数有:\n"); for(m=2;m<=1000;m++) { s=0;//此处s=0一定要加,因为前几次循环的时候s的值已经改变 for(i=1;i<m;i++) if((m%i)==0) s=s+i; if(s==m) { printf("%d 它的因子有:",m); for(i=1;i<m;i++) if(m%i==0) printf("%d ",i); printf("\n"); } } system("pause"); }
结果显示:
9-1、求一个数组的逆序排列
#include <stdio.h> #define N 5 void main() { int a[N],i,temp; printf("请输入数组a的元素:"); for(i=0;i<N;i++) scanf("%d",&a[i]); printf("数组a为:"); for(i=0;i<N;i++) printf("%d ",a[i]); printf("\n"); for(i=0;i<N/2;i++) { temp=a[i]; a[i]=a[N-i-1]; a[N-i-1]=temp; } printf("数组a重排后为:"); for(i=0;i<N;i++) printf("%d ",a[i]); printf("\n"); system("pause"); }
结果显示:
9-2、字符串逆序排列(采用函数调用)
#include <stdio.h> void main() { void inverse(char str[]); //对inverse函数的声明,如果将main函数放在inverse函数的后面,就不必在main函数中声明 char string[20]; printf("请输入一个字符串String:"); scanf("%s",string); printf("\n"); inverse(string); printf("反转后的新字符串为:%s",string); printf("\n"); system("pause"); } void inverse(char str[]) { int i; char temp; for(i=0;i<strlen(str)/2;i++) { temp=str[i]; str[i]=str[strlen(str)-i-1]; str[strlen(str)-i-1]=temp; } }
结果显示:
10、输出杨辉三角形(要求前N行)
分析:
杨辉三角形是(a+b)n 展开后各项的系数。如:
(a+b)0展开后为:1 系数为:1
(a+b)1展开后为:a+b 系数为:1,1
(a+b)2展开后为:a2+2ab+b2 系数为:1,2,1
(a+b)3展开后为:a3+3a2b+3ab2+b3 系数为:1,3,3,1
(a+b)4展开后为:a4+4a3b+6a2b2+4ab3+b4 系数为:1,4,6,4,1
..................
杨辉三角形的特点:
(1)各行的第一个数都是1
(2)各行的最后一个数也都是1
(3)从第3行起,除上面指出的第一个数和最后一个数外,其余格数是上一行的同列与前一列两个数之和
表示为:a[i][j]=a[i-1][j]+a[i-1][j-1],其中i表示行,j表示列
#include <stdio.h> #define N 11 void main() { int a[N][N],i,j; //数组为11行11列,0行0列不用 for(i=1;i<N;i++) { a[i][1]=1; //各行第一个元素设为1 a[i][i]=1; //对角元素设为1 } for(i=3;i<N;i++) for(j=2;j<=i-1;j++) a[i][j]=a[i-1][j]+a[i-1][j-1]; for(i=1;i<N;i++) { for(j=1;j<i;j++) printf("%d ",a[i][j]); printf("\n"); } printf("\n"); system("pause"); }
结果显示:
11、将两个字符串连接起来(注:不允许用自带函数strcat)
方法1:直接进行
#include <stdio.h> void main() { char str1[20],str2[20]; int i=0,j=0; printf("\n请输入第一个字符串:"); scanf("%s",str1); printf("\n请输入第二个字符串:"); scanf("%s",str2); while(str1[i]!='\0') i++; while(str2[j]!='\0') str1[i++]=str2[j++]; str1[i]='\0'; printf("\n合并后的新字符串为: %s\n",str1); system("pause"); }
结果显示:
方法2:将连接行为作为一个函数,在主函数中调用
#include <stdio.h> void main() { void connection(char str1[],char str2[],char str[]); //对connection函数的声明,如果将main函数放在connection函数的后面,就不必在main函数中声明 char S1[20],S2[20],S[20]; printf("请输入第一个字符串S1:"); scanf("%s",S1); printf("\n"); printf("请输入第二个字符串S2:"); scanf("%s",S2); printf("\n"); connection(S1,S2,S); printf("合并后的新字符串为:%s",S); printf("\n"); system("pause"); } void connection(char str1[],char str2[], char str[]) { int i,j; for(i=0;str1[i]!='\0';i++) str[i]=str1[i]; for(j=0;str2[j]!='\0';j++) str[i+j]=str2[j]; str[i+j]='\0'; }
结果显示:
12、将字符数组str2中的全部字符复制到字符数组str1中(要求不允许用自带函数strcpy)
#include <stdio.h> void main() { char str1[20],str2[20]; int i; printf("\n请输入第二个字符串:"); scanf("%s",str2); for(i=0;i<=strlen(str2);i++) str1[i]=str2[i]; printf("str1: %s \n",str1); system("pause"); }
结果显示:
13、给出年、月、日,计算该日期是该年中的第几天
注意:有是否闰年之分
#include <stdio.h> void main() { int sum_day(int month,int day); int leap(int year); int year,month,day,days; printf("请输入日期(形如:年,月,日):"); scanf("%d,%d,%d",&year,&month,&day); days=sum_day(month,day); if(leap(year) && month>=3) days=days+1; printf("\n"); printf("%d/%d/%d是今年的第%d天\n",year,month,day,days); printf("\n"); system("pause"); } int sum_day(int month,int day) { int i; int day_table[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//存放12个月每月的天数 for(i=1;i<month;i++) day=day+day_table[i];//将所输入月份之前的天数累加 return(day); } int leap(int year) //判断是否是闰年 { int flag=1; if((year%4==0 && year%100!=0)||(year%400==0)) return(flag); }
结果显示:
14、用弦截法求方程f(x)=x3-5x2+16x-80=0的根(参考:谭浩强C程序设计第三版P168)-------主要考虑函数的嵌套调用
方法:
(1)取两个不同点x1,x2,如果f(x1)和f(x2)符号相反,则(x1,x2)区间内必有一个根。如果f(x1)与f(x2)同符号,则应改变x1,x2,直到f(x1)、f(x2)异号为止。注意x1、x2的值不应差太大,以保证(x1,x2)区间内只有一个根;
(2)连接(x1,f(x1))和(x2,f(x2))两点,此线(即弦)交x轴于x;
(3)若f(x)与f(x1)同符号,则根必在(x,x2)区间内,此时将x作为新的x1。如果f(x)与f(x2)同符号,则表示根在(x1,x)区间内,将x作为新的x2;
(4)重复步骤 (2) 和 (3) , 直到|f(x)|<ε 为止, ε为一个很小的数, 例如 10-6\. 此时认为 f(x)≈0 。
#include <stdio.h> #include <math.h> float f(float x) //定义函数f,实现方程 { float y; y=((x-5.0)*x+16.0)*x-80.0; return(y); } float xpoint(float x1,float x2) //定义函数xpoint,求出弦与x轴的交点 { float y; y=(x1*f(x2)-x2*f(x1))/(f(x2)-f(x1)); return(y); } float root(float x1,float x2) //定义函数root,求出近似的根 { float x,y,y1; y1=f(x1); do { x=xpoint(x1,x2); y=f(x); if(y*y1>0) { y1=y; x1=x; } else x2=x; } while(fabs(y)>=0.0001); return(x); } void main() { float x1,x2,f1,f2,x; do { printf("输入x1,x2:"); scanf("%f,%f",&x1,&x2); f1=f(x1); f2=f(x2); } while(f1*f2>0); x=root(x1,x2); printf("\n"); printf("该方程的根为:%8.4f\n",x); printf("\n"); system("pause"); }
结果显示:
15、求n!(采用递归调用)
#include <stdio.h> int fac(int n) { int y; if(n<0) printf("输入的数不符合实际!"); else if(n==0||n==1) y=1; else y=n*fac(n-1); return(y); } void main() { int y; int n; printf("请输入一个所求阶乘的数:"); scanf("%d",&n); printf("\n"); y=fac(n); printf("%d的阶乘为:%d\n",n,y); printf("\n"); system("pause"); }
结果显示:
16、输入a和b两个数,按从大到小顺序输出(目的:主要了解指针与指针变量)
几个基本概念:
(1)指针:就是地址,就像我们学过的整型、实型等数据类型一样,指针也是一种数据类型。
(2)指针变量:是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。指针变量就是存放地址的变量。
(3)内存地址:内存中存储单元的编号。
(4)指针变量名前的“*”表示该变量为指针变量,而指针变量名不包含该“*”。
(5)一个指针变量只能指向同一类型的变量。
(6)指针变量中只能存放地址,而不能将数值型数据赋给指针变量。
(7)只有当指针变量中具有确定地址后才能被引用。
与指针相关的两个运算符:
(1)&:取地址运算符
(2)*:指针运算符,取其指向的内容
指针变量的运算(如果先使指针变量p指向数组a的首元素,即p=a):
(1)p++(或p+=1):表示使p指向下一元素,即a[1]。若再次执行*p,则得到下一个元素a[1]的值
(2)*p++:由于运算符++与*是同级运算符,结合方向自右向左,因此它等价于*(p++),作用是先得到p指向的变量值(即*p),再使p+1->p
(3)*p++与*(++p):前者如上,后者是先使p加1,再取*p。若p初值为a,即p=&a[0],则*p++=a[0],*(++p)=a[1]
(4)(*p)++:表示p所指向的元素值加1。若p初值为a,即p=&a[0],则(*p)++=a[0]+1
#include <stdio.h> void main() { int *p1,*p2,*p,a,b; printf("input two number:"); scanf("%d,%d",&a,&b); p1=&a; p2=&b; if(a<b) { p=p1; p1=p2; p2=p; } printf("a=%d;b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); system("pause"); }
计算过程如图:
结果显示:
17、单链表的创建、打印、删除、插入操作(参考谭浩强C程序设计第三版P297-307)
#include <stdio.h> #include <malloc.h> #include <stdlib.h> #define NULL 0 struct student { long num; float score; struct student *next; }; int n; struct student *creat() //单向链表的创建 { struct student *head, *p1,*p2; //定义三个指向结构体的指针 n=0; p1=p2=(struct student *) malloc(sizeof(struct student)); scanf("%ld,%f",&p1->num,&p1->score); head=NULL; while(p1->num!=0) //约定学生学号不为0,如果输入的学号为0,则表示链表建立完成 { n=n+1; if(n==1) head=p1; else p2->next=p1; p2=p1; p1=(struct student *) malloc(sizeof(struct student)); scanf("%ld,%f",&p1->num,&p1->score); } p2->next=NULL; return(head); } void print(struct student *head) //打印链表 { struct student *p; printf("\nNow,These %d records are:\n",n); p=head; if(head!=NULL) do { printf("%ld,%5.1f\n",p->num,p->score); p=p->next; } while(p!=NULL); } struct student *del(struct student *head,long num) //删除结点 { struct student *p1,*p2; if(head==NULL) { printf("\nThis list is null !\n"); } p1=head; while(num!=p1->num && p1->next!=NULL) { p2=p1; p1=p1->next; } if(num==p1->num) { if(p1==head) head=p1->next; //若p1指向的是首结点,让head指向第二个节点 else p2->next=p1->next; printf("delete:%ld\n",num); n=n-1; } else printf("%ld is not been found !\n",num); return(head); } struct student *insert(struct student *head,struct student *insert_stu) //插入结点 { struct student *p0,*p1,*p2; p0=insert_stu; p1=head; if(head==NULL) { head=p0; p0->next=NULL; } else { while((p0->num>p1->num) && (p1->next!=NULL)) { p2=p1; p1=p1->next; } if(p0->num<=p1->num) { if(head==p1) head=p0; else p2->next=p0; p0->next=p1; } else { p1->next=p0; p0->next=NULL; } } n=n+1; return(head); } void main() { struct student *a; struct student new_stu; //要插入的节点 long del_num; printf("input records:\n"); a=creat(); //建立链表,返回头指针 print(a); printf("\ninput the delete number:"); scanf("%ld",&del_num); a=del(a,del_num);//删除某结点后,链表的头地址 print(a); printf("\ninput the inserted record:"); scanf("%ld,%f",&new_stu.num,&new_stu.score); a=insert(a,&new_stu); print(a); system("pause"); }
结果显示:
注意:这里有一个问题,上面的程序只能删除一个节点与插入一个节点,弱国想再插入一个节点,重复写main函数的最后4行,即想插入两个节点,这样程序运行就会出错
原因在于:new_stu是一个有固定地址的结构图变量,第一次插入到链表后,第二次若再用它插入,就会把第一层插入的节点数据冲掉,实际上程序并没有开辟两个节点
解决方法:必须在每次插入一个节点时要开辟一个新的内存空间
修改上述main函数如下(能删除多个节点,能插入多个节点):
void main() { struct student *a; struct student *new_stu; //要插入的节点 long del_num; printf("input records:\n"); a=creat(); //建立链表,返回头指针 print(a); printf("\ninput the delete number:"); scanf("%ld",&del_num); while(del_num!=0) { a=del(a,del_num);//删除某结点后,链表的头地址 print(a); printf("\ninput the delete number:"); scanf("%ld",&del_num); } printf("\ninput the inserted record:"); new_stu=(struct student *)malloc(sizeof(struct student)); scanf("%ld,%f",&new_stu->num,&new_stu->score); while(new_stu->num!=0) { a=insert(a,&new_stu); print(a); printf("\ninput the inserted record:"); new_stu=(struct student *)malloc(sizeof(struct student)); scanf("%ld,%f",&new_stu->num,&new_stu->score); } system("pause"); }