C语言程序设计(8)

2014

例一:
int main(){
    int *p,*q;
    p = malloc(sizeof (int)*20);
    q = malloc(sizeof (char )*10);
    ...
    q = p;		//内存泄露,q指向的存储单元内容不能找回
    ...
    free(p);
    free(q);	//重复释放,q/p已经指向同一内存单元
}
修改:将free(q)放在q=p的前面,同时实现两处修改

例二:交换字符串
void fun(char *a, char*b){
    char *temp;
    *temp =*a;	// 内存泄露,指针没有初始化!!!
    *a = *b;	
    *b =*temp;	
}
修改:将temp修改为数组,再用字符串复制函数
void fun(char *a, char *b){
    char temp[100];
    strcpy(temp,a);
    strcpy(a,b);
    strcpy(b,temp);
    //不能使用下面的语句,因为把实参地址作为参数在给形参交换内容
    //实际上实参指针并没有改变。
//    char *temp =a;
//    a = b;	
//    b = temp;
}

#include 
#include 


例三:
/*完美乘数:若a*b=c,且a,b,c中每个数字0~9各出现一次*/
int main(){
    int f[10],s[3];
    int n=0;
    for(int a=12;a<999;a++){       //遍历a
        int t=0;                     //当前轮 统计出现1次的数字
        for(int x=0;x<10;x++){
            f[x]=0;
        }   //当前轮 初始化10个数字次数为0
        for(int b=345;b<9999;b++){  //遍历b
            int c;                  //当前轮 计算c
            c= a*b;
            s[0] =a;s[1] =b;s[2] =c;    //当前轮 a,b,c,因为后面还有输出a,b,c,所以要复制出来
            for(int x=0;x<3;x++){
                int y =s[x];
                while(y!=0){            //数字分离
                    int t =y%10;
                    f[t]++;             //统计数字0~9
                    y/=10;
                }
            }
            for(int x=0;x<10;x++){
                if(f[x] !=1) t++;       //计数,要求每个数字都必须出现一次
            }
            if(t==0) {
                printf("%d*%d =%d", a, b, c);
                n++;                    //输出符合条件的完美乘数
            }
        }
    }
    printf("cnt:%d",n);
}
例四:
/*判断出生日期的大小
 * res = isbothsame("500236200005194417","500236200104194417");
*/
int isbothsame (char str1[19],char str2[19]){   //可以不指定,二维数组必须指定 列数
    int i=6,j=13;             // 手写,找出下标
    while (str1[i] ==str2[i]) i++; //找到不匹配的字符
    return str1[i]-str2[i];   //大:正数 等:0 小:负数
}

例五:
/*   计算:1-x+x^2/2!-x^3/3! +...+x^n/n!  */
int main(){
    float sum =1.0,temp;
    int x,n,i;
    printf("输入n,x");
    scanf("%d %d",&x,&n);
    temp =1;
    for (i =1;i<=n;i++){
        temp = temp*(-1)*x/i;
        sum+=temp;
    }
    printf("%f",sum);
}


例六:
/*创建链表 进行选择排序*/
typedef struct node{
    int data;
    struct  node *next;
}NODE;

NODE * create(){
    NODE * head,*p;
    head = (NODE *)(malloc(sizeof (NODE)*8));
    head ->data = 100;
    head ->next=NULL;
    for (int i = 1; i < 8; ++i) {
        p =(NODE *) malloc(sizeof (NODE *));
        p->data =rand()%10;
        p->next =head ->next;
        head->next =p;
    }
    p=head->next;
    while(p){
        printf("%d",p->data);
        p=p->next;
    }
    printf("\n");
    return head;
}
NODE *sort(NODE * head){
    NODE *p =(NODE *) malloc(sizeof(NODE));		//仅仅暂时连接头节点
    p->next =head;
    head =p;
    p= head->next;      //初始节点的头节点
    NODE *k =head,*q =head;
    while(p->next){     //选择循环的两层
        q = p->next;    // 新链表的第一个数已排序节点
        k =q;           //内存循环的指针
        while(q){
            if(q->data<k->data)        //寻找最小值
                k=q;
            q =q->next;
        }
        if(p->next !=k){               //交换data
            int temp = p->next->data;
            p->next->data =k->data;
            k->data =temp;
        }
        p=p->next;   //待排序的第一个数据元素
    }
    p = head;
    head =head->next;
    free(p);			//释放创建的节点
    return head;
}
void print(NODE *head){
    NODE *p;
    p=head->next;
    while(p){
        printf("%3d",p->data);
        p=p->next;
    }
    printf("\n");
}
int main(){
    NODE * head;
    head =create();
    sort(head);
    print(head);
}



例七:
/* 按快速排序的思想,求数组n个元素中第k大的数 */

void swap(int *a,int *b){
    int temp =*a;
    *a =*b;
    *b =temp;
}
int find_k(int *a,int n,int k){
    int i,j,t;
    int low =0,high =n-1;
    do{ //第一层循环,相当于在二分查找第k大的
        i=low;j=high;t=a[low];
        do{ //第二层循环,相当于以low为枢轴,划分左、右
            while(a[j]>t) j--;  //注意:如果后面有相同的数,则要求用前面大的数与其交换
            while(a[i]<=t) i++; //注意:前面的数只能是大的数
            // [2,4,6,1,3,2,8,10]->[2,2,6,1,3,4,8,10]
            // ->[2,2,1(i),6(j),3,4,8,10]->[2,2,1(j),6(i),3,4,8,10]
            if(i<j)
                swap(&a[i],&a[j]);
            else
                break;
        }while(i<j);   // 一趟排序,以a[low]为枢轴,此时i为枢轴下标

        if(i==k)
            return t;
        if(i>k)
            high =i-1;
        if(i<k)
            low =i+1;
    }while(low<high);
    return t;
}
int main(){
    int a[] ={0,1,2,3,4,4,5,6,7,8,9,12};
    int n ;
    n= find_k(a,12,10);
    printf("%d",n);
}


例八:
/* 约瑟夫环问题 */
int lastRemaining(int n, int m){
    // 反向计算,正向模拟
    int i=0;
    int alive= 0;   //最后只剩下一个人
    for(i=2;i<=n;i++){
        alive =(alive+m)%i;
    }
    printf("%d",alive);
    return alive;
 }
 
 /* 约瑟夫环问题 */
#define N 10
int main(){
    int a[N+1];       // 下标0不使用
    int *p=a,i,j,k;    // k剩余人数
    for(i=0;i<N+1;i++)  //初始化下标
        *(p+i)=i;
    p=a+1;      // p模拟移动指针
    k=N;        // 圈里剩余的人数
for(i=0;k!=1;p++){  //i为间隔计数器
        if(p >a+N)  //构成环状,循环
            p=a+1;
        if(*p!=0)
            i++;
        if(i==3)    //离场,人数减一,并将数组元素赋值为0
        {
            k =k-1;
            i=0;
            *p =0;
        }
    }
    for(i=0;i<N+1;i++){
        if(a[i]!=0)
            printf("%d\n",a[i]);
    }
}
例九
/* 创建链表,找出最大值并移动到链表尾部 */
typedef struct node{
    int data;
    struct  node *next;
}NODE;

NODE * create(){
    NODE * head,*p;
    head = (NODE *)(malloc(sizeof (NODE)*8));
    head ->data = 100;
    head ->next=NULL;
    for (int i = 1; i < 8; ++i) {
        p =(NODE *) malloc(sizeof (NODE *));
        p->data =rand()%10;
        p->next =head ->next;
        head->next =p;
    }
    p=head->next;
    while(p){
        printf("%d",p->data);
        p=p->next;
    }
    printf("\n");
    return head;
}
NODE *sort(NODE * head){
    NODE *p,*max;
    p =head->next;
    max =p;
    while(p->next){
        if (p->data >max->data)
            max =p;
        p =p->next;
    }
    int temp =p->data;
    p->data =max->data;
    max->data=temp;

    return head;
}
void print(NODE *head){
    NODE *p;
    p=head->next;
    while(p){
        printf("%3d",p->data);
        p=p->next;
    }
    printf("\n");
}
int main(){
    NODE * head;
    head =create();
    print(sort(head));
}


C语言程序设计(8)_第1张图片 C语言程序设计(8)_第2张图片

2015

例一:

void main(){
    char p[10]="abc";
    char q[] ="xyz";
    int i=0,j;
    while(*(p+i)!='\0') //计算P数组的长度,i=3
        i++;
    j=0;
    i++;    //注意,这里又移动了,i=4
    while(*(q+j)!='\0'){
        *(p+i) =*(p+j);
        j++;    //注意:这里i没有移动,所以重复修改i=4里面的字符
    }
    // p= "abc\0z"
    printf("%s",p);
}

例二:
/* 质数分解为素数乘积:90 =2*3*3*5
 * 任何数都可以分解为素数的乘积 */
void main(){
    int n;
    printf("input num:");
    scanf("%d",&n);
    printf("%d=",n);
    int i=2;
    while(n>1){
        if(n%i ==0){
            printf("%d",i);
            n/=i;
            if(n>1)     //因为除尽时,最后一定会是1,
                printf("*");
        }
        else        //否则,不是素数
            i++;
    }
}

例三:
/*将给定字符串,如”aaa111bbb222”中的数字全部提取出来,放到给定的数组中,字符串以#结尾 */
void int_find(int *a,char *p){
    int j=0;
    while(*p !='\0'){
        if(*p>='0'&&*p<='9')
            a[j++] =*p-'0';
        p++;
    }
    a[j] =-1;

}
void main(){
    int num [100],i=0;
    char str[] ="aaa111bbb222";
    int_find(num,str);
    while(num[i]!=-1) {
        printf("%d", num[i]);
        i++;
    }
}

例四:
/* 随机输入最多100个整数和浮点数,将整数按从大到小排列,浮点数按从小到大排列(浮点数排序可省略),并输出
 *  strstr() 用于判断字符串str2在字符串str1中第一次出现的位置
 *  atoi()  用于将字符串转化为int型整数  atol() 字符串转化为long
 *  atof() 用于将字符串转换为double浮点数 abs() 求int的绝对值 fabs()求double的绝对值
 *
 * */

void sort_i(int a[100] ,int len){
    int temp,i,j,max;
    for(i=0;i<len-1;i++){
        max =i;
        for(j=i+1;j<len;j++){
            if(a[j]>a[max]){
                max=j;
            }
        }
        if(max!=i){
            temp =a[i];
            a[i] =a[max];
            a[max] =temp;
        }
    }
    for(i =0;i<len;i++){
        printf("%d",a[i]);
    }
}

void sort_f(float f[100],int len){
    int temp,i,j,min;
    for(i=0;i<len-1;i++){
        min =i;
        for(j=i+1;j<len;j++){
            if(f[j]<f[min]){
                min=j;
            }
        }
        if(min!=i){
            temp =f[i];
            f[i] =f[min];
            f[min] =temp;
        }
    }
    for(i =0;i<len;i++){
        printf("%d",f[i]);
    }
    printf("\n");
}
void main(){
    float f[100];   //存放浮点数
    int i[100];     //存放整数
    int m=1,n;
    int n1=0,n2=0;
    char buff[100]; // 暂存当前输入的数据
    printf("input n:");
    scanf("%d",&n);
    while(m<=n){
        scanf("%s",buff);
        if(strstr(buff,"."))
            f[n1++] =atof(buff);
        else
            i[n2++] = atoi(buff);
        m++;
    }
    sort_i(i,n1);
    printf("\n");
    sort_f(f,n2);
}

例五:
/* 创建一个整数集合,实现集合的操作:查找、插入、删除、交集、并集
 * */

 struct set{
    int data;
    struct  set * next;
};

 void add(struct set *a, int d){
     struct set *node;
     node =(struct set*) malloc(sizeof (struct set));
     node->data = d;
     node->next =a->next;
     a->next =node;
 }
 int find(struct set *a,int d){
     struct set *p =a->next;
     while(p){
         if(p->data == d)
             return 1;
         p = p->next;
     }
     return 0;
 }

 void delete(struct set *a,int d){
     struct set * p=a->next,*pre =a;
     while (p) {
         if (p->data == d) {
             pre->next = p->next;
             free(p);
             break;
         } else {
             pre = p;
             p = p->next;
         }
     }
 }

 void union_set(struct set *la, struct set *lb){
     struct set *tempa,*tempb;
     tempa =la->next;
     while(tempa){
         tempb =lb->next;
         while(tempb){
             if(tempa->data == tempb->data){
                 printf("%d\t",tempa->data);
                 break;
             }
             tempb =tempb->next;
         }
         tempa =tempa->next;
     }
 }

 void intersection(struct set *la,struct set *lb){
     struct set *tempa =la->next,*tempb =lb->next;
     int is_find =0;
     while(tempa){
         printf("%d",tempa->data);
         tempa =tempa->next;
     }
     while(tempb){
         if(!(find(tempa,tempb->data))){
             printf("%d",tempb->data);
         }
         tempb =tempb ->next;
     }
 }

void main(){
    struct set *la,*lb;
    la = (struct set*)malloc(sizeof (struct set));
    lb =(struct set*) malloc(sizeof (struct set));
    la ->next =NULL;lb->next =NULL;
    int m,n;
    printf("分别输入链表la,lb的长度:m,n");
    scanf("%d %d",&m,&n);
    int i=1,temp;
    while(i<=m){
        scanf("%d",&temp);
        add(la,temp);
        i++;
    }
    i=1;
    while (i<=n){
        scanf("%d",&temp);
        add(lb,temp);
        i++;
    }
    printf("输出集合的并集:");
    union_set(la,lb);
    printf("输出集合的交集:");
    intersection(la,lb);
}

例六:
从提高程序的执行效率的角度,说明C语言采取哪些措施并指出原因:
1.使用指针:对于指针的理解简单点可以认为类似于汇编中的寻址方式,
正是指针的存在使C语言威力无穷。有些程序用其他语言也可以实现,但C能够更有效地实现;
有些程序无法用其它语言实现,如直接访问硬件,但C却可以。
正因为指针可以拥有类似于汇编的寻址方式,所以可以使程序更高效。
2.使用宏函数:函数和宏函数的区别就在于,宏函数占用了大量的空间,而函数占用了时间。
函数调用是要使用系统的栈来保存数据的,如果编译器里有栈检查选项,一般在函数的头会嵌入一些汇编语句对当前栈进行检查;
同时,CPU也要在函数调用时保存和恢复当前的现场,进行压栈和弹栈操作,所以,函数调用需要一些CPU时间。
而宏函数不存在这个问题。宏函数仅仅作为预先写好的代码嵌入到当前程序,不会产生函数调用,所以仅仅是占用了空间,而使程序可以高效运行。
在频繁调用同一个宏函数的时候,该现象尤其突出。
3.使用位操作:位操作可以减少除法和取模的运算。在计算机程序中数据的位是可以操作的最小数据单位,理论上可以用"位运算"来完成所有的运算和操作。
一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。
4.循环嵌套中将较长循环设为内存循环,较短循环设为外置循环,以减少cpu跨切循环层的次数,提高程序的运行效率。
5.上下文相关文法,申明先于使用,使得可以简化处理,错误提示


2016

1:do while:1,-3
2:数组a[],指针p1,p2 :8,8
3:fun§+*p :5
4:switch
5:数组求和:45
6:文件重复打开与写:B
7:fib
8:位运算和左移:12480

1:逆序输出字符串修改:长度、指针初始化、指针元素赋值

1:程序效率:if if if 与if else if else
if if if 必须判断n次,但是if else 可能会提前结束,速度更快
2:宏定义SQUARE(X) (a++)(a++) =56 =30
3:函数调用,循环修改最后一个数组元素
4:截取字符串str后m的字符
5:C语言的隐式转换
6:C语言的

例一:
int func(int *p){           //尽管形参和实参指向同一个存储单元7,但是形参p和实参p是量不同的指针
    printf("%p",&p);        //输出:000000e7a6fffbf0
    return (*p-- =3)-1;     //首先将p指向的arr[1]修改为3,计算得出返回值为2;但是形参p--指向arr[0],但是形参p没变
}
void main(){
    int arr[] ={10,7,5};
    int *p =arr+1;                  //这里指向7
    printf("%p\n",&p);            //输出:000000e7a6fffc18
    printf("%d",func(p)+ *p);   // 2+*p =2+3 =5
}
结果输出:5
例二:
/*将字符串逆序输出 修改程序*/
void main(){
    char *str="hello,world";
    char *dest,*p,*d;
    int len;
    len = strlen(str);
    dest =(char *)malloc(len); //len+1,为'\0'预留空间
    p = str[len];        // &str[len-1]
    d =dest;
    while(len-- !=0){
        d++ =p--;         //*d++ =*p--;
    }
		             	//增加结束符
    printf("%s",dest);
}
例三:
/*建立一个结构体包含学术信息(学号,成绩),使用结构体数组和而结构体指针,
 * 输入200个学生信息,按成绩由低到高排序,输出成绩最高的学生的学号和成绩 */
# define N 3
struct stu{
    char name[10];
    int score;
};
void main(){
    struct stu student[N],*p,*q,*min,temp;
    int i,j,max=0;
    for(i=0;i<N;i++){       //注意:必须指针要移动,要么用p++,要么用数组
        scanf("%s",&student[i].name);
        scanf("%d",&student[i].score);
    }
    p= student;
    //选择排序
    for(i=0;i<N-1;i++,p++){
        min =p;
        q =p+1;
        for(j=i+1;j<N;j++,q++){
            if(min->score >q->score){
                min =q;
            }
        }
        temp =*p;
        *p= *min;
        *min =temp;
    }
    p =student;
    for(i=0;i<N;i++){
        if(student[i].score>max)
            max =student[i].score;
    }
    for (i = 0; i < N; i++) {
        if(student[i].score == max)
            printf("score:%d,name:%s",student[i].score,student[i].name);
    }
}
例四:
/*逆序构建一个单向链表*/
#define  N 3
struct list{
    int data;
    struct list *next;
};

void main(){
    struct  list *head,*p;
    int n =N;
    head =(struct list *) malloc(sizeof (struct list));
    head ->next =NULL;
    while(n--!=0){
        p =(struct list *) malloc(sizeof (struct list));
        scanf("%d",&p->data);
        p->next =head->next;
        head->next=p;
    }
    p =head->next;
    while(p){
        printf("%d\t",p->data);
        p=p->next;
    }
}



2017

1:do while输出1,-3
2:数组a[],指针p1,p2
3:fun§+*p,*p不变实参
4:fib
5:12480数字位运算和左移
6:
7:数组求和45
8:结构体数组引用

1:字符串复制修改:长度,指针初始化,指针复位,结束符
2:文件指针p1,p2修改:内存泄露、重复free
3:交换字符串修改:改用数组、strcpy()
4:字符串复制与指针修改:常量不能改,长度不足

1:素数筛选
2:C语言效率
3:C语言的单词类型(关键字、标识符、运算符、分隔符、常量、注释符…)
4:表格

1:“UESTC\0z”
2:找出1~100内的数和它的平方,同时包含输入整数d
3:截取str中第m个之后的字符
4:C语言的四种隐式类型转化
6:C语言效率(指针、宏定义、位运算、寄存器变量、不对数组做下标检查、无布尔类型、a&&b短路原则、合理malloc/free动态分配存储空间)
7:表格
8:1-x+x^2/2!+
9:完美乘数

1:快排找K小
2:在str1中删除str2中出现的字符
3:链表逆序(头插法,注意节点开始位置)
4:互满数
5:链表L1、L2交集
6:整数降序,浮点数升序

例一:
void main(){
    char pa[] ="ABCDE";
    char *pb ="efg";
    pb[1] ='a';         //字符串常量,不能修改,但是能读取
//    printf("%c",pb[1]);
    pb= pa;
    strcpy(pa,"QBCDEFGH"); //pa内存不够
    pb="D";
//    printf("%s",pb);
}

例二:如何进行浮点数四舍五入
float fun(float a,int n){
    //四舍五入算法:保留n位小数,就是处理n+1位+5的结果
    //先放大10^(n+1)倍,计算+5后强转int进行舍入
    //最后缩小10^(n)倍,强转为float
    int tmp ;
    tmp =(int)(a* pow(10,n+1)+5)/10;
    printf("%f",(float)tmp/ pow(10,n));
    return (float)tmp/ pow(10,n);
}
例三:
#include 
/*Eratasheenes 筛选法:求200以内的素数 */
void main(){
    int prime[201] ={0};            //因为一个合数必定存在一个<=sqrt(x)的因数,如果不存在,则为素数
    int d,k,i;
    for(d =2;d<=sqrt(200);d++){ // 已知素数,反推删除合数
        if(prime[d] ==0)
            for( k=2*d;k<=200;k=k+d)
                prime[k] =1;       // 1:删除2的倍数 2:删除3的倍数 3:删除5的倍数
    }
    k=0;
    for(i=2;i<=200;i++)
        if(prime[i]==0){
        printf("%d\t", i);  //输出下标
            k++;
            if(k%5 ==0)
                printf("\n");
        }
}

例四:
/*互满数:每个数它的所有约数的和正好等于对方 */
#define N 3000
int factor(int j){
    int k[40];
    int n=0,s=0;
    for(int i=1;i<j;i++){   //求不包含自己的因数
        if(j%i==0){
            k[n++] =i;
        }
    }
    for(int i=0;i<n;i++){
        s +=k[i];
    }
    return s;
}
void main(){
    int s1,s2;
    for(int m=2;m<N;m++){
        s1= factor(m);
        for(int n=m+1;n<N;n++){
            s2= factor(n);
            if((s1==n)&&(s2==m))
                printf("%d 和%d是互满数:",m,n);
        }
    }
}
/*220 和284是互满数:
1184 和1210是互满数:
2620 和2924是互满数:*/

2018

1:数组a[],指针p1,p2输出
2:Fib
3:结构体数组引用

1:字符串逆序修改:长度、循环控制、结束符

1:找出1~100内的数和它的平方,同时包含输入整数d

1:C语言的四种隐式类型转换(算术运算、赋值运算、实参形参、函数返回值)
2:C语言提高效率(指针、宏定义、位运算、嵌入汇编)
3:数组越界产生的后果:

  • C 语言并不检验数组边界,数组的两端都有可能越界,从而使其他变量的数据甚至程序代码被破坏。
  • 程序结果不正确
  • 程序崩溃,造成死循环浪费CPU资源等
  • 没有影响
  • 不安全,存在攻击者漏洞
    内存泄露:分配了内存而没有释放,逐渐耗尽内存资源,导致系统崩溃
    内存越界: 打个比方 就是你有一个 500ml 的水瓶,然后你倒在瓶里的水大于 500ml 那个多余的就会流出来

4:数组

1:快排找第K小
2:存储区表格(常量区、全局区、main、func)
3:素数筛选求200以内
4:凯撒加密
5:逆序构建双向链表

2019

  1. 改错题
    1:数组指针未分配:malloc
    2:冒泡排序,大数已排序在尾部,i=0,j=0开始

  2. 阅读理解
    1:辗转gcd
    2:字符串a中插入字符串b
    3:三个不同函数在随机生成1~100随机数的区别:
    函数功能,时间复杂度计算,优缺点
    4:乱序数组求中位数,程序改进:
    排序过程中swap太多;float数直接比较大小;偶数长度求中位数没有取2个数的均值;变量类型错误

  3. 填空题:
    1:对student结构体排序
    2:在字符数组str[]中,从第n个开始删除长度为len的字符
    3:实现链表L,第m个到第n个节点的逆序
    4:找通项,求和

  4. 简答题
    1:C语言编程实现网络数据传输,使用TCP/IP协议还是HTTP协议
    WinSock通讯的所有数据传输,都是通过套接字来完成的,套接字包含了两个信息,一个是IP地址,一个是Port端口号,使用这两个信息,就可以确定网络中的任何一个通讯节点。
    使用Socket进行网络通信的过程:
    ① 服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户的连接请求。
    ② 客户程序根据服务器程序所在的主机和端口号发出连接请求。
    ③ 如果一切正常,服务器接受连接请求。并获得一个新的绑定到不同端口地址的套接字。
    ④ 客户和服务器通过读、写套接字进行通讯。

    2:怎么对客户定制的软件进行测试
    按功能分:黑盒测试(功能性:等价划分、边界值分析、错误推测)、白盒测试(结构性:语句覆盖、分支覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖、点覆盖、边覆盖、路径覆盖)
    按时间分:单元测试、子系统测试、系统测试、验收测试

  5. 编程
    1:一个循环数组大小为n,有序,但不知道向哪个方向有序,也不知道起点在哪里,设计算法,找出数组里的最小值,要求时间复杂度为O(logn),超时不给分

你可能感兴趣的:(c语言,数据结构,算法)