代码改变世界

(原创)一些常见小程序(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:

pa开始,检测p是否能同时整除ab, 若是则停止循环,不是则令p1,继续检测。

qb开始,检测q是否能同时被ab整除,若是则停止循环,不是则令q1,继续检测。

#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,则直接可推算出最小公倍数qq= 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");
}